summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorglisse <glisse@636b058d-ea47-450e-bf9e-a15bfbe3eedb>2016-12-12 05:43:06 +0000
committerglisse <glisse@636b058d-ea47-450e-bf9e-a15bfbe3eedb>2016-12-12 05:43:06 +0000
commitad6a64ad5a4f4121410250021eda0904eb9c718c (patch)
treefdad2e783a79b388cde1826e3b344d8977d1183a /src
parentf9a32a464156dd61b444f0e70c8342642363e8ea (diff)
parentf0e5330a88f9e89a887769ab79f6db6dd4e1c35a (diff)
Merge from trunk.
git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/qt5@1848 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: c8e1376894207c8c08896f750f71c115e07f6d95
Diffstat (limited to 'src')
-rw-r--r--src/Alpha_complex/concept/Simplicial_complex_for_alpha.h89
-rw-r--r--src/Alpha_complex/doc/Intro_alpha_complex.h176
-rw-r--r--src/Alpha_complex/doc/alpha_complex_doc.ipe296
-rw-r--r--src/Alpha_complex/doc/alpha_complex_doc.pngbin0 -> 18720 bytes
-rw-r--r--src/Alpha_complex/doc/alpha_complex_doc_420.ipe514
-rw-r--r--src/Alpha_complex/doc/alpha_complex_doc_420.pngbin0 -> 80794 bytes
-rw-r--r--src/Alpha_complex/doc/alpha_complex_representation.ipe321
-rw-r--r--src/Alpha_complex/doc/alpha_complex_representation.pngbin0 -> 14606 bytes
-rw-r--r--src/Alpha_complex/example/Alpha_complex_from_off.cpp63
-rw-r--r--src/Alpha_complex/example/Alpha_complex_from_points.cpp68
-rw-r--r--src/Alpha_complex/example/CMakeLists.txt33
-rw-r--r--src/Alpha_complex/example/alphaoffreader_for_doc_32.txt22
-rw-r--r--src/Alpha_complex/example/alphaoffreader_for_doc_60.txt27
-rw-r--r--src/Alpha_complex/include/gudhi/Alpha_complex.h434
-rw-r--r--src/Alpha_complex/test/Alpha_complex_unit_test.cpp286
-rw-r--r--src/Alpha_complex/test/CMakeLists.txt32
-rw-r--r--src/Alpha_complex/test/README12
-rw-r--r--src/Bitmap_cubical_complex/doc/Cubical_complex_representation.ipe732
-rw-r--r--src/Bitmap_cubical_complex/doc/Cubical_complex_representation.pngbin0 -> 19167 bytes
-rw-r--r--src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h159
-rw-r--r--src/Bitmap_cubical_complex/doc/bitmapAllCubes.pngbin0 -> 38944 bytes
-rw-r--r--src/Bitmap_cubical_complex/doc/exampleBitmap.pngbin0 -> 2549 bytes
-rw-r--r--src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp72
-rw-r--r--src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp74
-rw-r--r--src/Bitmap_cubical_complex/example/CMakeLists.txt26
-rw-r--r--src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp83
-rw-r--r--src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h595
-rw-r--r--src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h144
-rw-r--r--src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h817
-rw-r--r--src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h308
-rw-r--r--src/Bitmap_cubical_complex/test/Bitmap_test.cpp1378
-rw-r--r--src/Bitmap_cubical_complex/test/CMakeLists.txt24
-rw-r--r--src/Bottleneck/example/CMakeLists.txt2
-rw-r--r--src/Bottleneck/test/CMakeLists.txt6
-rw-r--r--src/CMakeLists.txt114
-rw-r--r--src/Contraction/doc/sphere_contraction_representation.pngbin0 -> 44839 bytes
-rw-r--r--src/Contraction/example/CMakeLists.txt8
-rw-r--r--src/Contraction/example/Garland_heckbert.cpp20
-rw-r--r--src/Contraction/example/Garland_heckbert/Error_quadric.h364
-rw-r--r--src/Contraction/example/Rips_contraction.cpp7
-rw-r--r--src/Contraction/include/gudhi/Contraction/policies/Link_condition_valid_contraction.h2
-rw-r--r--src/Contraction/include/gudhi/Edge_contraction.h15
-rw-r--r--src/Contraction/include/gudhi/Skeleton_blocker_contractor.h15
-rw-r--r--src/Doxyfile68
-rw-r--r--src/GudhUI/CMakeLists.txt24
-rw-r--r--src/GudhUI/gui/MainWindow.h3
-rw-r--r--src/GudhUI/gui/MenuEdgeContraction.ui236
-rw-r--r--src/GudhUI/gui/gudhui.cpp76
-rw-r--r--src/GudhUI/model/Complex_typedefs.h2
-rw-r--r--src/GudhUI/model/Model.h18
-rw-r--r--src/GudhUI/utils/Bar_code_persistence.h90
-rw-r--r--src/GudhUI/utils/Edge_contractor.h2
-rw-r--r--src/GudhUI/utils/Furthest_point_epsilon_net.h2
-rw-r--r--src/GudhUI/utils/Is_manifold.h2
-rw-r--r--src/GudhUI/utils/K_nearest_builder.h10
-rw-r--r--src/GudhUI/utils/Persistence_compute.h14
-rw-r--r--src/GudhUI/view/FirstCoordProjector.h8
-rw-r--r--src/GudhUI/view/Viewer.h234
-rw-r--r--src/GudhUI/view/Viewer_instructor.cpp2
-rw-r--r--src/GudhUI/view/Viewer_instructor.h228
-rw-r--r--src/Hasse_complex/include/gudhi/Hasse_complex.h44
-rw-r--r--src/Persistent_cohomology/concept/FilteredComplex.h17
-rw-r--r--src/Persistent_cohomology/doc/3DTorus_poch.pngbin0 -> 40164 bytes
-rw-r--r--src/Persistent_cohomology/doc/Intro_persistent_cohomology.h206
-rw-r--r--src/Persistent_cohomology/example/CMakeLists.txt100
-rw-r--r--src/Persistent_cohomology/example/README108
-rw-r--r--src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp (renamed from src/Persistent_cohomology/example/alpha_shapes_persistence.cpp)52
-rw-r--r--src/Persistent_cohomology/example/alpha_complex_persistence.cpp122
-rw-r--r--src/Persistent_cohomology/example/custom_persistence_sort.cpp137
-rw-r--r--src/Persistent_cohomology/example/performance_rips_persistence.cpp83
-rw-r--r--src/Persistent_cohomology/example/periodic_alpha_complex_3d_persistence.cpp313
-rw-r--r--src/Persistent_cohomology/example/persistence_from_file.cpp2
-rw-r--r--src/Persistent_cohomology/example/plain_homology.cpp95
-rw-r--r--src/Persistent_cohomology/example/rips_multifield_persistence.cpp5
-rw-r--r--src/Persistent_cohomology/example/rips_persistence.cpp8
-rw-r--r--src/Persistent_cohomology/example/rips_persistence_via_boundary_matrix.cpp180
-rw-r--r--src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h298
-rw-r--r--src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Multi_field.h3
-rw-r--r--src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Persistent_cohomology_column.h1
-rw-r--r--src/Persistent_cohomology/test/CMakeLists.txt26
-rw-r--r--src/Persistent_cohomology/test/betti_numbers_unit_test.cpp234
-rw-r--r--src/Persistent_cohomology/test/persistent_cohomology_unit_test.cpp45
-rw-r--r--src/Simplex_tree/concept/SimplexKey.h2
-rw-r--r--src/Simplex_tree/concept/SimplexTreeOptions.h10
-rw-r--r--src/Simplex_tree/doc/Intro_simplex_tree.h85
-rw-r--r--src/Simplex_tree/doc/Simplex_tree_representation.pngbin0 -> 39217 bytes
-rw-r--r--src/Simplex_tree/example/CMakeLists.txt29
-rw-r--r--src/Simplex_tree/example/README4
-rw-r--r--src/Simplex_tree/example/example_alpha_shapes_3_simplex_tree_from_off_file.cpp (renamed from src/Simplex_tree/example/simplex_tree_from_alpha_shapes_3.cpp)31
-rw-r--r--src/Simplex_tree/include/gudhi/Simplex_tree.h289
-rw-r--r--src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_iterators.h84
-rw-r--r--src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_siblings.h6
-rw-r--r--src/Simplex_tree/test/CMakeLists.txt9
-rw-r--r--src/Simplex_tree/test/simplex_tree_unit_test.cpp487
-rw-r--r--src/Skeleton_blocker/concept/SkeletonBlockerDS.h218
-rw-r--r--src/Skeleton_blocker/concept/SkeletonBlockerGeometricDS.h122
-rw-r--r--src/Skeleton_blocker/example/CMakeLists.txt2
-rw-r--r--src/Skeleton_blocker/example/Skeleton_blocker_from_simplices.cpp40
-rw-r--r--src/Skeleton_blocker/example/Skeleton_blocker_iteration.cpp17
-rw-r--r--src/Skeleton_blocker/example/Skeleton_blocker_link.cpp30
-rw-r--r--src/Skeleton_blocker/include/gudhi/Skeleton_blocker.h229
-rw-r--r--src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_complex_visitor.h67
-rw-r--r--src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_link_superior.h26
-rw-r--r--src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_off_io.h25
-rw-r--r--src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_simple_geometric_traits.h19
-rw-r--r--src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_simple_traits.h44
-rw-r--r--src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_simplex.h22
-rw-r--r--src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_sub_complex.h81
-rw-r--r--src/Skeleton_blocker/include/gudhi/Skeleton_blocker/internal/Top_faces.h11
-rw-r--r--src/Skeleton_blocker/include/gudhi/Skeleton_blocker/internal/Trie.h49
-rw-r--r--src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_blockers_iterators.h13
-rw-r--r--src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_edges_iterators.h9
-rw-r--r--src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_iterators.h2
-rw-r--r--src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_simplices_iterators.h135
-rw-r--r--src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_triangles_iterators.h38
-rw-r--r--src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_vertices_iterators.h18
-rw-r--r--src/Skeleton_blocker/include/gudhi/Skeleton_blocker_complex.h256
-rw-r--r--src/Skeleton_blocker/include/gudhi/Skeleton_blocker_geometric_complex.h21
-rw-r--r--src/Skeleton_blocker/include/gudhi/Skeleton_blocker_link_complex.h89
-rw-r--r--src/Skeleton_blocker/include/gudhi/Skeleton_blocker_simplifiable_complex.h115
-rw-r--r--src/Skeleton_blocker/test/CMakeLists.txt33
-rw-r--r--src/Skeleton_blocker/test/TestGeometricComplex.cpp120
-rw-r--r--src/Skeleton_blocker/test/TestSimplifiable.cpp356
-rw-r--r--src/Skeleton_blocker/test/TestSkeletonBlockerComplex.cpp952
-rw-r--r--src/Skeleton_blocker/test/test_skeleton_blocker_complex.cpp837
-rw-r--r--src/Skeleton_blocker/test/test_skeleton_blocker_geometric_complex.cpp125
-rw-r--r--src/Skeleton_blocker/test/test_skeleton_blocker_simplifiable.cpp360
-rw-r--r--src/Spatial_searching/doc/Intro_spatial_searching.h62
-rw-r--r--src/Spatial_searching/example/CMakeLists.txt13
-rw-r--r--src/Spatial_searching/example/example_spatial_searching.cpp52
-rw-r--r--src/Spatial_searching/include/gudhi/Kd_tree_search.h264
-rw-r--r--src/Spatial_searching/test/CMakeLists.txt25
-rw-r--r--src/Spatial_searching/test/test_Kd_tree_search.cpp112
-rw-r--r--src/Subsampling/doc/Intro_subsampling.h70
-rw-r--r--src/Subsampling/example/CMakeLists.txt20
-rw-r--r--src/Subsampling/example/example_choose_n_farthest_points.cpp27
-rw-r--r--src/Subsampling/example/example_pick_n_random_points.cpp27
-rw-r--r--src/Subsampling/example/example_sparsify_point_set.cpp27
-rw-r--r--src/Subsampling/include/gudhi/choose_n_farthest_points.h132
-rw-r--r--src/Subsampling/include/gudhi/pick_n_random_points.h84
-rw-r--r--src/Subsampling/include/gudhi/sparsify_point_set.h115
-rw-r--r--src/Subsampling/test/CMakeLists.txt38
-rw-r--r--src/Subsampling/test/test_choose_n_farthest_points.cpp103
-rw-r--r--src/Subsampling/test/test_pick_n_random_points.cpp69
-rw-r--r--src/Subsampling/test/test_sparsify_point_set.cpp55
-rw-r--r--src/Tangential_complex/benchmark/CMakeLists.txt26
-rw-r--r--src/Tangential_complex/benchmark/RIB_exporter.h269
-rw-r--r--src/Tangential_complex/benchmark/XML_exporter.h207
-rw-r--r--src/Tangential_complex/benchmark/benchmark_script.txt221
-rw-r--r--src/Tangential_complex/benchmark/benchmark_tc.cpp785
-rw-r--r--src/Tangential_complex/doc/Intro_tangential_complex.h119
-rw-r--r--src/Tangential_complex/doc/tc_example_01.pngbin0 -> 20323 bytes
-rw-r--r--src/Tangential_complex/doc/tc_example_02.pngbin0 -> 36017 bytes
-rw-r--r--src/Tangential_complex/doc/tc_example_03.pngbin0 -> 62990 bytes
-rw-r--r--src/Tangential_complex/doc/tc_example_05.pngbin0 -> 36032 bytes
-rw-r--r--src/Tangential_complex/doc/tc_example_06.pngbin0 -> 37195 bytes
-rw-r--r--src/Tangential_complex/doc/tc_example_07.pngbin0 -> 49399 bytes
-rw-r--r--src/Tangential_complex/doc/tc_example_07_after.pngbin0 -> 50132 bytes
-rw-r--r--src/Tangential_complex/doc/tc_example_07_before.pngbin0 -> 48898 bytes
-rw-r--r--src/Tangential_complex/doc/tc_example_08.pngbin0 -> 63636 bytes
-rw-r--r--src/Tangential_complex/doc/tc_example_09.pngbin0 -> 35453 bytes
-rw-r--r--src/Tangential_complex/doc/tc_examples.pngbin0 -> 150776 bytes
-rw-r--r--src/Tangential_complex/example/CMakeLists.txt23
-rw-r--r--src/Tangential_complex/example/example_basic.cpp46
-rw-r--r--src/Tangential_complex/example/example_with_perturb.cpp53
-rw-r--r--src/Tangential_complex/include/gudhi/Tangential_complex.h2279
-rw-r--r--src/Tangential_complex/include/gudhi/Tangential_complex/Simplicial_complex.h539
-rw-r--r--src/Tangential_complex/include/gudhi/Tangential_complex/config.h (renamed from src/common/include/gudhi/Utils.h)43
-rw-r--r--src/Tangential_complex/include/gudhi/Tangential_complex/utilities.h195
-rw-r--r--src/Tangential_complex/test/CMakeLists.txt31
-rw-r--r--src/Tangential_complex/test/test_tangential_complex.cpp70
-rw-r--r--src/Witness_complex/concept/Simplicial_complex_for_witness.h87
-rw-r--r--src/Witness_complex/doc/Witness_complex_doc.h42
-rw-r--r--src/Witness_complex/doc/Witness_complex_representation.pngbin0 -> 48899 bytes
-rw-r--r--src/Witness_complex/doc/bench_Cy8.pngbin0 -> 15254 bytes
-rw-r--r--src/Witness_complex/doc/bench_sphere.pngbin0 -> 16614 bytes
-rw-r--r--src/Witness_complex/example/CMakeLists.txt17
-rw-r--r--src/Witness_complex/example/generators.h147
-rw-r--r--src/Witness_complex/example/witness_complex_from_file.cpp83
-rw-r--r--src/Witness_complex/example/witness_complex_sphere.cpp92
-rw-r--r--src/Witness_complex/include/gudhi/Construct_closest_landmark_table.h90
-rw-r--r--src/Witness_complex/include/gudhi/Witness_complex.h265
-rw-r--r--src/Witness_complex/test/CMakeLists.txt30
-rw-r--r--src/Witness_complex/test/simple_witness_complex.cpp59
-rw-r--r--src/Witness_complex/test/witness_complex_points.cpp58
-rw-r--r--src/cmake/modules/FindQGLViewer.cmake2
-rw-r--r--src/cmake/modules/FindTBB.cmake425
-rw-r--r--src/cmake/modules/GUDHI_doxygen_target.txt11
-rw-r--r--src/cmake/modules/GUDHI_user_version_target.txt115
-rw-r--r--src/cmake/modules/UseTBB.cmake6
-rw-r--r--src/common/doc/Gudhi_banner.jpgbin34437 -> 0 bytes
-rw-r--r--src/common/doc/Gudhi_banner.pngbin0 -> 34877 bytes
-rw-r--r--src/common/doc/footer.html29
-rw-r--r--src/common/doc/header.html83
-rw-r--r--src/common/doc/main_page.h422
-rw-r--r--src/common/doc/stylesheet.css1367
-rw-r--r--src/common/example/CMakeLists.txt21
-rw-r--r--src/common/example/cgal3Doffreader_result.txt8
-rw-r--r--src/common/example/cgaloffreader_result.txt7
-rw-r--r--src/common/example/example_CGAL_3D_points_off_reader.cpp41
-rw-r--r--src/common/example/example_CGAL_points_off_reader.cpp46
-rw-r--r--src/common/example/example_vector_double_points_off_reader.cpp41
-rw-r--r--src/common/include/gudhi/Clock.h48
-rw-r--r--src/common/include/gudhi/Debug_utils.h57
-rw-r--r--src/common/include/gudhi/Off_reader.h49
-rw-r--r--src/common/include/gudhi/Points_3D_off_io.h202
-rw-r--r--src/common/include/gudhi/Points_off_io.h183
-rw-r--r--src/common/include/gudhi/Test.h105
-rw-r--r--src/common/include/gudhi/allocator.h55
-rw-r--r--src/common/include/gudhi/console_color.h97
-rw-r--r--src/common/include/gudhi/distance_functions.h4
-rw-r--r--src/common/include/gudhi/random_point_generators.h477
-rw-r--r--src/common/include/gudhi/reader_utils.h6
-rw-r--r--src/common/include/gudhi_patches/CGAL/Convex_hull.h56
-rw-r--r--src/common/include/gudhi_patches/CGAL/Delaunay_triangulation.h933
-rw-r--r--src/common/include/gudhi_patches/CGAL/Epeck_d.h53
-rw-r--r--src/common/include/gudhi_patches/CGAL/Epick_d.h71
-rw-r--r--src/common/include/gudhi_patches/CGAL/IO/Triangulation_off_ostream.h320
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_LA_base.h177
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_LA_functors.h344
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_base.h40
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_change_FT.h117
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_complete.h33
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_filter_K.h79
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_filter_NT.h93
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_per_dimension.h33
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_static_filters.h95
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Coaffine.h330
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Define_kernel_types.h50
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Dimension_base.h49
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Filtered_predicate2.h137
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/KernelD_converter.h199
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Kernel_2_interface.h104
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Kernel_3_interface.h102
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Kernel_d_interface.h298
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Kernel_object_converter.h134
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/LA_eigen/LA.h175
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/LA_eigen/constructors.h162
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Lazy_cartesian.h188
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Aff_transformation.h59
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Hyperplane.h159
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Iso_box.h88
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Line.h66
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Ray.h66
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Segment.h121
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Sphere.h132
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Weighted_point.h205
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/array.h165
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/avx4.h213
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_iterator_to_points_from_iterator_to_vectors.h76
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_iterator_to_points_from_points.h211
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_iterator_to_vectors_from_vectors.h201
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_points_from_vectors.h164
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_vectors_small_dim.h58
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_vectors_small_dim_internal.h164
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/mix.h46
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/sse2.h145
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/v2int.h181
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/vector.h167
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h305
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Hyperplane_d.h131
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Point_d.h284
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Ref_count_obj.h120
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Segment_d.h133
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Sphere_d.h130
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Vector_d.h266
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Weighted_point_d.h129
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/function_objects_cartesian.h1355
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/functor_properties.h40
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/functor_tags.h363
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/static_int.h61
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/store_kernel.h104
-rw-r--r--src/common/include/gudhi_patches/CGAL/NewKernel_d/utils.h306
-rw-r--r--src/common/include/gudhi_patches/CGAL/Regular_triangulation.h1169
-rw-r--r--src/common/include/gudhi_patches/CGAL/Regular_triangulation_traits_adapter.h288
-rw-r--r--src/common/include/gudhi_patches/CGAL/TDS_full_cell_default_storage_policy.h99
-rw-r--r--src/common/include/gudhi_patches/CGAL/TDS_full_cell_mirror_storage_policy.h71
-rw-r--r--src/common/include/gudhi_patches/CGAL/Triangulation.h1424
-rw-r--r--src/common/include/gudhi_patches/CGAL/Triangulation_data_structure.h1603
-rw-r--r--src/common/include/gudhi_patches/CGAL/Triangulation_ds_full_cell.h311
-rw-r--r--src/common/include/gudhi_patches/CGAL/Triangulation_ds_vertex.h154
-rw-r--r--src/common/include/gudhi_patches/CGAL/Triangulation_face.h111
-rw-r--r--src/common/include/gudhi_patches/CGAL/Triangulation_full_cell.h148
-rw-r--r--src/common/include/gudhi_patches/CGAL/Triangulation_vertex.h128
-rw-r--r--src/common/include/gudhi_patches/CGAL/argument_swaps.h88
-rw-r--r--src/common/include/gudhi_patches/CGAL/determinant_of_vectors.h117
-rw-r--r--src/common/include/gudhi_patches/CGAL/internal/Combination_enumerator.h148
-rw-r--r--src/common/include/gudhi_patches/CGAL/internal/Static_or_dynamic_array.h116
-rw-r--r--src/common/include/gudhi_patches/CGAL/internal/Triangulation/Dummy_TDS.h49
-rw-r--r--src/common/include/gudhi_patches/CGAL/internal/Triangulation/Triangulation_ds_iterators.h154
-rw-r--r--src/common/include/gudhi_patches/CGAL/internal/Triangulation/utilities.h154
-rw-r--r--src/common/include/gudhi_patches/CGAL/iterator_from_indices.h75
-rw-r--r--src/common/include/gudhi_patches/CGAL/transforming_iterator.h123
-rw-r--r--src/common/include/gudhi_patches/CGAL/transforming_pair_iterator.h127
-rw-r--r--src/common/include/gudhi_patches/CGAL/typeset.h117
-rw-r--r--src/common/test/CMakeLists.txt24
-rw-r--r--src/common/test/README14
-rw-r--r--src/common/test/dtoffrw_alphashapedoc_result.off7
-rw-r--r--src/common/test/test_points_off_reader.cpp73
-rw-r--r--src/debian/changelog5
-rw-r--r--src/debian/compat1
-rw-r--r--src/debian/control26
-rw-r--r--src/debian/copyright28
-rw-r--r--src/debian/docs2
-rwxr-xr-xsrc/debian/rules28
-rw-r--r--src/debian/source/format1
306 files changed, 41183 insertions, 3617 deletions
diff --git a/src/Alpha_complex/concept/Simplicial_complex_for_alpha.h b/src/Alpha_complex/concept/Simplicial_complex_for_alpha.h
new file mode 100644
index 00000000..2b8bff94
--- /dev/null
+++ b/src/Alpha_complex/concept/Simplicial_complex_for_alpha.h
@@ -0,0 +1,89 @@
+/* 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) 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 CONCEPT_ALPHA_COMPLEX_SIMPLICIAL_COMPLEX_FOR_ALPHA_H_
+#define CONCEPT_ALPHA_COMPLEX_SIMPLICIAL_COMPLEX_FOR_ALPHA_H_
+
+namespace Gudhi {
+
+namespace alpha_complex {
+
+/** \brief The concept SimplicialComplexForAlpha describes the requirements for a type to implement a simplicial
+ * complex, that can be created from a `Alpha_complex`.
+ */
+struct SimplicialComplexForAlpha {
+ /** Handle to specify a simplex. */
+ typedef unspecified Simplex_handle;
+ /** Handle to specify a vertex. Must be a non-negative integer. */
+ typedef unspecified Vertex_handle;
+ /** Handle to specify the simplex filtration value. */
+ typedef unspecified Filtration_value;
+
+ /** Returns the number of vertices in the simplicial complex. */
+ std::size_t num_vertices();
+
+ /** Sets the simplicial complex dimension. */
+ void set_dimension(int dimension);
+
+ /** Gets the 'simplex' dimension. */
+ int dimension(Simplex_handle simplex);
+
+ /** Assigns the 'simplex' with the given 'filtration' value. */
+ int assign_filtration(Simplex_handle simplex, Filtration_value filtration);
+
+ /** \brief Inserts a simplex with vertices from a given simplex (represented by a vector of Vertex_handle) in the
+ * simplicial complex with the given 'filtration' value. */
+ void insert_simplex_and_subfaces(std::vector<Vertex_handle> const & vertex_range, Filtration_value filtration);
+
+ /** Browses the simplicial complex to make the filtration non-decreasing. */
+ void make_filtration_non_decreasing();
+
+ /** Prune the simplicial complex above 'filtration' value given as parameter. */
+ void prune_above_filtration(Filtration_value filtration);
+
+ /** \brief Iterator over vertices of a simplex.
+ *
+ * 'value type' must be 'Vertex_handle'.*/
+ typedef unspecified Simplex_vertex_range;
+
+ /** \brief Returns a range over vertices of a given
+ * simplex. */
+ Simplex_vertex_range simplex_vertex_range(Simplex_handle const & simplex);
+
+ /** \brief Iterator over the boundaries of the complex, in an arbitrary order.
+ *
+ * 'value_type' must be 'Simplex_handle'.*/
+ typedef unspecified Boundary_simplex_range;
+
+ /** \brief Returns a range over boundaries of a given simplex. */
+ Boundary_simplex_range boundary_simplex_range(Simplex_handle const & simplex);
+
+ /** \brief Return type of an insertion of a simplex
+ */
+ typedef unspecified Insertion_result_type;
+};
+
+} // namespace alpha_complex
+
+} // namespace Gudhi
+
+#endif // CONCEPT_ALPHA_COMPLEX_SIMPLICIAL_COMPLEX_FOR_ALPHA_H_
diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h
new file mode 100644
index 00000000..3ffdae7f
--- /dev/null
+++ b/src/Alpha_complex/doc/Intro_alpha_complex.h
@@ -0,0 +1,176 @@
+/* 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
+ *
+ * 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 DOC_ALPHA_COMPLEX_INTRO_ALPHA_COMPLEX_H_
+#define DOC_ALPHA_COMPLEX_INTRO_ALPHA_COMPLEX_H_
+
+// needs namespace for Doxygen to link on classes
+namespace Gudhi {
+// needs namespace for Doxygen to link on classes
+namespace alpha_complex {
+
+/** \defgroup alpha_complex Alpha complex
+ *
+ * \author Vincent Rouvreau
+ *
+ * @{
+ *
+ * \section definition Definition
+ *
+ * Alpha_complex is a <a target="_blank" href="https://en.wikipedia.org/wiki/Simplicial_complex">simplicial complex</a>
+ * constructed from the finite cells of a Delaunay Triangulation.
+ *
+ * The filtration value of each simplex is computed as the square of the circumradius of the simplex if the
+ * circumsphere is empty (the simplex is then said to be Gabriel), and as the minimum of the filtration
+ * values of the codimension 1 cofaces that make it not Gabriel otherwise.
+ *
+ * All simplices that have a filtration value strictly greater than a given alpha squared value are not inserted into
+ * the complex.
+ *
+ * \image html "alpha_complex_representation.png" "Alpha-complex representation"
+ *
+ * Alpha_complex is constructing a <a target="_blank"
+ * href="http://doc.cgal.org/latest/Triangulation/index.html#Chapter_Triangulations">Delaunay Triangulation</a>
+ * \cite cgal:hdj-t-15b from <a target="_blank" href="http://www.cgal.org/">CGAL</a> (the Computational Geometry
+ * Algorithms Library \cite cgal:eb-15b) and is able to create a `SimplicialComplexForAlpha`.
+ *
+ * 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 parameter.
+ *
+ * \remark When the simplicial complex is constructed with an infinite value of alpha, the complex is a Delaunay
+ * complex.
+ *
+ * \section pointsexample Example from points
+ *
+ * This example builds the Delaunay triangulation from the given points in a 2D static kernel, and creates a
+ * `Simplex_tree` with it.
+ *
+ * Then, it is asked to display information about the simplicial complex.
+ *
+ * \include Alpha_complex/Alpha_complex_from_points.cpp
+ *
+ * When launching:
+ *
+ * \code $> ./alphapoints
+ * \endcode
+ *
+ * the program output is:
+ *
+ * \include Alpha_complex/alphaoffreader_for_doc_60.txt
+ *
+ * \section createcomplexalgorithm Create complex algorithm
+ *
+ * \subsection datastructure Data structure
+ *
+ * In order to create the simplicial complex, first, it is built from the cells of the Delaunay Triangulation.
+ * The filtration values are set to NaN, which stands for unknown value.
+ *
+ * In example, :
+ * \image html "alpha_complex_doc.png" "Simplicial complex structure construction example"
+ *
+ * \subsection filtrationcomputation Filtration value computation algorithm
+ *
+ * \f{algorithm}{
+ * \caption{Filtration value computation algorithm}\label{alpha}
+ * \begin{algorithmic}
+ * \For{i : dimension $\rightarrow$ 0}
+ * \ForAll{$\sigma$ of dimension i}
+ * \If {filtration($\sigma$) is NaN}
+ * \State filtration($\sigma$) = $\alpha^2(\sigma)$
+ * \EndIf
+ * \ForAll{$\tau$ face of $\sigma$} \Comment{propagate alpha filtration value}
+ * \If {filtration($\tau$) is not NaN}
+ * \State filtration($\tau$) = min (filtration($\tau$), filtration($\sigma$))
+ * \Else
+ * \If {$\tau$ is not Gabriel for $\sigma$}
+ * \State filtration($\tau$) = filtration($\sigma$)
+ * \EndIf
+ * \EndIf
+ * \EndFor
+ * \EndFor
+ * \EndFor
+ * \State make\_filtration\_non\_decreasing()
+ * \State prune\_above\_filtration()
+ * \end{algorithmic}
+ * \f}
+ *
+ * \subsubsection dimension2 Dimension 2
+ *
+ * From the example above, it means the algorithm looks into each triangle ([0,1,2], [0,2,4], [1,2,3], ...),
+ * computes the filtration value of the triangle, and then propagates the filtration value as described
+ * here :
+ * \image html "alpha_complex_doc_420.png" "Filtration value propagation example"
+ *
+ * \subsubsection dimension1 Dimension 1
+ *
+ * Then, the algorithm looks into each edge ([0,1], [0,2], [1,2], ...),
+ * computes the filtration value of the edge (in this case, propagation will have no effect).
+ *
+ * \subsubsection dimension0 Dimension 0
+ *
+ * Finally, the algorithm looks into each vertex ([0], [1], [2], [3], [4], [5] and [6]) and
+ * sets the filtration value (0 in case of a vertex - propagation will have no effect).
+ *
+ * \subsubsection nondecreasing Non decreasing filtration values
+ *
+ * As the squared radii computed by CGAL are an approximation, it might happen that these alpha squared values do not
+ * quite define a proper filtration (i.e. non-decreasing with respect to inclusion).
+ * We fix that up by calling `SimplicialComplexForAlpha::make_filtration_non_decreasing()`.
+ *
+ * \subsubsection pruneabove Prune above given filtration value
+ *
+ * The simplex tree is pruned from the given maximum alpha squared value (cf.
+ * `SimplicialComplexForAlpha::prune_above_filtration()`).
+ * In the following example, the value is given by the user as argument of the program.
+ *
+ *
+ * \section offexample Example from OFF file
+ *
+ * This example builds the Delaunay triangulation in a dynamic kernel, and initializes the alpha complex with it.
+ *
+ *
+ * Then, it is asked to display information about the alpha complex.
+ *
+ * \include Alpha_complex/Alpha_complex_from_off.cpp
+ *
+ * When launching:
+ *
+ * \code $> ./alphaoffreader ../../data/points/alphacomplexdoc.off 32.0
+ * \endcode
+ *
+ * the program output is:
+ *
+ * \include Alpha_complex/alphaoffreader_for_doc_32.txt
+ *
+ * \copyright GNU General Public License v3.
+ * \verbatim Contact: gudhi-users@lists.gforge.inria.fr \endverbatim
+ */
+/** @} */ // end defgroup alpha_complex
+
+} // namespace alpha_complex
+
+namespace alphacomplex = alpha_complex;
+
+} // namespace Gudhi
+
+#endif // DOC_ALPHA_COMPLEX_INTRO_ALPHA_COMPLEX_H_
diff --git a/src/Alpha_complex/doc/alpha_complex_doc.ipe b/src/Alpha_complex/doc/alpha_complex_doc.ipe
new file mode 100644
index 00000000..71e5ce6c
--- /dev/null
+++ b/src/Alpha_complex/doc/alpha_complex_doc.ipe
@@ -0,0 +1,296 @@
+<?xml version="1.0"?>
+<!DOCTYPE ipe SYSTEM "ipe.dtd">
+<ipe version="70107" creator="Ipe 7.1.10">
+<info created="D:20150603143945" modified="D:20160921180211"/>
+<ipestyle name="basic">
+<symbol name="arrow/arc(spx)">
+<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/farc(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="mark/circle(sx)" transformations="translations">
+<path fill="sym-stroke">
+0.6 0 0 0.6 0 0 e
+0.4 0 0 0.4 0 0 e
+</path>
+</symbol>
+<symbol name="mark/disk(sx)" transformations="translations">
+<path fill="sym-stroke">
+0.6 0 0 0.6 0 0 e
+</path>
+</symbol>
+<symbol name="mark/fdisk(sfx)" transformations="translations">
+<group>
+<path fill="sym-fill">
+0.5 0 0 0.5 0 0 e
+</path>
+<path fill="sym-stroke" fillrule="eofill">
+0.6 0 0 0.6 0 0 e
+0.4 0 0 0.4 0 0 e
+</path>
+</group>
+</symbol>
+<symbol name="mark/box(sx)" transformations="translations">
+<path fill="sym-stroke" fillrule="eofill">
+-0.6 -0.6 m
+0.6 -0.6 l
+0.6 0.6 l
+-0.6 0.6 l
+h
+-0.4 -0.4 m
+0.4 -0.4 l
+0.4 0.4 l
+-0.4 0.4 l
+h
+</path>
+</symbol>
+<symbol name="mark/square(sx)" transformations="translations">
+<path fill="sym-stroke">
+-0.6 -0.6 m
+0.6 -0.6 l
+0.6 0.6 l
+-0.6 0.6 l
+h
+</path>
+</symbol>
+<symbol name="mark/fsquare(sfx)" transformations="translations">
+<group>
+<path fill="sym-fill">
+-0.5 -0.5 m
+0.5 -0.5 l
+0.5 0.5 l
+-0.5 0.5 l
+h
+</path>
+<path fill="sym-stroke" fillrule="eofill">
+-0.6 -0.6 m
+0.6 -0.6 l
+0.6 0.6 l
+-0.6 0.6 l
+h
+-0.4 -0.4 m
+0.4 -0.4 l
+0.4 0.4 l
+-0.4 0.4 l
+h
+</path>
+</group>
+</symbol>
+<symbol name="mark/cross(sx)" transformations="translations">
+<group>
+<path fill="sym-stroke">
+-0.43 -0.57 m
+0.57 0.43 l
+0.43 0.57 l
+-0.57 -0.43 l
+h
+</path>
+<path fill="sym-stroke">
+-0.43 0.57 m
+0.57 -0.43 l
+0.43 -0.57 l
+-0.57 0.43 l
+h
+</path>
+</group>
+</symbol>
+<symbol name="arrow/fnormal(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/pointed(spx)">
+<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-0.8 0 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/fpointed(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-0.8 0 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/linear(spx)">
+<path stroke="sym-stroke" pen="sym-pen">
+-1 0.333 m
+0 0 l
+-1 -0.333 l
+</path>
+</symbol>
+<symbol name="arrow/fdouble(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+-1 0 m
+-2 0.333 l
+-2 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/double(spx)">
+<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+-1 0 m
+-2 0.333 l
+-2 -0.333 l
+h
+</path>
+</symbol>
+<pen name="heavier" value="0.8"/>
+<pen name="fat" value="1.2"/>
+<pen name="ultrafat" value="2"/>
+<symbolsize name="large" value="5"/>
+<symbolsize name="small" value="2"/>
+<symbolsize name="tiny" value="1.1"/>
+<arrowsize name="large" value="10"/>
+<arrowsize name="small" value="5"/>
+<arrowsize name="tiny" value="3"/>
+<color name="red" value="1 0 0"/>
+<color name="green" value="0 1 0"/>
+<color name="blue" value="0 0 1"/>
+<color name="yellow" value="1 1 0"/>
+<color name="orange" value="1 0.647 0"/>
+<color name="gold" value="1 0.843 0"/>
+<color name="purple" value="0.627 0.125 0.941"/>
+<color name="gray" value="0.745"/>
+<color name="brown" value="0.647 0.165 0.165"/>
+<color name="navy" value="0 0 0.502"/>
+<color name="pink" value="1 0.753 0.796"/>
+<color name="seagreen" value="0.18 0.545 0.341"/>
+<color name="turquoise" value="0.251 0.878 0.816"/>
+<color name="violet" value="0.933 0.51 0.933"/>
+<color name="darkblue" value="0 0 0.545"/>
+<color name="darkcyan" value="0 0.545 0.545"/>
+<color name="darkgray" value="0.663"/>
+<color name="darkgreen" value="0 0.392 0"/>
+<color name="darkmagenta" value="0.545 0 0.545"/>
+<color name="darkorange" value="1 0.549 0"/>
+<color name="darkred" value="0.545 0 0"/>
+<color name="lightblue" value="0.678 0.847 0.902"/>
+<color name="lightcyan" value="0.878 1 1"/>
+<color name="lightgray" value="0.827"/>
+<color name="lightgreen" value="0.565 0.933 0.565"/>
+<color name="lightyellow" value="1 1 0.878"/>
+<dashstyle name="dashed" value="[4] 0"/>
+<dashstyle name="dotted" value="[1 3] 0"/>
+<dashstyle name="dash dotted" value="[4 2 1 2] 0"/>
+<dashstyle name="dash dot dotted" value="[4 2 1 2 1 2] 0"/>
+<textsize name="large" value="\large"/>
+<textsize name="small" value="\small"/>
+<textsize name="tiny" value="\tiny"/>
+<textsize name="Large" value="\Large"/>
+<textsize name="LARGE" value="\LARGE"/>
+<textsize name="huge" value="\huge"/>
+<textsize name="Huge" value="\Huge"/>
+<textsize name="footnote" value="\footnotesize"/>
+<textstyle name="center" begin="\begin{center}" end="\end{center}"/>
+<textstyle name="itemize" begin="\begin{itemize}" end="\end{itemize}"/>
+<textstyle name="item" begin="\begin{itemize}\item{}" end="\end{itemize}"/>
+<gridsize name="4 pts" value="4"/>
+<gridsize name="8 pts (~3 mm)" value="8"/>
+<gridsize name="16 pts (~6 mm)" value="16"/>
+<gridsize name="32 pts (~12 mm)" value="32"/>
+<gridsize name="10 pts (~3.5 mm)" value="10"/>
+<gridsize name="20 pts (~7 mm)" value="20"/>
+<gridsize name="14 pts (~5 mm)" value="14"/>
+<gridsize name="28 pts (~10 mm)" value="28"/>
+<gridsize name="56 pts (~20 mm)" value="56"/>
+<anglesize name="90 deg" value="90"/>
+<anglesize name="60 deg" value="60"/>
+<anglesize name="45 deg" value="45"/>
+<anglesize name="30 deg" value="30"/>
+<anglesize name="22.5 deg" value="22.5"/>
+<tiling name="falling" angle="-60" step="4" width="1"/>
+<tiling name="rising" angle="30" step="4" width="1"/>
+</ipestyle>
+<page>
+<layer name="alpha"/>
+<view layers="alpha" active="alpha"/>
+<path layer="alpha" matrix="1 0 0 1 -240 0" stroke="darkcyan">
+320 580 m
+350 520 l
+290 530 l
+320 580 l
+320 580 l
+</path>
+<path matrix="1 0 0 1 -240 0" stroke="darkcyan">
+320 580 m
+280 660 l
+290 530 l
+320 580 l
+320 580 l
+</path>
+<path matrix="1 0 0 1 -240 0" stroke="darkcyan">
+320 580 m
+370 580 l
+350 520 l
+320 580 l
+</path>
+<text matrix="1 0 0 1 -260 0" transformations="translations" pos="380 530" stroke="darkcyan" type="label" width="118.196" height="8.307" depth="2.32" valign="baseline" size="large">Delaunay triangulation</text>
+<text matrix="1 0 0 1 -242.155 -3.50128" transformations="translations" pos="282.952 524.893" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">0</text>
+<text matrix="1 0 0 1 -240 0" transformations="translations" pos="352.708 510.349" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">1</text>
+<text matrix="1 0 0 1 -240 0" transformations="translations" pos="310.693 578.759" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">2</text>
+<text matrix="1 0 0 1 -240 0" transformations="translations" pos="375.332 578.49" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">3</text>
+<text matrix="1 0 0 1 -240 0" transformations="translations" pos="272.179 660.635" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">4</text>
+<text matrix="1 0 0 1 -239.3 -10.1537" transformations="translations" pos="296.419 724.197" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">5</text>
+<text matrix="1 0 0 1 -240 0" transformations="translations" pos="375.332 689.453" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">6</text>
+<path matrix="1 0 0 1 -240 0" stroke="darkcyan">
+280 660 m
+300 710 l
+370 690 l
+280 660 l
+</path>
+<path matrix="1 0 0 1 -240 0" stroke="darkcyan">
+320 580 m
+370 690 l
+370 580 l
+320 580 l
+</path>
+<path matrix="1 0 0 1 -240 0" stroke="darkcyan">
+280 660 m
+370 690 l
+320 580 l
+280 660 l
+</path>
+<text matrix="1 0 0 1 76 36" transformations="translations" pos="180 620" stroke="black" type="label" width="153.148" height="6.926" depth="1.93" valign="baseline">Simplicial complex data structure :</text>
+<use matrix="1 0 0 1 -239.3 -10.1537" name="mark/fdisk(sfx)" pos="300 720" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -240 0" name="mark/fdisk(sfx)" pos="370 690" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -240 0" name="mark/fdisk(sfx)" pos="280 660" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -240 0" name="mark/fdisk(sfx)" pos="320 580" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -240 0" name="mark/fdisk(sfx)" pos="370 580" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -240 0" name="mark/fdisk(sfx)" pos="350 520" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -240 0" name="mark/fdisk(sfx)" pos="290 530" size="normal" stroke="black" fill="white"/>
+<text matrix="1 0 0 1 -20 -32" transformations="translations" pos="288 672" stroke="black" type="label" width="148.582" height="7.473" depth="2.49" valign="baseline">insert simplex and subfaces [0,1,2]</text>
+<text matrix="1 0 0 1 -20 -56" transformations="translations" pos="288 672" stroke="black" type="label" width="148.582" height="7.473" depth="2.49" valign="baseline">insert simplex and subfaces [1,2,3]</text>
+<text matrix="1 0 0 1 -20 -44" transformations="translations" pos="288 672" stroke="black" type="label" width="148.582" height="7.473" depth="2.49" valign="baseline">insert simplex and subfaces [0,2,4]</text>
+<text matrix="1 0 0 1 -20 -68" transformations="translations" pos="288 672" stroke="black" type="label" width="148.582" height="7.473" depth="2.49" valign="baseline">insert simplex and subfaces [2,3,6]</text>
+<text matrix="1 0 0 1 -20 -80" transformations="translations" pos="288 672" stroke="black" type="label" width="148.582" height="7.473" depth="2.49" valign="baseline">insert simplex and subfaces [2,4,6]</text>
+<text matrix="1 0 0 1 -20 -92" transformations="translations" pos="288 672" stroke="black" type="label" width="148.582" height="7.473" depth="2.49" valign="baseline">insert simplex and subfaces [4,5,6]</text>
+</page>
+</ipe>
diff --git a/src/Alpha_complex/doc/alpha_complex_doc.png b/src/Alpha_complex/doc/alpha_complex_doc.png
new file mode 100644
index 00000000..170bae80
--- /dev/null
+++ b/src/Alpha_complex/doc/alpha_complex_doc.png
Binary files differ
diff --git a/src/Alpha_complex/doc/alpha_complex_doc_420.ipe b/src/Alpha_complex/doc/alpha_complex_doc_420.ipe
new file mode 100644
index 00000000..5d1d29d4
--- /dev/null
+++ b/src/Alpha_complex/doc/alpha_complex_doc_420.ipe
@@ -0,0 +1,514 @@
+<?xml version="1.0"?>
+<!DOCTYPE ipe SYSTEM "ipe.dtd">
+<ipe version="70107" creator="Ipe 7.1.10">
+<info created="D:20150603143945" modified="D:20151130095019"/>
+<ipestyle name="basic">
+<symbol name="arrow/arc(spx)">
+<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/farc(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="mark/circle(sx)" transformations="translations">
+<path fill="sym-stroke">
+0.6 0 0 0.6 0 0 e
+0.4 0 0 0.4 0 0 e
+</path>
+</symbol>
+<symbol name="mark/disk(sx)" transformations="translations">
+<path fill="sym-stroke">
+0.6 0 0 0.6 0 0 e
+</path>
+</symbol>
+<symbol name="mark/fdisk(sfx)" transformations="translations">
+<group>
+<path fill="sym-fill">
+0.5 0 0 0.5 0 0 e
+</path>
+<path fill="sym-stroke" fillrule="eofill">
+0.6 0 0 0.6 0 0 e
+0.4 0 0 0.4 0 0 e
+</path>
+</group>
+</symbol>
+<symbol name="mark/box(sx)" transformations="translations">
+<path fill="sym-stroke" fillrule="eofill">
+-0.6 -0.6 m
+0.6 -0.6 l
+0.6 0.6 l
+-0.6 0.6 l
+h
+-0.4 -0.4 m
+0.4 -0.4 l
+0.4 0.4 l
+-0.4 0.4 l
+h
+</path>
+</symbol>
+<symbol name="mark/square(sx)" transformations="translations">
+<path fill="sym-stroke">
+-0.6 -0.6 m
+0.6 -0.6 l
+0.6 0.6 l
+-0.6 0.6 l
+h
+</path>
+</symbol>
+<symbol name="mark/fsquare(sfx)" transformations="translations">
+<group>
+<path fill="sym-fill">
+-0.5 -0.5 m
+0.5 -0.5 l
+0.5 0.5 l
+-0.5 0.5 l
+h
+</path>
+<path fill="sym-stroke" fillrule="eofill">
+-0.6 -0.6 m
+0.6 -0.6 l
+0.6 0.6 l
+-0.6 0.6 l
+h
+-0.4 -0.4 m
+0.4 -0.4 l
+0.4 0.4 l
+-0.4 0.4 l
+h
+</path>
+</group>
+</symbol>
+<symbol name="mark/cross(sx)" transformations="translations">
+<group>
+<path fill="sym-stroke">
+-0.43 -0.57 m
+0.57 0.43 l
+0.43 0.57 l
+-0.57 -0.43 l
+h
+</path>
+<path fill="sym-stroke">
+-0.43 0.57 m
+0.57 -0.43 l
+0.43 -0.57 l
+-0.57 0.43 l
+h
+</path>
+</group>
+</symbol>
+<symbol name="arrow/fnormal(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/pointed(spx)">
+<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-0.8 0 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/fpointed(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-0.8 0 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/linear(spx)">
+<path stroke="sym-stroke" pen="sym-pen">
+-1 0.333 m
+0 0 l
+-1 -0.333 l
+</path>
+</symbol>
+<symbol name="arrow/fdouble(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+-1 0 m
+-2 0.333 l
+-2 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/double(spx)">
+<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+-1 0 m
+-2 0.333 l
+-2 -0.333 l
+h
+</path>
+</symbol>
+<pen name="heavier" value="0.8"/>
+<pen name="fat" value="1.2"/>
+<pen name="ultrafat" value="2"/>
+<symbolsize name="large" value="5"/>
+<symbolsize name="small" value="2"/>
+<symbolsize name="tiny" value="1.1"/>
+<arrowsize name="large" value="10"/>
+<arrowsize name="small" value="5"/>
+<arrowsize name="tiny" value="3"/>
+<color name="red" value="1 0 0"/>
+<color name="green" value="0 1 0"/>
+<color name="blue" value="0 0 1"/>
+<color name="yellow" value="1 1 0"/>
+<color name="orange" value="1 0.647 0"/>
+<color name="gold" value="1 0.843 0"/>
+<color name="purple" value="0.627 0.125 0.941"/>
+<color name="gray" value="0.745"/>
+<color name="brown" value="0.647 0.165 0.165"/>
+<color name="navy" value="0 0 0.502"/>
+<color name="pink" value="1 0.753 0.796"/>
+<color name="seagreen" value="0.18 0.545 0.341"/>
+<color name="turquoise" value="0.251 0.878 0.816"/>
+<color name="violet" value="0.933 0.51 0.933"/>
+<color name="darkblue" value="0 0 0.545"/>
+<color name="darkcyan" value="0 0.545 0.545"/>
+<color name="darkgray" value="0.663"/>
+<color name="darkgreen" value="0 0.392 0"/>
+<color name="darkmagenta" value="0.545 0 0.545"/>
+<color name="darkorange" value="1 0.549 0"/>
+<color name="darkred" value="0.545 0 0"/>
+<color name="lightblue" value="0.678 0.847 0.902"/>
+<color name="lightcyan" value="0.878 1 1"/>
+<color name="lightgray" value="0.827"/>
+<color name="lightgreen" value="0.565 0.933 0.565"/>
+<color name="lightyellow" value="1 1 0.878"/>
+<dashstyle name="dashed" value="[4] 0"/>
+<dashstyle name="dotted" value="[1 3] 0"/>
+<dashstyle name="dash dotted" value="[4 2 1 2] 0"/>
+<dashstyle name="dash dot dotted" value="[4 2 1 2 1 2] 0"/>
+<textsize name="large" value="\large"/>
+<textsize name="small" value="\small"/>
+<textsize name="tiny" value="\tiny"/>
+<textsize name="Large" value="\Large"/>
+<textsize name="LARGE" value="\LARGE"/>
+<textsize name="huge" value="\huge"/>
+<textsize name="Huge" value="\Huge"/>
+<textsize name="footnote" value="\footnotesize"/>
+<textstyle name="center" begin="\begin{center}" end="\end{center}"/>
+<textstyle name="itemize" begin="\begin{itemize}" end="\end{itemize}"/>
+<textstyle name="item" begin="\begin{itemize}\item{}" end="\end{itemize}"/>
+<gridsize name="4 pts" value="4"/>
+<gridsize name="8 pts (~3 mm)" value="8"/>
+<gridsize name="16 pts (~6 mm)" value="16"/>
+<gridsize name="32 pts (~12 mm)" value="32"/>
+<gridsize name="10 pts (~3.5 mm)" value="10"/>
+<gridsize name="20 pts (~7 mm)" value="20"/>
+<gridsize name="14 pts (~5 mm)" value="14"/>
+<gridsize name="28 pts (~10 mm)" value="28"/>
+<gridsize name="56 pts (~20 mm)" value="56"/>
+<anglesize name="90 deg" value="90"/>
+<anglesize name="60 deg" value="60"/>
+<anglesize name="45 deg" value="45"/>
+<anglesize name="30 deg" value="30"/>
+<anglesize name="22.5 deg" value="22.5"/>
+<tiling name="falling" angle="-60" step="4" width="1"/>
+<tiling name="rising" angle="30" step="4" width="1"/>
+</ipestyle>
+<page>
+<layer name="alpha"/>
+<view layers="alpha" active="alpha"/>
+<path layer="alpha" matrix="1 0 0 1 0 80" stroke="lightgray">
+320 580 m
+350 520 l
+290 530 l
+320 580 l
+320 580 l
+</path>
+<path matrix="1 0 0 1 0 80" stroke="darkcyan" pen="heavier">
+320 580 m
+280 660 l
+290 530 l
+320 580 l
+320 580 l
+</path>
+<path matrix="1 0 0 1 0 80" stroke="lightgray">
+320 580 m
+370 580 l
+350 520 l
+320 580 l
+</path>
+<text matrix="1 0 0 1 0 80" transformations="translations" pos="380 530" stroke="darkcyan" type="label" width="54.628" height="8.965" depth="2.99" valign="baseline" size="large">Cell [4,2,0]</text>
+<text matrix="1 0 0 1 -2.15463 76.4987" transformations="translations" pos="282.952 524.893" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">0</text>
+<text matrix="1 0 0 1 0 80" transformations="translations" pos="352.708 510.349" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">1</text>
+<text matrix="1 0 0 1 0 80" transformations="translations" pos="310.693 578.759" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">2</text>
+<text matrix="1 0 0 1 0 80" transformations="translations" pos="375.332 578.49" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">3</text>
+<text matrix="1 0 0 1 0 80" transformations="translations" pos="272.179 660.635" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">4</text>
+<text matrix="1 0 0 1 0.700256 69.8463" transformations="translations" pos="296.419 724.197" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">5</text>
+<text matrix="1 0 0 1 0 80" transformations="translations" pos="375.332 689.453" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">6</text>
+<path matrix="1 0 0 1 0 80" stroke="lightgray">
+280 660 m
+300 710 l
+370 690 l
+280 660 l
+</path>
+<path matrix="1 0 0 1 0 80" stroke="lightgray">
+320 580 m
+370 690 l
+370 580 l
+320 580 l
+</path>
+<path matrix="1 0 0 1 0 80" stroke="lightgray">
+280 660 m
+370 690 l
+320 580 l
+280 660 l
+</path>
+<path matrix="1 0 0 1 0 80" stroke="darkcyan">
+77.2727 0 0 77.2727 243.636 591.818 e
+</path>
+<path matrix="1 0 0 1 0 80" stroke="darkcyan">
+243.428 591.569 m
+186.061 643.28 l
+</path>
+<text matrix="1 0 0 1 0 80" transformations="translations" pos="212.724 627.389" stroke="darkcyan" type="label" width="18.785" height="4.294" depth="1.49" valign="baseline">$\alpha_{420}$</text>
+<path matrix="1 0 0 1 -264 -162" stroke="lightgray">
+320 580 m
+350 520 l
+290 530 l
+320 580 l
+320 580 l
+</path>
+<path matrix="1 0 0 1 -264 -162" stroke="lightgray">
+320 580 m
+280 660 l
+290 530 l
+320 580 l
+320 580 l
+</path>
+<path matrix="1 0 0 1 -264 -162" stroke="lightgray">
+320 580 m
+370 580 l
+350 520 l
+320 580 l
+</path>
+<text matrix="0.582962 0 0 1 -211.265 -209.555" transformations="translations" pos="380 530" stroke="darkcyan" type="label" width="231.798" height="8.965" depth="2.99" valign="baseline" size="large">[2,0] is Gabriel $\rightarrow$ $\alpha_{20}$ is not$\\$
+modified (NaN)
+</text>
+<text matrix="1 0 0 1 -266.155 -165.501" transformations="translations" pos="282.952 524.893" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">0</text>
+<text matrix="1 0 0 1 -264 -162" transformations="translations" pos="310.693 578.759" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">2</text>
+<text matrix="1 0 0 1 -264 -162" transformations="translations" pos="375.332 578.49" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">3</text>
+<text matrix="1 0 0 1 -264 -172" transformations="translations" pos="272.179 660.635" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">4</text>
+<text matrix="1 0 0 1 -263.3 -172.154" transformations="translations" pos="296.419 724.197" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">5</text>
+<text matrix="1 0 0 1 -264 -162" transformations="translations" pos="375.332 689.453" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">6</text>
+<path matrix="1 0 0 1 -264 -162" stroke="lightgray">
+280 660 m
+300 710 l
+370 690 l
+280 660 l
+</path>
+<path matrix="1 0 0 1 -264 -162" stroke="lightgray">
+320 580 m
+370 690 l
+370 580 l
+320 580 l
+</path>
+<path matrix="1 0 0 1 -264 -162" stroke="lightgray">
+280 660 m
+370 690 l
+320 580 l
+280 660 l
+</path>
+<text matrix="1 0 0 1 -166.834 -240.52" transformations="translations" pos="212.724 627.389" stroke="darkcyan" type="label" width="14.814" height="4.294" depth="1.49" valign="baseline">$\alpha_{20}$</text>
+<path matrix="1 0 0 1 -264 -162" stroke="darkcyan" pen="heavier">
+290 530 m
+320 580 l
+</path>
+<path matrix="1 0 0 1 -264 -162" stroke="darkcyan">
+29.1548 0 0 29.1548 305 555 e
+</path>
+<path matrix="1 0 0 1 -264 -162" stroke="darkcyan">
+304.883 555.015 m
+334.509 555.015 l
+</path>
+<path matrix="1 0 0 1 -37.2997 -163.65" stroke="lightgray">
+320 580 m
+350 520 l
+290 530 l
+320 580 l
+320 580 l
+</path>
+<path matrix="1 0 0 1 -38 -164" stroke="lightgray">
+320 580 m
+280 660 l
+290 530 l
+320 580 l
+320 580 l
+</path>
+<path matrix="1 0 0 1 -38 -164" stroke="lightgray">
+320 580 m
+370 580 l
+350 520 l
+320 580 l
+</path>
+<text matrix="1 0 0 1 -199.21 -189.117" transformations="translations" pos="380 530" stroke="darkred" type="label" width="168.308" height="8.965" depth="2.99" valign="baseline" size="large">[0,4] is not Gabriel $\rightarrow$ $\alpha_{40} = \alpha_{420}$</text>
+<text matrix="1 0 0 1 -40.1546 -167.501" transformations="translations" pos="282.952 524.893" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">0</text>
+<text matrix="1 0 0 1 -38 -164" transformations="translations" pos="375.332 578.49" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">3</text>
+<text matrix="1 0 0 1 -37.2997 -174.154" transformations="translations" pos="296.419 724.197" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">5</text>
+<text matrix="1 0 0 1 -38 -164" transformations="translations" pos="375.332 689.453" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">6</text>
+<path matrix="1 0 0 1 -38 -164" stroke="lightgray">
+280 660 m
+300 710 l
+370 690 l
+280 660 l
+</path>
+<path matrix="1 0 0 1 -38 -164" stroke="lightgray">
+320 580 m
+370 690 l
+370 580 l
+320 580 l
+</path>
+<path matrix="1 0 0 1 -38 -164" stroke="lightgray">
+280 660 m
+370 690 l
+320 580 l
+280 660 l
+</path>
+<text matrix="1 0 0 1 52.4654 -193.97" transformations="translations" pos="212.724 627.389" stroke="darkcyan" type="label" width="14.814" height="4.294" depth="1.49" valign="baseline">$\alpha_{40}$</text>
+<path matrix="1 0 0 1 -38 -164" stroke="darkcyan" pen="heavier">
+290 530 m
+280 660 l
+</path>
+<path matrix="1 0 0 1 126 -162" stroke="lightgray">
+320 580 m
+350 520 l
+290 530 l
+320 580 l
+320 580 l
+</path>
+<path matrix="1 0 0 1 126 -162" stroke="lightgray">
+320 580 m
+280 660 l
+290 530 l
+320 580 l
+320 580 l
+</path>
+<path matrix="1 0 0 1 126 -162" stroke="lightgray">
+320 580 m
+370 580 l
+350 520 l
+320 580 l
+</path>
+<text matrix="1 0 0 1 123.845 -165.501" transformations="translations" pos="282.952 524.893" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">0</text>
+<text matrix="1 0 0 1 126 -162" transformations="translations" pos="352.708 510.349" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">1</text>
+<text matrix="1 0 0 1 126 -162" transformations="translations" pos="310.693 578.759" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">2</text>
+<text matrix="1 0 0 1 126 -162" transformations="translations" pos="375.332 578.49" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">3</text>
+<text matrix="1 0 0 1 126.7 -172.154" transformations="translations" pos="296.419 724.197" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">5</text>
+<text matrix="1 0 0 1 126 -162" transformations="translations" pos="375.332 689.453" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">6</text>
+<path matrix="1 0 0 1 126 -162" stroke="lightgray">
+280 660 m
+300 710 l
+370 690 l
+280 660 l
+</path>
+<path matrix="1 0 0 1 126 -162" stroke="lightgray">
+320 580 m
+370 690 l
+370 580 l
+320 580 l
+</path>
+<path matrix="1 0 0 1 126 -162" stroke="lightgray">
+280 660 m
+370 690 l
+320 580 l
+280 660 l
+</path>
+<text matrix="1 0 0 1 225.859 -165.729" transformations="translations" pos="212.724 627.389" stroke="darkcyan" type="label" width="14.814" height="4.294" depth="1.49" valign="baseline">$\alpha_{42}$</text>
+<text matrix="1 0 0 1 122 -164" transformations="translations" pos="272.179 660.635" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">4</text>
+<path stroke="darkcyan" pen="heavier">
+406.093 497.775 m
+446.094 418.092 l
+</path>
+<path stroke="darkcyan">
+44.5799 0 0 44.5799 425.934 457.774 e
+</path>
+<path stroke="darkcyan">
+425.854 457.774 m
+470.795 457.774 l
+</path>
+<text matrix="1 0 0 1 -48.9756 -209.799" transformations="translations" pos="380 530" stroke="darkcyan" type="label" width="231.798" height="8.965" depth="2.99" valign="baseline" size="large">[2,4] is Gabriel $\rightarrow$ $\alpha_{42}$ is not modified (NaN)
+</text>
+<path stroke="darkblue" arrow="normal/normal">
+205.028 596.091 m
+110.946 544.02 l
+</path>
+<path stroke="darkblue" arrow="normal/normal">
+280.768 588.99 m
+280.768 547.57 l
+</path>
+<path stroke="darkblue" arrow="normal/normal">
+341.123 594.316 m
+413.904 554.079 l
+</path>
+<text matrix="1 0 0 1 39.645 -2.36686" transformations="translations" pos="199.703 569.464" stroke="darkblue" type="label" width="93.206" height="7.473" depth="2.49" valign="baseline">For all faces of [4,2,0]</text>
+<text matrix="1 0 0 1 -93.391 2.68003" transformations="translations" pos="104.437 300.174" stroke="black" type="label" width="208.621" height="6.926" depth="1.93" valign="baseline">N.B. : is Gabriel on a single point has no sense.</text>
+<text matrix="1 0 0 1 -36.9231 10" transformations="translations" pos="48 784" stroke="black" type="label" width="118.324" height="7.473" depth="2.49" valign="baseline">Dimension =2 - $\sigma$ = [4,2,0]</text>
+<path stroke="darkcyan">
+247.333 430.892 m
+311.764 430.892 l
+</path>
+<use matrix="1 0 0 1 0.700256 69.8463" name="mark/fdisk(sfx)" pos="300 720" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 0 80" name="mark/fdisk(sfx)" pos="370 690" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 0 80" name="mark/fdisk(sfx)" pos="280 660" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 0 80" name="mark/fdisk(sfx)" pos="243.636 591.818" size="normal" stroke="darkcyan" fill="white"/>
+<use matrix="1 0 0 1 0 80" name="mark/fdisk(sfx)" pos="370 580" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 0 80" name="mark/fdisk(sfx)" pos="350 520" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 0 80" name="mark/fdisk(sfx)" pos="320 580" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 0 80" name="mark/fdisk(sfx)" pos="290 530" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -263.3 -172.154" name="mark/fdisk(sfx)" pos="300 720" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -264 -162" name="mark/fdisk(sfx)" pos="280 660" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -264 -162" name="mark/fdisk(sfx)" pos="370 690" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -264 -162" name="mark/fdisk(sfx)" pos="370 580" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -264 -162" name="mark/fdisk(sfx)" pos="350 520" size="normal" stroke="black" fill="white"/>
+<text matrix="1 0 0 1 -264 -162" transformations="translations" pos="352.708 510.349" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">1</text>
+<use matrix="1 0 0 1 -264 -162" name="mark/fdisk(sfx)" pos="305 555" size="normal" stroke="darkcyan" fill="white"/>
+<use matrix="1 0 0 1 -264 -162" name="mark/fdisk(sfx)" pos="290 530" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -264 -162" name="mark/fdisk(sfx)" pos="320 580" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -37.2997 -174.154" name="mark/fdisk(sfx)" pos="300 720" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -38 -164" name="mark/fdisk(sfx)" pos="370 690" size="normal" stroke="black" fill="white"/>
+<text matrix="1 0 0 1 -38 -164" transformations="translations" pos="272.179 660.635" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">4</text>
+<use name="mark/fdisk(sfx)" pos="247 431" size="normal" stroke="darkcyan" fill="white"/>
+<use matrix="1 0 0 1 -38 -164" name="mark/fdisk(sfx)" pos="350 520" size="normal" stroke="black" fill="white"/>
+<text matrix="1 0 0 1 -38 -164" transformations="translations" pos="352.708 510.349" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">1</text>
+<use matrix="1 0 0 1 -38 -164" name="mark/fdisk(sfx)" pos="370 580" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -38 -164" name="mark/fdisk(sfx)" pos="320 580" size="normal" stroke="darkred" fill="white"/>
+<text matrix="1 0 0 1 -38 -164" transformations="translations" pos="310.693 578.759" stroke="darkred" type="label" width="4.981" height="6.42" depth="0" valign="baseline">2</text>
+<path matrix="1 0 0 1 -38 -164" stroke="darkred" pen="heavier">
+65.192 0 0 65.192 285 595 e
+</path>
+<use matrix="1 0 0 1 -38 -164" name="mark/fdisk(sfx)" pos="290 530" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 126 -162" name="mark/fdisk(sfx)" pos="290 530" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 126.7 -172.154" name="mark/fdisk(sfx)" pos="300 720" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 126 -162" name="mark/fdisk(sfx)" pos="370 690" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 126 -162" name="mark/fdisk(sfx)" pos="280 660" size="normal" stroke="black" fill="white"/>
+<use name="mark/fdisk(sfx)" pos="425.934 457.774" size="normal" stroke="darkcyan" fill="white"/>
+<use matrix="1 0 0 1 126 -162" name="mark/fdisk(sfx)" pos="320 580" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 126 -162" name="mark/fdisk(sfx)" pos="370 580" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 126 -162" name="mark/fdisk(sfx)" pos="350 520" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -38 -164" name="mark/fdisk(sfx)" pos="280 660" size="normal" stroke="black" fill="white"/>
+</page>
+</ipe>
diff --git a/src/Alpha_complex/doc/alpha_complex_doc_420.png b/src/Alpha_complex/doc/alpha_complex_doc_420.png
new file mode 100644
index 00000000..ef7187f7
--- /dev/null
+++ b/src/Alpha_complex/doc/alpha_complex_doc_420.png
Binary files differ
diff --git a/src/Alpha_complex/doc/alpha_complex_representation.ipe b/src/Alpha_complex/doc/alpha_complex_representation.ipe
new file mode 100644
index 00000000..e8096b93
--- /dev/null
+++ b/src/Alpha_complex/doc/alpha_complex_representation.ipe
@@ -0,0 +1,321 @@
+<?xml version="1.0"?>
+<!DOCTYPE ipe SYSTEM "ipe.dtd">
+<ipe version="70107" creator="Ipe 7.1.10">
+<info created="D:20150603143945" modified="D:20160404172133"/>
+<ipestyle name="basic">
+<symbol name="arrow/arc(spx)">
+<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/farc(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="mark/circle(sx)" transformations="translations">
+<path fill="sym-stroke">
+0.6 0 0 0.6 0 0 e
+0.4 0 0 0.4 0 0 e
+</path>
+</symbol>
+<symbol name="mark/disk(sx)" transformations="translations">
+<path fill="sym-stroke">
+0.6 0 0 0.6 0 0 e
+</path>
+</symbol>
+<symbol name="mark/fdisk(sfx)" transformations="translations">
+<group>
+<path fill="sym-fill">
+0.5 0 0 0.5 0 0 e
+</path>
+<path fill="sym-stroke" fillrule="eofill">
+0.6 0 0 0.6 0 0 e
+0.4 0 0 0.4 0 0 e
+</path>
+</group>
+</symbol>
+<symbol name="mark/box(sx)" transformations="translations">
+<path fill="sym-stroke" fillrule="eofill">
+-0.6 -0.6 m
+0.6 -0.6 l
+0.6 0.6 l
+-0.6 0.6 l
+h
+-0.4 -0.4 m
+0.4 -0.4 l
+0.4 0.4 l
+-0.4 0.4 l
+h
+</path>
+</symbol>
+<symbol name="mark/square(sx)" transformations="translations">
+<path fill="sym-stroke">
+-0.6 -0.6 m
+0.6 -0.6 l
+0.6 0.6 l
+-0.6 0.6 l
+h
+</path>
+</symbol>
+<symbol name="mark/fsquare(sfx)" transformations="translations">
+<group>
+<path fill="sym-fill">
+-0.5 -0.5 m
+0.5 -0.5 l
+0.5 0.5 l
+-0.5 0.5 l
+h
+</path>
+<path fill="sym-stroke" fillrule="eofill">
+-0.6 -0.6 m
+0.6 -0.6 l
+0.6 0.6 l
+-0.6 0.6 l
+h
+-0.4 -0.4 m
+0.4 -0.4 l
+0.4 0.4 l
+-0.4 0.4 l
+h
+</path>
+</group>
+</symbol>
+<symbol name="mark/cross(sx)" transformations="translations">
+<group>
+<path fill="sym-stroke">
+-0.43 -0.57 m
+0.57 0.43 l
+0.43 0.57 l
+-0.57 -0.43 l
+h
+</path>
+<path fill="sym-stroke">
+-0.43 0.57 m
+0.57 -0.43 l
+0.43 -0.57 l
+-0.57 0.43 l
+h
+</path>
+</group>
+</symbol>
+<symbol name="arrow/fnormal(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/pointed(spx)">
+<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-0.8 0 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/fpointed(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-0.8 0 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/linear(spx)">
+<path stroke="sym-stroke" pen="sym-pen">
+-1 0.333 m
+0 0 l
+-1 -0.333 l
+</path>
+</symbol>
+<symbol name="arrow/fdouble(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+-1 0 m
+-2 0.333 l
+-2 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/double(spx)">
+<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+-1 0 m
+-2 0.333 l
+-2 -0.333 l
+h
+</path>
+</symbol>
+<pen name="heavier" value="0.8"/>
+<pen name="fat" value="1.2"/>
+<pen name="ultrafat" value="2"/>
+<symbolsize name="large" value="5"/>
+<symbolsize name="small" value="2"/>
+<symbolsize name="tiny" value="1.1"/>
+<arrowsize name="large" value="10"/>
+<arrowsize name="small" value="5"/>
+<arrowsize name="tiny" value="3"/>
+<color name="red" value="1 0 0"/>
+<color name="green" value="0 1 0"/>
+<color name="blue" value="0 0 1"/>
+<color name="yellow" value="1 1 0"/>
+<color name="orange" value="1 0.647 0"/>
+<color name="gold" value="1 0.843 0"/>
+<color name="purple" value="0.627 0.125 0.941"/>
+<color name="gray" value="0.745"/>
+<color name="brown" value="0.647 0.165 0.165"/>
+<color name="navy" value="0 0 0.502"/>
+<color name="pink" value="1 0.753 0.796"/>
+<color name="seagreen" value="0.18 0.545 0.341"/>
+<color name="turquoise" value="0.251 0.878 0.816"/>
+<color name="violet" value="0.933 0.51 0.933"/>
+<color name="darkblue" value="0 0 0.545"/>
+<color name="darkcyan" value="0 0.545 0.545"/>
+<color name="darkgray" value="0.663"/>
+<color name="darkgreen" value="0 0.392 0"/>
+<color name="darkmagenta" value="0.545 0 0.545"/>
+<color name="darkorange" value="1 0.549 0"/>
+<color name="darkred" value="0.545 0 0"/>
+<color name="lightblue" value="0.678 0.847 0.902"/>
+<color name="lightcyan" value="0.878 1 1"/>
+<color name="lightgray" value="0.827"/>
+<color name="lightgreen" value="0.565 0.933 0.565"/>
+<color name="lightyellow" value="1 1 0.878"/>
+<dashstyle name="dashed" value="[4] 0"/>
+<dashstyle name="dotted" value="[1 3] 0"/>
+<dashstyle name="dash dotted" value="[4 2 1 2] 0"/>
+<dashstyle name="dash dot dotted" value="[4 2 1 2 1 2] 0"/>
+<textsize name="large" value="\large"/>
+<textsize name="small" value="\small"/>
+<textsize name="tiny" value="\tiny"/>
+<textsize name="Large" value="\Large"/>
+<textsize name="LARGE" value="\LARGE"/>
+<textsize name="huge" value="\huge"/>
+<textsize name="Huge" value="\Huge"/>
+<textsize name="footnote" value="\footnotesize"/>
+<textstyle name="center" begin="\begin{center}" end="\end{center}"/>
+<textstyle name="itemize" begin="\begin{itemize}" end="\end{itemize}"/>
+<textstyle name="item" begin="\begin{itemize}\item{}" end="\end{itemize}"/>
+<gridsize name="4 pts" value="4"/>
+<gridsize name="8 pts (~3 mm)" value="8"/>
+<gridsize name="16 pts (~6 mm)" value="16"/>
+<gridsize name="32 pts (~12 mm)" value="32"/>
+<gridsize name="10 pts (~3.5 mm)" value="10"/>
+<gridsize name="20 pts (~7 mm)" value="20"/>
+<gridsize name="14 pts (~5 mm)" value="14"/>
+<gridsize name="28 pts (~10 mm)" value="28"/>
+<gridsize name="56 pts (~20 mm)" value="56"/>
+<anglesize name="90 deg" value="90"/>
+<anglesize name="60 deg" value="60"/>
+<anglesize name="45 deg" value="45"/>
+<anglesize name="30 deg" value="30"/>
+<anglesize name="22.5 deg" value="22.5"/>
+<tiling name="falling" angle="-60" step="4" width="1"/>
+<tiling name="rising" angle="30" step="4" width="1"/>
+</ipestyle>
+<page>
+<layer name="alpha"/>
+<view layers="alpha" active="alpha"/>
+<path layer="alpha" fill="lightblue">
+109.771 601.912 m
+159.595 601.797 l
+140.058 541.915 l
+h
+</path>
+<path fill="lightblue">
+79.8776 552.169 m
+109.756 601.699 l
+139.812 542.209 l
+h
+</path>
+<path fill="lightblue">
+69.8453 682.419 m
+159.925 712.208 l
+90.12 732.039 l
+h
+</path>
+<text matrix="1 0 0 1 -230.178 22.1775" transformations="translations" pos="380 530" stroke="seagreen" type="label" width="76.735" height="8.307" depth="2.32" valign="baseline" size="large">Alpha complex</text>
+<text matrix="1 0 0 1 -212.333 18.6762" transformations="translations" pos="282.952 524.893" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">0</text>
+<text matrix="1 0 0 1 -210.178 22.1775" transformations="translations" pos="352.708 510.349" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">1</text>
+<text matrix="1 0 0 1 -210.178 22.1775" transformations="translations" pos="310.693 578.759" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">2</text>
+<text matrix="1 0 0 1 -210.178 22.1775" transformations="translations" pos="375.332 578.49" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">3</text>
+<text matrix="1 0 0 1 -210.178 22.1775" transformations="translations" pos="272.179 660.635" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">4</text>
+<text matrix="1 0 0 1 -209.478 12.0238" transformations="translations" pos="296.419 724.197" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">5</text>
+<text matrix="1 0 0 1 -210.178 22.1775" transformations="translations" pos="375.332 689.453" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">6</text>
+<path matrix="1 0 0 1 31.9779 -58.7483" stroke="darkgray">
+58.1341 0 0 58.1341 218.925 692.601 e
+</path>
+<path matrix="1 0 0 1 29.8225 22.1775" stroke="black" pen="heavier">
+60 710 m
+40 660 l
+</path>
+<path matrix="1 0 0 1 29.8225 22.1775" stroke="black" pen="heavier">
+40 660 m
+130 690 l
+</path>
+<path matrix="1 0 0 1 29.8225 22.1775" stroke="black" pen="heavier">
+130 690 m
+60 710 l
+</path>
+<path matrix="1 0 0 1 29.8225 22.1775" stroke="black" pen="heavier">
+40 660 m
+80 580 l
+</path>
+<path matrix="1 0 0 1 29.8225 22.1775" stroke="black" pen="heavier">
+80 580 m
+130 580 l
+130 580 l
+</path>
+<path matrix="1 0 0 1 29.8225 22.1775" stroke="black" pen="heavier">
+130 580 m
+110 520 l
+</path>
+<path matrix="1 0 0 1 29.8225 22.1775" stroke="black" pen="heavier">
+110 520 m
+50 530 l
+50 530 l
+50 530 l
+</path>
+<path matrix="1 0 0 1 29.8225 22.1775" stroke="black" pen="heavier">
+50 530 m
+80 580 l
+</path>
+<path matrix="1 0 0 1 29.8225 22.1775" stroke="black" pen="heavier">
+130 580 m
+130 690 l
+</path>
+<use matrix="1 0 0 1 142.618 -109.867" name="mark/fdisk(sfx)" pos="108.285 743.72" size="normal" stroke="darkgray" fill="white"/>
+<path matrix="1 0 0 1 142.618 -109.867" stroke="darkgray">
+108.275 743.531 m
+166.45 743.531 l
+</path>
+<text matrix="1 0 0 1 142.618 -109.867" transformations="translations" pos="127.397 746.763" stroke="darkgray" type="label" width="6.41" height="4.289" depth="0" valign="baseline">$\alpha$</text>
+<use matrix="1 0 0 1 -209.478 12.0238" name="mark/fdisk(sfx)" pos="300 720" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -210.178 22.1775" name="mark/fdisk(sfx)" pos="280 660" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -210.178 22.1775" name="mark/fdisk(sfx)" pos="370 690" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -210.178 22.1775" name="mark/fdisk(sfx)" pos="370 580" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -210.178 22.1775" name="mark/fdisk(sfx)" pos="290 530" size="normal" stroke="black" fill="white"/>
+<path matrix="1 0 0 1 -40 -8" stroke="black" pen="heavier">
+150.038 609.9 m
+179.929 549.727 l
+</path>
+<use matrix="1 0 0 1 -210.178 22.1775" name="mark/fdisk(sfx)" pos="320 580" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -210.178 22.1775" name="mark/fdisk(sfx)" pos="350 520" size="normal" stroke="black" fill="white"/>
+</page>
+</ipe>
diff --git a/src/Alpha_complex/doc/alpha_complex_representation.png b/src/Alpha_complex/doc/alpha_complex_representation.png
new file mode 100644
index 00000000..7b81cd69
--- /dev/null
+++ b/src/Alpha_complex/doc/alpha_complex_representation.png
Binary files differ
diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp
new file mode 100644
index 00000000..32bef1cd
--- /dev/null
+++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp
@@ -0,0 +1,63 @@
+#include <gudhi/Alpha_complex.h>
+// to construct a simplex_tree from alpha complex
+#include <gudhi/Simplex_tree.h>
+
+#include <CGAL/Epick_d.h>
+
+#include <iostream>
+#include <string>
+
+void usage(int nbArgs, char * const progName) {
+ std::cerr << "Error: Number of arguments (" << nbArgs << ") is not correct\n";
+ std::cerr << "Usage: " << progName << " filename.off alpha_square_max_value [ouput_file.txt]\n";
+ std::cerr << " i.e.: " << progName << " ../../data/points/alphacomplexdoc.off 60.0\n";
+ exit(-1); // ----- >>
+}
+
+int main(int argc, char **argv) {
+ if ((argc != 3) && (argc != 4)) usage(argc, (argv[0] - 1));
+
+ std::string off_file_name(argv[1]);
+ double alpha_square_max_value = atof(argv[2]);
+
+ // ----------------------------------------------------------------------------
+ // Init of an alpha complex from an OFF file
+ // ----------------------------------------------------------------------------
+ typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel;
+ Gudhi::alpha_complex::Alpha_complex<Kernel> alpha_complex_from_file(off_file_name);
+
+ std::streambuf* streambufffer;
+ std::ofstream ouput_file_stream;
+
+ if (argc == 4) {
+ ouput_file_stream.open(std::string(argv[3]));
+ streambufffer = ouput_file_stream.rdbuf();
+ } else {
+ streambufffer = std::cout.rdbuf();
+ }
+
+ Gudhi::Simplex_tree<> simplex;
+ if (alpha_complex_from_file.create_complex(simplex, alpha_square_max_value)) {
+ std::ostream output_stream(streambufffer);
+
+ // ----------------------------------------------------------------------------
+ // Display information about the alpha complex
+ // ----------------------------------------------------------------------------
+ output_stream << "Alpha complex is of dimension " << simplex.dimension() <<
+ " - " << simplex.num_simplices() << " simplices - " <<
+ simplex.num_vertices() << " vertices." << std::endl;
+
+ output_stream << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" <<
+ std::endl;
+ for (auto f_simplex : simplex.filtration_simplex_range()) {
+ output_stream << " ( ";
+ for (auto vertex : simplex.simplex_vertex_range(f_simplex)) {
+ output_stream << vertex << " ";
+ }
+ output_stream << ") -> " << "[" << simplex.filtration(f_simplex) << "] ";
+ output_stream << std::endl;
+ }
+ }
+ ouput_file_stream.close();
+ return 0;
+}
diff --git a/src/Alpha_complex/example/Alpha_complex_from_points.cpp b/src/Alpha_complex/example/Alpha_complex_from_points.cpp
new file mode 100644
index 00000000..491b7e6d
--- /dev/null
+++ b/src/Alpha_complex/example/Alpha_complex_from_points.cpp
@@ -0,0 +1,68 @@
+#include <gudhi/Alpha_complex.h>
+// to construct a simplex_tree from alpha complex
+#include <gudhi/Simplex_tree.h>
+
+#include <CGAL/Epick_d.h>
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <limits> // for numeric limits
+
+typedef CGAL::Epick_d< CGAL::Dimension_tag<2> > Kernel;
+typedef Kernel::Point_d Point;
+typedef std::vector<Point> Vector_of_points;
+
+void usage(int nbArgs, char * const progName) {
+ std::cerr << "Error: Number of arguments (" << nbArgs << ") is not correct\n";
+ std::cerr << "Usage: " << progName << " [alpha_square_max_value]\n";
+ std::cerr << " i.e.: " << progName << " 60.0\n";
+ exit(-1); // ----- >>
+}
+
+int main(int argc, char **argv) {
+ if ((argc != 1) && (argc != 2)) usage(argc, (argv[0] - 1));
+
+ // Delaunay complex if alpha_square_max_value is not given by the user.
+ double alpha_square_max_value = std::numeric_limits<double>::infinity();
+ if (argc == 2)
+ alpha_square_max_value = atof(argv[1]);
+
+ // ----------------------------------------------------------------------------
+ // Init of a list of points
+ // ----------------------------------------------------------------------------
+ Vector_of_points points;
+ points.push_back(Point(1.0, 1.0));
+ points.push_back(Point(7.0, 0.0));
+ points.push_back(Point(4.0, 6.0));
+ points.push_back(Point(9.0, 6.0));
+ points.push_back(Point(0.0, 14.0));
+ points.push_back(Point(2.0, 19.0));
+ points.push_back(Point(9.0, 17.0));
+
+ // ----------------------------------------------------------------------------
+ // Init of an alpha complex from the list of points
+ // ----------------------------------------------------------------------------
+ Gudhi::alpha_complex::Alpha_complex<Kernel> alpha_complex_from_points(points);
+
+ Gudhi::Simplex_tree<> simplex;
+ if (alpha_complex_from_points.create_complex(simplex, alpha_square_max_value)) {
+ // ----------------------------------------------------------------------------
+ // Display information about the alpha complex
+ // ----------------------------------------------------------------------------
+ std::cout << "Alpha complex is of dimension " << simplex.dimension() <<
+ " - " << simplex.num_simplices() << " simplices - " <<
+ simplex.num_vertices() << " vertices." << std::endl;
+
+ std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl;
+ for (auto f_simplex : simplex.filtration_simplex_range()) {
+ std::cout << " ( ";
+ for (auto vertex : simplex.simplex_vertex_range(f_simplex)) {
+ std::cout << vertex << " ";
+ }
+ std::cout << ") -> " << "[" << simplex.filtration(f_simplex) << "] ";
+ std::cout << std::endl;
+ }
+ }
+ return 0;
+}
diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt
new file mode 100644
index 00000000..71a95d61
--- /dev/null
+++ b/src/Alpha_complex/example/CMakeLists.txt
@@ -0,0 +1,33 @@
+cmake_minimum_required(VERSION 2.6)
+project(Alpha_complex_examples)
+
+# need CGAL 4.7
+# cmake -DCGAL_DIR=~/workspace/CGAL-4.7-Ic-41 ../../..
+if(CGAL_FOUND)
+ if (NOT CGAL_VERSION VERSION_LESS 4.7.0)
+ if (EIGEN3_FOUND)
+ add_executable ( alphapoints Alpha_complex_from_points.cpp )
+ target_link_libraries(alphapoints ${Boost_SYSTEM_LIBRARY} ${Boost_THREAD_LIBRARY} ${CGAL_LIBRARY})
+ add_executable ( alphaoffreader Alpha_complex_from_off.cpp )
+ target_link_libraries(alphaoffreader ${Boost_SYSTEM_LIBRARY} ${Boost_THREAD_LIBRARY} ${CGAL_LIBRARY})
+ if (TBB_FOUND)
+ target_link_libraries(alphapoints ${TBB_LIBRARIES})
+ target_link_libraries(alphaoffreader ${TBB_LIBRARIES})
+ endif()
+
+ add_test(alphapoints ${CMAKE_CURRENT_BINARY_DIR}/alphapoints)
+ # Do not forget to copy test files in current binary dir
+ file(COPY "${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
+ add_test(alphaoffreader_doc_60 ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader alphacomplexdoc.off 60.0 ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_result_60.txt)
+ add_test(alphaoffreader_doc_32 ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader alphacomplexdoc.off 32.0 ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_result_32.txt)
+ if (DIFF_PATH)
+ # Do not forget to copy test results files in current binary dir
+ file(COPY "alphaoffreader_for_doc_32.txt" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
+ file(COPY "alphaoffreader_for_doc_60.txt" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
+
+ add_test(alphaoffreader_doc_60_diff_files ${DIFF_PATH} ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_result_60.txt ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_for_doc_60.txt)
+ add_test(alphaoffreader_doc_32_diff_files ${DIFF_PATH} ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_result_32.txt ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_for_doc_32.txt)
+ endif()
+ endif(EIGEN3_FOUND)
+ endif(NOT CGAL_VERSION VERSION_LESS 4.7.0)
+endif(CGAL_FOUND)
diff --git a/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt b/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt
new file mode 100644
index 00000000..13183e86
--- /dev/null
+++ b/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt
@@ -0,0 +1,22 @@
+Alpha complex is of dimension 2 - 20 simplices - 7 vertices.
+Iterator on alpha complex simplices in the filtration order, with [filtration value]:
+ ( 0 ) -> [0]
+ ( 1 ) -> [0]
+ ( 2 ) -> [0]
+ ( 3 ) -> [0]
+ ( 4 ) -> [0]
+ ( 5 ) -> [0]
+ ( 6 ) -> [0]
+ ( 3 2 ) -> [6.25]
+ ( 5 4 ) -> [7.25]
+ ( 2 0 ) -> [8.5]
+ ( 1 0 ) -> [9.25]
+ ( 3 1 ) -> [10]
+ ( 2 1 ) -> [11.25]
+ ( 3 2 1 ) -> [12.5]
+ ( 2 1 0 ) -> [12.9959]
+ ( 6 5 ) -> [13.25]
+ ( 4 2 ) -> [20]
+ ( 6 4 ) -> [22.7367]
+ ( 6 5 4 ) -> [22.7367]
+ ( 6 3 ) -> [30.25]
diff --git a/src/Alpha_complex/example/alphaoffreader_for_doc_60.txt b/src/Alpha_complex/example/alphaoffreader_for_doc_60.txt
new file mode 100644
index 00000000..71f29a00
--- /dev/null
+++ b/src/Alpha_complex/example/alphaoffreader_for_doc_60.txt
@@ -0,0 +1,27 @@
+Alpha complex is of dimension 2 - 25 simplices - 7 vertices.
+Iterator on alpha complex simplices in the filtration order, with [filtration value]:
+ ( 0 ) -> [0]
+ ( 1 ) -> [0]
+ ( 2 ) -> [0]
+ ( 3 ) -> [0]
+ ( 4 ) -> [0]
+ ( 5 ) -> [0]
+ ( 6 ) -> [0]
+ ( 3 2 ) -> [6.25]
+ ( 5 4 ) -> [7.25]
+ ( 2 0 ) -> [8.5]
+ ( 1 0 ) -> [9.25]
+ ( 3 1 ) -> [10]
+ ( 2 1 ) -> [11.25]
+ ( 3 2 1 ) -> [12.5]
+ ( 2 1 0 ) -> [12.9959]
+ ( 6 5 ) -> [13.25]
+ ( 4 2 ) -> [20]
+ ( 6 4 ) -> [22.7367]
+ ( 6 5 4 ) -> [22.7367]
+ ( 6 3 ) -> [30.25]
+ ( 6 2 ) -> [36.5]
+ ( 6 3 2 ) -> [36.5]
+ ( 6 4 2 ) -> [37.2449]
+ ( 4 0 ) -> [59.7107]
+ ( 4 2 0 ) -> [59.7107]
diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h
new file mode 100644
index 00000000..9d5a9bad
--- /dev/null
+++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h
@@ -0,0 +1,434 @@
+/* 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
+ *
+ * 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_
+
+#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 <CGAL/property_map.h> // for CGAL::Identity_property_map
+
+#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 alpha_complex {
+
+/**
+ * \class Alpha_complex Alpha_complex.h gudhi/Alpha_complex.h
+ * \brief Alpha complex data structure.
+ *
+ * \ingroup alpha_complex
+ *
+ * \details
+ * 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.
+ *
+ * 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:
+ // 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:
+ 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< 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.
+ * 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 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.
+ */
+ 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()) {
+ std::cerr << "Alpha_complex - Unable to read file " << off_file_name << "\n";
+ exit(-1); // ----- >>
+ }
+
+ init_from_range(off_reader.get_point_cloud());
+ }
+
+ /** \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
+ *
+ * The type InputPointRange must be a range for which std::begin and
+ * std::end return input iterators on a Kernel::Point_d.
+ */
+ template<typename InputPointRange >
+ Alpha_complex(const InputPointRange& points)
+ : triangulation_(nullptr) {
+ init_from_range(points);
+ }
+
+ /** \brief Alpha_complex destructor 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).
+ */
+ 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) {
+ 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> 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>(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;
+
+ 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(point_cloud[index], hint);
+ // Save index value as data to retrieve it after insertion
+ pos->data() = index;
+ hint = pos->full_cell();
+ }
+ // --------------------------------------------------------------------------------------------
+ // 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);
+ }
+ }
+ // --------------------------------------------------------------------------------------------
+ }
+ }
+
+ 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
+ *
+ * \tparam SimplicialComplexForAlpha must meet `SimplicialComplexForAlpha` concept.
+ *
+ * @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.
+ */
+ 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 cannot create_complex from a NULL triangulation\n";
+ return false; // ----- >>
+ }
+ if (triangulation_->maximal_dimension() < 1) {
+ std::cerr << "Alpha_complex cannot create_complex from a zero-dimension triangulation\n";
+ return false; // ----- >>
+ }
+ if (complex.num_vertices() > 0) {
+ std::cerr << "Alpha_complex create_complex - complex is not empty\n";
+ return false; // ----- >>
+ }
+
+ complex.set_dimension(triangulation_->maximal_dimension());
+
+ // --------------------------------------------------------------------------------------------
+ // Simplex_tree construction from loop on triangulation finite full cells list
+ 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 ";
+#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
+ complex.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 = triangulation_->maximal_dimension(); decr_dim >= 0; decr_dim--) {
+ // ### Foreach Sigma of dim i
+ 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 : complex.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 (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) {
+ // squared_radius function initialization
+ Squared_Radius squared_radius = kernel_.compute_squared_radius_d_object();
+
+ alpha_complex_filtration = squared_radius(pointVector.begin(), pointVector.end());
+ }
+ complex.assign_filtration(f_simplex, alpha_complex_filtration);
+#ifdef DEBUG_TRACES
+ std::cout << "filt(Sigma) is NaN : filt(Sigma) =" << complex.filtration(f_simplex) << std::endl;
+#endif // DEBUG_TRACES
+ }
+ propagate_alpha_filtration(complex, f_simplex, decr_dim);
+ }
+ }
+ }
+ // --------------------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------------------
+ // As Alpha value is an approximation, we have to make filtration non decreasing while increasing the dimension
+ complex.make_filtration_non_decreasing();
+ // Remove all simplices that have a filtration value greater than max_alpha_square
+ complex.prune_above_filtration(max_alpha_square);
+ // --------------------------------------------------------------------------------------------
+ return true;
+ }
+
+ 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 : complex.boundary_simplex_range(f_simplex)) {
+#ifdef DEBUG_TRACES
+ std::cout << " | --------------------------------------------------\n";
+ std::cout << " | Tau ";
+ for (auto vertex : complex.simplex_vertex_range(f_boundary)) {
+ std::cout << vertex << " ";
+ }
+ std::cout << "is a face of Sigma\n";
+ 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(complex.filtration(f_boundary))) {
+ // ### filt(Tau) = fmin(filt(Tau), filt(Sigma))
+ 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)) = " << complex.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 : 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 : 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
+ // 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 = complex.filtration(f_simplex);
+ complex.assign_filtration(f_boundary, alpha_complex_filtration);
+#ifdef DEBUG_TRACES
+ std::cout << " | filt(Tau) = filt(Sigma) = " << complex.filtration(f_boundary) << std::endl;
+#endif // DEBUG_TRACES
+ }
+ }
+ }
+ }
+ }
+};
+
+} // namespace alpha_complex
+
+namespace alphacomplex = alpha_complex;
+
+} // namespace Gudhi
+
+#endif // ALPHA_COMPLEX_H_
diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp
new file mode 100644
index 00000000..7380547f
--- /dev/null
+++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp
@@ -0,0 +1,286 @@
+/* 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
+ *
+ * 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/>.
+ */
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE "alpha_complex"
+#include <boost/test/unit_test.hpp>
+
+#include <CGAL/Delaunay_triangulation.h>
+#include <CGAL/Epick_d.h>
+
+#include <cmath> // float comparison
+#include <limits>
+#include <string>
+#include <vector>
+
+#include <gudhi/Alpha_complex.h>
+// to construct a simplex_tree from Delaunay_triangulation
+#include <gudhi/graph_simplicial_complex.h>
+#include <gudhi/Simplex_tree.h>
+#include <boost/mpl/list.hpp>
+
+// Use dynamic_dimension_tag for the user to be able to set dimension
+typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel_d;
+// Use static dimension_tag for the user not to be able to set dimension
+typedef CGAL::Epick_d< CGAL::Dimension_tag<2> > Kernel_s;
+// The triangulation uses the default instantiation of the TriangulationDataStructure template parameter
+
+typedef boost::mpl::list<Kernel_d, Kernel_s> list_of_kernel_variants;
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_from_OFF_file, TestedKernel, list_of_kernel_variants) {
+ // ----------------------------------------------------------------------------
+ //
+ // Init of an alpha-complex from a OFF file
+ //
+ // ----------------------------------------------------------------------------
+ std::string off_file_name("alphacomplexdoc.off");
+ double max_alpha_square_value = 60.0;
+ std::cout << "========== OFF FILE NAME = " << off_file_name << " - alpha²=" <<
+ max_alpha_square_value << "==========" << std::endl;
+
+ Gudhi::alpha_complex::Alpha_complex<TestedKernel> alpha_complex_from_file(off_file_name);
+
+ std::cout << "alpha_complex_from_points.number_of_vertices()=" << alpha_complex_from_file.number_of_vertices()
+ << std::endl;
+ BOOST_CHECK(alpha_complex_from_file.number_of_vertices() == 7);
+
+ Gudhi::Simplex_tree<> simplex_tree_60;
+ BOOST_CHECK(alpha_complex_from_file.create_complex(simplex_tree_60, max_alpha_square_value));
+
+ std::cout << "simplex_tree_60.dimension()=" << simplex_tree_60.dimension() << std::endl;
+ BOOST_CHECK(simplex_tree_60.dimension() == 2);
+
+ std::cout << "alpha_complex_from_points.number_of_vertices()=" << alpha_complex_from_file.number_of_vertices()
+ << std::endl;
+ BOOST_CHECK(alpha_complex_from_file.number_of_vertices() == 7);
+
+ std::cout << "simplex_tree_60.num_vertices()=" << simplex_tree_60.num_vertices() << std::endl;
+ BOOST_CHECK(simplex_tree_60.num_vertices() == 7);
+
+ std::cout << "simplex_tree_60.num_simplices()=" << simplex_tree_60.num_simplices() << std::endl;
+ BOOST_CHECK(simplex_tree_60.num_simplices() == 25);
+
+ max_alpha_square_value = 59.0;
+ std::cout << "========== OFF FILE NAME = " << off_file_name << " - alpha²=" <<
+ max_alpha_square_value << "==========" << std::endl;
+
+ Gudhi::Simplex_tree<> simplex_tree_59;
+ BOOST_CHECK(alpha_complex_from_file.create_complex(simplex_tree_59, max_alpha_square_value));
+
+ std::cout << "simplex_tree_59.dimension()=" << simplex_tree_59.dimension() << std::endl;
+ BOOST_CHECK(simplex_tree_59.dimension() == 2);
+
+ std::cout << "simplex_tree_59.num_vertices()=" << simplex_tree_59.num_vertices() << std::endl;
+ BOOST_CHECK(simplex_tree_59.num_vertices() == 7);
+
+ std::cout << "simplex_tree_59.num_simplices()=" << simplex_tree_59.num_simplices() << std::endl;
+ BOOST_CHECK(simplex_tree_59.num_simplices() == 23);
+}
+
+bool are_almost_the_same(float a, float b) {
+ return std::fabs(a - b) < std::numeric_limits<float>::epsilon();
+}
+
+// Use static dimension_tag for the user not to be able to set dimension
+typedef CGAL::Epick_d< CGAL::Dimension_tag<4> > Kernel_4;
+typedef Kernel_4::Point_d Point_4;
+typedef std::vector<Point_4> Vector_4_Points;
+
+bool is_point_in_list(Vector_4_Points points_list, Point_4 point) {
+ for (auto& point_in_list : points_list) {
+ if (point_in_list == point) {
+ return true; // point found
+ }
+ }
+ return false; // point not found
+}
+
+BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) {
+ // ----------------------------------------------------------------------------
+ // Init of a list of points
+ // ----------------------------------------------------------------------------
+ Vector_4_Points points;
+ std::vector<double> coords = { 0.0, 0.0, 0.0, 1.0 };
+ points.push_back(Point_4(coords.begin(), coords.end()));
+ coords = { 0.0, 0.0, 1.0, 0.0 };
+ points.push_back(Point_4(coords.begin(), coords.end()));
+ coords = { 0.0, 1.0, 0.0, 0.0 };
+ points.push_back(Point_4(coords.begin(), coords.end()));
+ coords = { 1.0, 0.0, 0.0, 0.0 };
+ points.push_back(Point_4(coords.begin(), coords.end()));
+
+ // ----------------------------------------------------------------------------
+ // Init of an alpha complex from the list of points
+ // ----------------------------------------------------------------------------
+ Gudhi::alpha_complex::Alpha_complex<Kernel_4> alpha_complex_from_points(points);
+
+ std::cout << "========== Alpha_complex_from_points ==========" << std::endl;
+
+ Gudhi::Simplex_tree<> simplex_tree;
+ BOOST_CHECK(alpha_complex_from_points.create_complex(simplex_tree));
+
+ std::cout << "alpha_complex_from_points.number_of_vertices()=" << alpha_complex_from_points.number_of_vertices()
+ << std::endl;
+ BOOST_CHECK(alpha_complex_from_points.number_of_vertices() == points.size());
+
+ // Another way to check num_simplices
+ std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl;
+ int num_simplices = 0;
+ for (auto f_simplex : simplex_tree.filtration_simplex_range()) {
+ num_simplices++;
+ std::cout << " ( ";
+ for (auto vertex : simplex_tree.simplex_vertex_range(f_simplex)) {
+ std::cout << vertex << " ";
+ }
+ std::cout << ") -> " << "[" << simplex_tree.filtration(f_simplex) << "] ";
+ std::cout << std::endl;
+ }
+ BOOST_CHECK(num_simplices == 15);
+ std::cout << "simplex_tree.num_simplices()=" << simplex_tree.num_simplices() << std::endl;
+ BOOST_CHECK(simplex_tree.num_simplices() == 15);
+
+ std::cout << "simplex_tree.dimension()=" << simplex_tree.dimension() << std::endl;
+ BOOST_CHECK(simplex_tree.dimension() == 4);
+ std::cout << "simplex_tree.num_vertices()=" << simplex_tree.num_vertices() << std::endl;
+ BOOST_CHECK(simplex_tree.num_vertices() == 4);
+
+ for (auto f_simplex : simplex_tree.filtration_simplex_range()) {
+ switch (simplex_tree.dimension(f_simplex)) {
+ case 0:
+ BOOST_CHECK(are_almost_the_same(simplex_tree.filtration(f_simplex), 0.0));
+ break;
+ case 1:
+ BOOST_CHECK(are_almost_the_same(simplex_tree.filtration(f_simplex), 1.0/2.0));
+ break;
+ case 2:
+ BOOST_CHECK(are_almost_the_same(simplex_tree.filtration(f_simplex), 2.0/3.0));
+ break;
+ case 3:
+ BOOST_CHECK(are_almost_the_same(simplex_tree.filtration(f_simplex), 3.0/4.0));
+ break;
+ default:
+ BOOST_CHECK(false); // Shall not happen
+ break;
+ }
+ }
+
+ Point_4 p0 = alpha_complex_from_points.get_point(0);
+ std::cout << "alpha_complex_from_points.get_point(0)=" << p0 << std::endl;
+ BOOST_CHECK(4 == p0.dimension());
+ BOOST_CHECK(is_point_in_list(points, p0));
+
+ Point_4 p1 = alpha_complex_from_points.get_point(1);
+ std::cout << "alpha_complex_from_points.get_point(1)=" << p1 << std::endl;
+ BOOST_CHECK(4 == p1.dimension());
+ BOOST_CHECK(is_point_in_list(points, p1));
+
+ Point_4 p2 = alpha_complex_from_points.get_point(2);
+ std::cout << "alpha_complex_from_points.get_point(2)=" << p2 << std::endl;
+ BOOST_CHECK(4 == p2.dimension());
+ BOOST_CHECK(is_point_in_list(points, p2));
+
+ Point_4 p3 = alpha_complex_from_points.get_point(3);
+ std::cout << "alpha_complex_from_points.get_point(3)=" << p3 << std::endl;
+ BOOST_CHECK(4 == p3.dimension());
+ BOOST_CHECK(is_point_in_list(points, p3));
+
+ // Test to the limit
+ BOOST_CHECK_THROW (alpha_complex_from_points.get_point(4), std::out_of_range);
+ BOOST_CHECK_THROW (alpha_complex_from_points.get_point(-1), std::out_of_range);
+ BOOST_CHECK_THROW (alpha_complex_from_points.get_point(1234), std::out_of_range);
+
+ // Test after prune_above_filtration
+ bool modified = simplex_tree.prune_above_filtration(0.6);
+ if (modified) {
+ simplex_tree.initialize_filtration();
+ }
+ BOOST_CHECK(modified);
+
+ // Another way to check num_simplices
+ std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl;
+ num_simplices = 0;
+ for (auto f_simplex : simplex_tree.filtration_simplex_range()) {
+ num_simplices++;
+ std::cout << " ( ";
+ for (auto vertex : simplex_tree.simplex_vertex_range(f_simplex)) {
+ std::cout << vertex << " ";
+ }
+ std::cout << ") -> " << "[" << simplex_tree.filtration(f_simplex) << "] ";
+ std::cout << std::endl;
+ }
+ BOOST_CHECK(num_simplices == 10);
+ std::cout << "simplex_tree.num_simplices()=" << simplex_tree.num_simplices() << std::endl;
+ BOOST_CHECK(simplex_tree.num_simplices() == 10);
+
+ std::cout << "simplex_tree.dimension()=" << simplex_tree.dimension() << std::endl;
+ BOOST_CHECK(simplex_tree.dimension() == 4);
+ std::cout << "simplex_tree.num_vertices()=" << simplex_tree.num_vertices() << std::endl;
+ BOOST_CHECK(simplex_tree.num_vertices() == 4);
+
+ for (auto f_simplex : simplex_tree.filtration_simplex_range()) {
+ switch (simplex_tree.dimension(f_simplex)) {
+ case 0:
+ BOOST_CHECK(are_almost_the_same(simplex_tree.filtration(f_simplex), 0.0));
+ break;
+ case 1:
+ BOOST_CHECK(are_almost_the_same(simplex_tree.filtration(f_simplex), 1.0/2.0));
+ break;
+ default:
+ BOOST_CHECK(false); // Shall not happen
+ break;
+ }
+ }
+
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_from_empty_points, TestedKernel, list_of_kernel_variants) {
+ std::cout << "========== Alpha_complex_from_empty_points ==========" << std::endl;
+
+ // ----------------------------------------------------------------------------
+ // Init of an empty list of points
+ // ----------------------------------------------------------------------------
+ std::vector<typename TestedKernel::Point_d> points;
+
+ // ----------------------------------------------------------------------------
+ // Init of an alpha complex from the list of points
+ // ----------------------------------------------------------------------------
+ Gudhi::alpha_complex::Alpha_complex<TestedKernel> alpha_complex_from_points(points);
+
+ // Test to the limit
+ BOOST_CHECK_THROW (alpha_complex_from_points.get_point(0), std::out_of_range);
+
+ Gudhi::Simplex_tree<> simplex_tree;
+ BOOST_CHECK(!alpha_complex_from_points.create_complex(simplex_tree));
+
+ std::cout << "alpha_complex_from_points.number_of_vertices()=" << alpha_complex_from_points.number_of_vertices()
+ << std::endl;
+ BOOST_CHECK(alpha_complex_from_points.number_of_vertices() == points.size());
+
+ std::cout << "simplex_tree.num_simplices()=" << simplex_tree.num_simplices() << std::endl;
+ BOOST_CHECK(simplex_tree.num_simplices() == 0);
+
+ std::cout << "simplex_tree.dimension()=" << simplex_tree.dimension() << std::endl;
+ BOOST_CHECK(simplex_tree.dimension() == -1);
+
+ std::cout << "simplex_tree.num_vertices()=" << simplex_tree.num_vertices() << std::endl;
+ BOOST_CHECK(simplex_tree.num_vertices() == 0);
+}
diff --git a/src/Alpha_complex/test/CMakeLists.txt b/src/Alpha_complex/test/CMakeLists.txt
new file mode 100644
index 00000000..efc0565f
--- /dev/null
+++ b/src/Alpha_complex/test/CMakeLists.txt
@@ -0,0 +1,32 @@
+cmake_minimum_required(VERSION 2.6)
+project(Alpha_complex_tests)
+
+if (GCOVR_PATH)
+ # for gcovr to make coverage reports - Corbera Jenkins plugin
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
+endif()
+if (GPROF_PATH)
+ # for gprof to make coverage reports - Jenkins
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg")
+endif()
+
+if(CGAL_FOUND)
+ if (NOT CGAL_VERSION VERSION_LESS 4.7.0)
+ if (EIGEN3_FOUND)
+ add_executable ( AlphaComplexUT Alpha_complex_unit_test.cpp )
+ target_link_libraries(AlphaComplexUT ${Boost_SYSTEM_LIBRARY} ${Boost_THREAD_LIBRARY} ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+ if (TBB_FOUND)
+ target_link_libraries(AlphaComplexUT ${TBB_LIBRARIES})
+ endif()
+
+ # Do not forget to copy test files in current binary dir
+ file(COPY "${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
+
+ add_test(AlphaComplexUT ${CMAKE_CURRENT_BINARY_DIR}/AlphaComplexUT
+ # XML format for Jenkins xUnit plugin
+ --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/AlphaComplexUT.xml --log_level=test_suite --report_level=no)
+
+ endif(EIGEN3_FOUND)
+ endif (NOT CGAL_VERSION VERSION_LESS 4.7.0)
+endif(CGAL_FOUND)
+
diff --git a/src/Alpha_complex/test/README b/src/Alpha_complex/test/README
new file mode 100644
index 00000000..45b87d91
--- /dev/null
+++ b/src/Alpha_complex/test/README
@@ -0,0 +1,12 @@
+To compile:
+***********
+
+cmake .
+make
+
+To launch with details:
+***********************
+
+./AlphaComplexUnitTest --report_level=detailed --log_level=all
+
+ ==> echo $? returns 0 in case of success (non-zero otherwise)
diff --git a/src/Bitmap_cubical_complex/doc/Cubical_complex_representation.ipe b/src/Bitmap_cubical_complex/doc/Cubical_complex_representation.ipe
new file mode 100644
index 00000000..bec245e7
--- /dev/null
+++ b/src/Bitmap_cubical_complex/doc/Cubical_complex_representation.ipe
@@ -0,0 +1,732 @@
+<?xml version="1.0"?>
+<!DOCTYPE ipe SYSTEM "ipe.dtd">
+<ipe version="70107" creator="Ipe 7.1.10">
+<info created="D:20160330102945" modified="D:20160330104654"/>
+<ipestyle name="basic">
+<symbol name="arrow/arc(spx)">
+<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/farc(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/ptarc(spx)">
+<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-0.8 0 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/fptarc(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-0.8 0 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="mark/circle(sx)" transformations="translations">
+<path fill="sym-stroke">
+0.6 0 0 0.6 0 0 e
+0.4 0 0 0.4 0 0 e
+</path>
+</symbol>
+<symbol name="mark/disk(sx)" transformations="translations">
+<path fill="sym-stroke">
+0.6 0 0 0.6 0 0 e
+</path>
+</symbol>
+<symbol name="mark/fdisk(sfx)" transformations="translations">
+<group>
+<path fill="sym-fill">
+0.5 0 0 0.5 0 0 e
+</path>
+<path fill="sym-stroke" fillrule="eofill">
+0.6 0 0 0.6 0 0 e
+0.4 0 0 0.4 0 0 e
+</path>
+</group>
+</symbol>
+<symbol name="mark/box(sx)" transformations="translations">
+<path fill="sym-stroke" fillrule="eofill">
+-0.6 -0.6 m
+0.6 -0.6 l
+0.6 0.6 l
+-0.6 0.6 l
+h
+-0.4 -0.4 m
+0.4 -0.4 l
+0.4 0.4 l
+-0.4 0.4 l
+h
+</path>
+</symbol>
+<symbol name="mark/square(sx)" transformations="translations">
+<path fill="sym-stroke">
+-0.6 -0.6 m
+0.6 -0.6 l
+0.6 0.6 l
+-0.6 0.6 l
+h
+</path>
+</symbol>
+<symbol name="mark/fsquare(sfx)" transformations="translations">
+<group>
+<path fill="sym-fill">
+-0.5 -0.5 m
+0.5 -0.5 l
+0.5 0.5 l
+-0.5 0.5 l
+h
+</path>
+<path fill="sym-stroke" fillrule="eofill">
+-0.6 -0.6 m
+0.6 -0.6 l
+0.6 0.6 l
+-0.6 0.6 l
+h
+-0.4 -0.4 m
+0.4 -0.4 l
+0.4 0.4 l
+-0.4 0.4 l
+h
+</path>
+</group>
+</symbol>
+<symbol name="mark/cross(sx)" transformations="translations">
+<group>
+<path fill="sym-stroke">
+-0.43 -0.57 m
+0.57 0.43 l
+0.43 0.57 l
+-0.57 -0.43 l
+h
+</path>
+<path fill="sym-stroke">
+-0.43 0.57 m
+0.57 -0.43 l
+0.43 -0.57 l
+-0.57 0.43 l
+h
+</path>
+</group>
+</symbol>
+<symbol name="arrow/fnormal(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/pointed(spx)">
+<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-0.8 0 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/fpointed(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-0.8 0 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/linear(spx)">
+<path stroke="sym-stroke" pen="sym-pen">
+-1 0.333 m
+0 0 l
+-1 -0.333 l
+</path>
+</symbol>
+<symbol name="arrow/fdouble(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+-1 0 m
+-2 0.333 l
+-2 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/double(spx)">
+<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+-1 0 m
+-2 0.333 l
+-2 -0.333 l
+h
+</path>
+</symbol>
+<pen name="heavier" value="0.8"/>
+<pen name="fat" value="1.2"/>
+<pen name="ultrafat" value="2"/>
+<symbolsize name="large" value="5"/>
+<symbolsize name="small" value="2"/>
+<symbolsize name="tiny" value="1.1"/>
+<arrowsize name="large" value="10"/>
+<arrowsize name="small" value="5"/>
+<arrowsize name="tiny" value="3"/>
+<color name="red" value="1 0 0"/>
+<color name="green" value="0 1 0"/>
+<color name="blue" value="0 0 1"/>
+<color name="yellow" value="1 1 0"/>
+<color name="orange" value="1 0.647 0"/>
+<color name="gold" value="1 0.843 0"/>
+<color name="purple" value="0.627 0.125 0.941"/>
+<color name="gray" value="0.745"/>
+<color name="brown" value="0.647 0.165 0.165"/>
+<color name="navy" value="0 0 0.502"/>
+<color name="pink" value="1 0.753 0.796"/>
+<color name="seagreen" value="0.18 0.545 0.341"/>
+<color name="turquoise" value="0.251 0.878 0.816"/>
+<color name="violet" value="0.933 0.51 0.933"/>
+<color name="darkblue" value="0 0 0.545"/>
+<color name="darkcyan" value="0 0.545 0.545"/>
+<color name="darkgray" value="0.663"/>
+<color name="darkgreen" value="0 0.392 0"/>
+<color name="darkmagenta" value="0.545 0 0.545"/>
+<color name="darkorange" value="1 0.549 0"/>
+<color name="darkred" value="0.545 0 0"/>
+<color name="lightblue" value="0.678 0.847 0.902"/>
+<color name="lightcyan" value="0.878 1 1"/>
+<color name="lightgray" value="0.827"/>
+<color name="lightgreen" value="0.565 0.933 0.565"/>
+<color name="lightyellow" value="1 1 0.878"/>
+<dashstyle name="dashed" value="[4] 0"/>
+<dashstyle name="dotted" value="[1 3] 0"/>
+<dashstyle name="dash dotted" value="[4 2 1 2] 0"/>
+<dashstyle name="dash dot dotted" value="[4 2 1 2 1 2] 0"/>
+<textsize name="large" value="\large"/>
+<textsize name="Large" value="\Large"/>
+<textsize name="LARGE" value="\LARGE"/>
+<textsize name="huge" value="\huge"/>
+<textsize name="Huge" value="\Huge"/>
+<textsize name="small" value="\small"/>
+<textsize name="footnote" value="\footnotesize"/>
+<textsize name="tiny" value="\tiny"/>
+<textstyle name="center" begin="\begin{center}" end="\end{center}"/>
+<textstyle name="itemize" begin="\begin{itemize}" end="\end{itemize}"/>
+<textstyle name="item" begin="\begin{itemize}\item{}" end="\end{itemize}"/>
+<gridsize name="4 pts" value="4"/>
+<gridsize name="8 pts (~3 mm)" value="8"/>
+<gridsize name="16 pts (~6 mm)" value="16"/>
+<gridsize name="32 pts (~12 mm)" value="32"/>
+<gridsize name="10 pts (~3.5 mm)" value="10"/>
+<gridsize name="20 pts (~7 mm)" value="20"/>
+<gridsize name="14 pts (~5 mm)" value="14"/>
+<gridsize name="28 pts (~10 mm)" value="28"/>
+<gridsize name="56 pts (~20 mm)" value="56"/>
+<anglesize name="90 deg" value="90"/>
+<anglesize name="60 deg" value="60"/>
+<anglesize name="45 deg" value="45"/>
+<anglesize name="30 deg" value="30"/>
+<anglesize name="22.5 deg" value="22.5"/>
+<opacity name="10%" value="0.1"/>
+<opacity name="30%" value="0.3"/>
+<opacity name="50%" value="0.5"/>
+<opacity name="75%" value="0.75"/>
+<tiling name="falling" angle="-60" step="4" width="1"/>
+<tiling name="rising" angle="30" step="4" width="1"/>
+</ipestyle>
+<page>
+<layer name="alpha"/>
+<view layers="alpha" active="alpha"/>
+<path layer="alpha" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<text transformations="translations" pos="180 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">0</text>
+<path stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<text transformations="translations" pos="212 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">1</text>
+<path matrix="1 0 0 1 64 0" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<text matrix="1 0 0 1 64 0" transformations="translations" pos="180 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">2</text>
+<path matrix="1 0 0 1 64 0" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<text matrix="1 0 0 1 64 0" transformations="translations" pos="212 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">3</text>
+<path matrix="1 0 0 1 128 0" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<text matrix="1 0 0 1 128 0" transformations="translations" pos="180 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">4</text>
+<path matrix="1 0 0 1 128 0" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<text matrix="1 0 0 1 128 0" transformations="translations" pos="212 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">5</text>
+<path matrix="1 0 0 1 192 0" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<text matrix="1 0 0 1 192 0" transformations="translations" pos="180 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">6</text>
+<path matrix="1 0 0 1 192 0" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<text matrix="1 0 0 1 192 0" transformations="translations" pos="212 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">7</text>
+<path matrix="1 0 0 1 256 0" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<text matrix="1 0 0 1 256 0" transformations="translations" pos="180 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">8</text>
+<path matrix="1 0 0 1 0 -32" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<text matrix="1 0 0 1 0 -48" transformations="translations" pos="180 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">1</text>
+<path matrix="1 0 0 1 0 -32" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<path matrix="1 0 0 1 64 -32" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<text matrix="1 0 0 1 64 -48" transformations="translations" pos="180 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">2</text>
+<path matrix="1 0 0 1 64 -32" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<text matrix="1 0 0 1 96 -48" transformations="translations" pos="212 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">3</text>
+<path matrix="1 0 0 1 128 -32" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<text matrix="1 0 0 1 192 -48" transformations="translations" pos="180 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">4</text>
+<path matrix="1 0 0 1 128 -32" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<text matrix="1 0 0 1 224 -48" transformations="translations" pos="212 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">5</text>
+<path matrix="1 0 0 1 192 -32" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<path matrix="1 0 0 1 192 -32" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<path matrix="1 0 0 1 256 -32" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<path matrix="1 0 0 1 -32 0" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<path stroke="black" fill="lightgreen">
+160 496 m
+160 544 l
+144 544 l
+144 496 l
+h
+</path>
+<path matrix="1 0 0 1 -32 64" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<path matrix="1 0 0 1 0 64" stroke="black" fill="lightgreen">
+160 496 m
+160 544 l
+144 544 l
+144 496 l
+h
+</path>
+<path matrix="1 0 0 1 -32 128" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<text transformations="translations" pos="132 484" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">1</text>
+<text transformations="translations" pos="132 548" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">2</text>
+<text transformations="translations" pos="132 612" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">3</text>
+<path matrix="1 0 0 1 32 0" stroke="black" fill="lightgreen">
+160 496 m
+160 544 l
+144 544 l
+144 496 l
+h
+</path>
+<text transformations="translations" pos="180 516" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">9</text>
+<path matrix="1 0 0 1 96 0" stroke="black" fill="lightgreen">
+160 496 m
+160 544 l
+144 544 l
+144 496 l
+h
+</path>
+<text transformations="translations" pos="244 516" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">11</text>
+<path matrix="1 0 0 1 160 0" stroke="black" fill="lightgreen">
+160 496 m
+160 544 l
+144 544 l
+144 496 l
+h
+</path>
+<path matrix="1 0 0 1 224 0" stroke="black" fill="lightgreen">
+160 496 m
+160 544 l
+144 544 l
+144 496 l
+h
+</path>
+<path matrix="1 0 0 1 288 0" stroke="black" fill="lightgreen">
+160 496 m
+160 544 l
+144 544 l
+144 496 l
+h
+</path>
+<path matrix="1 0 0 1 0 64" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<path matrix="1 0 0 1 0 64" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<path matrix="1 0 0 1 64 64" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<path matrix="1 0 0 1 64 64" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<path matrix="1 0 0 1 128 64" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<path matrix="1 0 0 1 128 64" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<path matrix="1 0 0 1 192 64" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<path matrix="1 0 0 1 192 64" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<path matrix="1 0 0 1 256 64" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<path matrix="1 0 0 1 0 128" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<path matrix="1 0 0 1 0 128" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<path matrix="1 0 0 1 64 128" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<path matrix="1 0 0 1 64 128" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<path matrix="1 0 0 1 128 128" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<path matrix="1 0 0 1 128 128" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<path matrix="1 0 0 1 192 128" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<path matrix="1 0 0 1 192 128" stroke="black" fill="lightgreen">
+192 496 m
+192 480 l
+240 480 l
+240 496 l
+h
+</path>
+<path matrix="1 0 0 1 256 128" stroke="black" fill="lightblue">
+176 496 m
+176 480 l
+192 480 l
+192 496 l
+h
+</path>
+<path matrix="1 0 0 1 32 64" stroke="black" fill="lightgreen">
+160 496 m
+160 544 l
+144 544 l
+144 496 l
+h
+</path>
+<path matrix="1 0 0 1 96 64" stroke="black" fill="lightgreen">
+160 496 m
+160 544 l
+144 544 l
+144 496 l
+h
+</path>
+<path matrix="1 0 0 1 160 64" stroke="black" fill="lightgreen">
+160 496 m
+160 544 l
+144 544 l
+144 496 l
+h
+</path>
+<path matrix="1 0 0 1 224 64" stroke="black" fill="lightgreen">
+160 496 m
+160 544 l
+144 544 l
+144 496 l
+h
+</path>
+<path matrix="1 0 0 1 288 64" stroke="black" fill="lightgreen">
+160 496 m
+160 544 l
+144 544 l
+144 496 l
+h
+</path>
+<path stroke="black" fill="lightgray">
+192 544 m
+192 496 l
+240 496 l
+240 544 l
+h
+</path>
+<path matrix="1 0 0 1 64 0" stroke="black" fill="lightgray">
+192 544 m
+192 496 l
+240 496 l
+240 544 l
+h
+</path>
+<path matrix="1 0 0 1 128 0" stroke="black" fill="lightgray">
+192 544 m
+192 496 l
+240 496 l
+240 544 l
+h
+</path>
+<path matrix="1 0 0 1 192 0" stroke="black" fill="lightgray">
+192 544 m
+192 496 l
+240 496 l
+240 544 l
+h
+</path>
+<path matrix="1 0 0 1 0 64" stroke="black" fill="lightgray">
+192 544 m
+192 496 l
+240 496 l
+240 544 l
+h
+</path>
+<path matrix="1 0 0 1 64 64" stroke="black" fill="lightgray">
+192 544 m
+192 496 l
+240 496 l
+240 544 l
+h
+</path>
+<path matrix="1 0 0 1 128 64" stroke="black" fill="lightgray">
+192 544 m
+192 496 l
+240 496 l
+240 544 l
+h
+</path>
+<path matrix="1 0 0 1 192 64" stroke="black" fill="lightgray">
+192 544 m
+192 496 l
+240 496 l
+240 544 l
+h
+</path>
+<text transformations="translations" pos="212 516" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">10</text>
+<text transformations="translations" pos="276 516" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">12</text>
+<text transformations="translations" pos="308 516" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">13</text>
+<text transformations="translations" pos="340 516" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">14</text>
+<text transformations="translations" pos="372 516" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">15</text>
+<text transformations="translations" pos="404 516" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">16</text>
+<text transformations="translations" pos="436 516" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">17</text>
+<text transformations="translations" pos="180 548" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">18</text>
+<text transformations="translations" pos="212 548" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">19</text>
+<text transformations="translations" pos="244 548" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">20</text>
+<text transformations="translations" pos="276 548" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">21</text>
+<text transformations="translations" pos="308 548" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">22</text>
+<text transformations="translations" pos="340 548" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">23</text>
+<text transformations="translations" pos="372 548" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">24</text>
+<text transformations="translations" pos="404 548" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">25</text>
+<text transformations="translations" pos="436 548" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">26</text>
+<text transformations="translations" pos="180 580" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">27</text>
+<text transformations="translations" pos="212 580" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">28</text>
+<text transformations="translations" pos="244 580" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">29</text>
+<text transformations="translations" pos="276 580" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">30</text>
+<text transformations="translations" pos="308 580" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">31</text>
+<text transformations="translations" pos="340 580" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">32</text>
+<text transformations="translations" pos="372 580" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">33</text>
+<text transformations="translations" pos="404 580" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">34</text>
+<text transformations="translations" pos="436 580" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">35</text>
+<text transformations="translations" pos="180 612" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">36</text>
+<text transformations="translations" pos="212 612" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">37</text>
+<text transformations="translations" pos="244 612" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">38</text>
+<text transformations="translations" pos="276 612" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">39</text>
+<text transformations="translations" pos="308 612" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">40</text>
+<text transformations="translations" pos="340 612" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">41</text>
+<text transformations="translations" pos="372 612" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">42</text>
+<text transformations="translations" pos="404 612" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">43</text>
+<text transformations="translations" pos="436 612" stroke="black" type="label" width="9.963" height="6.42" depth="0" valign="baseline">44</text>
+<path stroke="black" arrow="normal/normal">
+152 456 m
+472 456 l
+</path>
+<path stroke="black" arrow="normal/normal">
+152 456 m
+152 648 l
+</path>
+</page>
+</ipe>
diff --git a/src/Bitmap_cubical_complex/doc/Cubical_complex_representation.png b/src/Bitmap_cubical_complex/doc/Cubical_complex_representation.png
new file mode 100644
index 00000000..afb2a75e
--- /dev/null
+++ b/src/Bitmap_cubical_complex/doc/Cubical_complex_representation.png
Binary files differ
diff --git a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h
new file mode 100644
index 00000000..5963caa3
--- /dev/null
+++ b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h
@@ -0,0 +1,159 @@
+/* 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): Pawel Dlotko
+ *
+ * Copyright (C) 2015 INRIA Sophia-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 DOC_GUDHI_CUBICAL_COMPLEX_COMPLEX_H_
+#define DOC_GUDHI_CUBICAL_COMPLEX_COMPLEX_H_
+
+namespace Gudhi {
+
+namespace cubical_complex {
+
+/** \defgroup cubical_complex Cubical complex
+ *
+ * \author Pawel Dlotko
+ *
+ * @{
+ *
+
+ * Bitmap_cubical_complex is an example of a structured complex useful in computational mathematics (specially rigorous
+ * numerics) and image analysis. The presented implementation of cubical complexes is based on the following
+ * definition.
+ *
+ * An <em>elementary interval</em> is an interval of a form \f$ [n,n+1] \f$, or \f$[n,n]\f$, for \f$ n \in \mathcal{Z}
+ * \f$. The first one is called <em>non-degenerate</em>, while the second one is \a degenerate interval. A
+ * <em>boundary of a elementary interval</em> is a chain \f$\partial [n,n+1] = [n+1,n+1]-[n,n] \f$ in case of
+ * non-degenerated elementary interval and \f$\partial [n,n] = 0 \f$ in case of degenerate elementary interval. An
+ * <em>elementary cube</em> \f$ C \f$ is a product of elementary intervals, \f$C=I_1 \times \ldots \times I_n\f$.
+ * <em>Embedding dimension</em> of a cube is n, the number of elementary intervals (degenerate or not) in the product.
+ * A <em>dimension of a cube</em> \f$C=I_1 \times ... \times I_n\f$ is the number of non degenerate elementary
+ * intervals in the product. A <em>boundary of a cube</em> \f$C=I_1 \times \ldots \times I_n\f$ is a chain obtained
+ * in the following way:
+ * \f[\partial C = (\partial I_1 \times \ldots \times I_n) + (I_1 \times \partial I_2 \times \ldots \times I_n) +
+ * \ldots + (I_1 \times I_2 \times \ldots \times \partial I_n).\f]
+ * A <em>cubical complex</em> \f$\mathcal{K}\f$ is a collection of cubes closed under operation of taking boundary
+ * (i.e. boundary of every cube from the collection is in the collection). A cube \f$C\f$ in cubical complex
+ * \f$\mathcal{K}\f$ is <em>maximal</em> if it is not in a boundary of any other cube in \f$\mathcal{K}\f$. A \a
+ * support of a cube \f$C\f$ is the set in \f$\mathbb{R}^n\f$ occupied by \f$C\f$ (\f$n\f$ is the embedding dimension
+ * of \f$C\f$).
+ *
+ * Cubes may be equipped with a filtration values in which case we have filtered cubical complex. All the cubical
+ * complexes considered in this implementation are filtered cubical complexes (although, the range of a filtration may
+ * be a set of two elements).
+ *
+ * For further details and theory of cubical complexes, please consult \cite kaczynski2004computational as well as the
+ * following paper \cite peikert2012topological .
+ *
+ * \section cubicalcomplexdatastructure Data structure.
+ *
+ * The implementation of Cubical complex provides a representation of complexes that occupy a rectangular region in
+ * \f$\mathbb{R}^n\f$. This extra assumption allows for a memory efficient way of storing cubical complexes in a form
+ * of so called bitmaps. Let \f$R = [b_1,e_1] \times \ldots \times [b_n,e_n]\f$, for \f$b_1,...b_n,e_1,...,e_n \in
+ * \mathbb{Z}\f$, \f$b_i \leq d_i\f$ be the considered rectangular region and let \f$\mathcal{K}\f$ be a filtered
+ * cubical complex having the rectangle \f$R\f$ as its support. Note that the structure of the coordinate system gives
+ * a way a lexicographical ordering of cells of \f$\mathcal{K}\f$. This ordering is a base of the presented
+ * bitmap-based implementation. In this implementation, the whole cubical complex is stored as a vector of the values
+ * of filtration. This, together with dimension of \f$\mathcal{K}\f$ and the sizes of \f$\mathcal{K}\f$ in all
+ * directions, allows to determine, dimension, neighborhood, boundary and coboundary of every cube \f$C \in
+ * \mathcal{K}\f$.
+ *
+ * \image html "Cubical_complex_representation.png" Cubical complex.
+ *
+ * Note that the cubical complex in the figure above is, in a natural way, a product of one dimensional cubical
+ * complexes in \f$\mathbb{R}\f$. The number of all cubes in each direction is equal \f$2n+1\f$, where \f$n\f$ is the
+ * number of maximal cubes in the considered direction. Let us consider a cube at the position \f$k\f$ in the bitmap.
+ * Knowing the sizes of the bitmap, by a series of modulo operation, we can determine which elementary intervals are
+ * present in the product that gives the cube \f$C\f$. In a similar way, we can compute boundary and the coboundary of
+ * each cube. Further details can be found in the literature.
+ *
+ * \section inputformat Input Format.
+ *
+ * In the current implantation, filtration is given at the maximal cubes, and it is then extended by the lower star
+ * filtration to all cubes. There are a number of constructors that can be used to construct cubical complex by users
+ * who want to use the code directly. They can be found in the \a Bitmap_cubical_complex class.
+ * Currently one input from a text file is used. It uses a format used already in Perseus software
+ * (http://www.sas.upenn.edu/~vnanda/perseus/) by Vidit Nanda.
+ * Below we are providing a description of the format. The first line contains a number d begin the dimension of the
+ * bitmap (2 in the example below). Next d lines are the numbers of top dimensional cubes in each dimensions (3 and 3
+ * in the example below). Next, in lexicographical order, the filtration of top dimensional cubes is given (1 4 6 8
+ * 20 4 7 6 5 in the example below).
+ *
+ *
+ * \image html "exampleBitmap.png" "Example of a input data."
+ *
+ * The input file for the following complex is:
+ * \verbatim
+2
+3
+3
+1
+4
+6
+8
+20
+4
+7
+6
+5
+\endverbatim
+
+ * \section PeriodicBoundaryConditions Periodic boundary conditions
+ * Often one would like to impose periodic boundary conditions to the cubical complex. Let \f$ I_1\times ... \times
+ * I_n \f$ be a box that is decomposed with a cubical complex \f$ \mathcal{K} \f$. Imposing periodic boundary
+ * conditions in the direction i, means that the left and the right side of a complex \f$ \mathcal{K} \f$ are
+ * considered the same. In particular, if for a bitmap \f$ \mathcal{K} \f$ periodic boundary conditions are imposed
+ * in all directions, then complex \f$ \mathcal{K} \f$ became n-dimensional torus. One can use various constructors
+ * from the file Bitmap_cubical_complex_periodic_boundary_conditions_base.h to construct cubical complex with periodic
+ * boundary conditions. One can also use Perseus style input files. To indicate periodic boundary conditions in a
+ * given direction, then number of top dimensional cells in this direction have to be multiplied by -1. For instance:
+
+ *\verbatim
+2
+-3
+3
+1
+4
+6
+8
+20
+4
+7
+6
+5
+\endverbatim
+
+ * Indicate that we have imposed periodic boundary conditions in the direction x, but not in the direction y.
+
+ * \section BitmapExamples Examples
+ * End user programs are available in example/Bitmap_cubical_complex folder.
+ *
+ * \copyright GNU General Public License v3.
+ */
+/** @} */ // end defgroup cubical_complex
+
+} // namespace cubical_complex
+
+namespace Cubical_complex = cubical_complex;
+
+} // namespace Gudhi
+
+#endif // DOC_GUDHI_CUBICAL_COMPLEX_COMPLEX_H_
diff --git a/src/Bitmap_cubical_complex/doc/bitmapAllCubes.png b/src/Bitmap_cubical_complex/doc/bitmapAllCubes.png
new file mode 100644
index 00000000..77167b13
--- /dev/null
+++ b/src/Bitmap_cubical_complex/doc/bitmapAllCubes.png
Binary files differ
diff --git a/src/Bitmap_cubical_complex/doc/exampleBitmap.png b/src/Bitmap_cubical_complex/doc/exampleBitmap.png
new file mode 100644
index 00000000..069c6eb2
--- /dev/null
+++ b/src/Bitmap_cubical_complex/doc/exampleBitmap.png
Binary files differ
diff --git a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp
new file mode 100644
index 00000000..e6bc6648
--- /dev/null
+++ b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp
@@ -0,0 +1,72 @@
+/* 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): Pawel Dlotko
+ *
+ * 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/>.
+ */
+
+
+#include <gudhi/reader_utils.h>
+#include <gudhi/Bitmap_cubical_complex.h>
+#include <gudhi/Persistent_cohomology.h>
+
+// standard stuff
+#include <iostream>
+#include <sstream>
+#include <vector>
+
+int main(int argc, char** argv) {
+ std::cout << "This program computes persistent homology, by using bitmap_cubical_complex class, of cubical " <<
+ "complexes provided in text files in Perseus style (the only numbered in the first line is a dimension D of a" <<
+ "bitmap. In the lines I between 2 and D+1 there are numbers of top dimensional cells in the direction I. Let " <<
+ "N denote product of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are " <<
+ "filtrations of top dimensional cells. We assume that the cells are in the lexicographical order. See " <<
+ "CubicalOneSphere.txt or CubicalTwoSphere.txt for example.\n" << std::endl;
+
+ int p = 2;
+ double min_persistence = 0;
+
+ if (argc != 2) {
+ std::cerr << "Wrong number of parameters. Please provide the name of a file with a Perseus style bitmap at " <<
+ "the input. The program will now terminate.\n";
+ return 1;
+ }
+
+ typedef Gudhi::cubical_complex::Bitmap_cubical_complex_base<double> Bitmap_cubical_complex_base;
+ typedef Gudhi::cubical_complex::Bitmap_cubical_complex<Bitmap_cubical_complex_base> Bitmap_cubical_complex;
+ typedef Gudhi::persistent_cohomology::Field_Zp Field_Zp;
+ typedef Gudhi::persistent_cohomology::Persistent_cohomology<Bitmap_cubical_complex, Field_Zp> Persistent_cohomology;
+
+ Bitmap_cubical_complex b(argv[1]);
+
+ // Compute the persistence diagram of the complex
+ Persistent_cohomology pcoh(b);
+ pcoh.init_coefficients(p); // initializes the coefficient field for homology
+ pcoh.compute_persistent_cohomology(min_persistence);
+
+ std::stringstream ss;
+ ss << argv[1] << "_persistence";
+ std::ofstream out(ss.str().c_str());
+ pcoh.output_diagram(out);
+ out.close();
+
+ std::cout << "Result in file: " << ss.str().c_str() << "\n";
+
+ return 0;
+}
+
diff --git a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp
new file mode 100644
index 00000000..839a4c89
--- /dev/null
+++ b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp
@@ -0,0 +1,74 @@
+/* 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): Pawel Dlotko
+ *
+ * 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/>.
+ */
+
+
+#include <gudhi/reader_utils.h>
+#include <gudhi/Bitmap_cubical_complex.h>
+#include <gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h>
+#include <gudhi/Persistent_cohomology.h>
+
+// standard stuff
+#include <iostream>
+#include <sstream>
+#include <vector>
+
+int main(int argc, char** argv) {
+ std::cout << "This program computes persistent homology, by using " <<
+ "Bitmap_cubical_complex_periodic_boundary_conditions class, of cubical complexes provided in text files in " <<
+ "Perseus style (the only numbered in the first line is a dimension D of a bitmap. In the lines I between 2 " <<
+ "and D+1 there are numbers of top dimensional cells in the direction I. Let N denote product of the numbers " <<
+ "in the lines between 2 and D. In the lines D+2 to D+2+N there are filtrations of top dimensional cells. We " <<
+ "assume that the cells are in the lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for" <<
+ " example.\n" << std::endl;
+
+ int p = 2;
+ double min_persistence = 0;
+
+ if (argc != 2) {
+ std::cerr << "Wrong number of parameters. Please provide the name of a file with a Perseus style bitmap at " <<
+ "the input. The program will now terminate.\n";
+ return 1;
+ }
+
+ typedef Gudhi::cubical_complex::Bitmap_cubical_complex_periodic_boundary_conditions_base<double> Bitmap_base;
+ typedef Gudhi::cubical_complex::Bitmap_cubical_complex< Bitmap_base > Bitmap_cubical_complex;
+
+ Bitmap_cubical_complex b(argv[1]);
+
+ typedef Gudhi::persistent_cohomology::Field_Zp Field_Zp;
+ typedef Gudhi::persistent_cohomology::Persistent_cohomology<Bitmap_cubical_complex, Field_Zp> Persistent_cohomology;
+ // Compute the persistence diagram of the complex
+ Persistent_cohomology pcoh(b, true);
+ pcoh.init_coefficients(p); // initializes the coefficient field for homology
+ pcoh.compute_persistent_cohomology(min_persistence);
+
+ std::stringstream ss;
+ ss << argv[1] << "_persistence";
+ std::ofstream out(ss.str().c_str());
+ pcoh.output_diagram(out);
+ out.close();
+
+ std::cout << "Result in file: " << ss.str().c_str() << "\n";
+
+ return 0;
+}
+
diff --git a/src/Bitmap_cubical_complex/example/CMakeLists.txt b/src/Bitmap_cubical_complex/example/CMakeLists.txt
new file mode 100644
index 00000000..2fddc514
--- /dev/null
+++ b/src/Bitmap_cubical_complex/example/CMakeLists.txt
@@ -0,0 +1,26 @@
+cmake_minimum_required(VERSION 2.6)
+project(Bitmap_cubical_complex_examples)
+
+add_executable ( Bitmap_cubical_complex Bitmap_cubical_complex.cpp )
+target_link_libraries(Bitmap_cubical_complex ${Boost_SYSTEM_LIBRARY})
+if (TBB_FOUND)
+ target_link_libraries(Bitmap_cubical_complex ${TBB_LIBRARIES})
+endif()
+add_test(Bitmap_cubical_complex_one_sphere ${CMAKE_CURRENT_BINARY_DIR}/Bitmap_cubical_complex ${CMAKE_SOURCE_DIR}/data/bitmap/CubicalOneSphere.txt)
+add_test(Bitmap_cubical_complex_two_sphere ${CMAKE_CURRENT_BINARY_DIR}/Bitmap_cubical_complex ${CMAKE_SOURCE_DIR}/data/bitmap/CubicalTwoSphere.txt)
+
+add_executable ( Random_bitmap_cubical_complex Random_bitmap_cubical_complex.cpp )
+target_link_libraries(Random_bitmap_cubical_complex ${Boost_SYSTEM_LIBRARY})
+if (TBB_FOUND)
+ target_link_libraries(Random_bitmap_cubical_complex ${TBB_LIBRARIES})
+endif()
+add_test(Random_bitmap_cubical_complex ${CMAKE_CURRENT_BINARY_DIR}/Random_bitmap_cubical_complex 2 100 100)
+
+add_executable ( Bitmap_cubical_complex_periodic_boundary_conditions Bitmap_cubical_complex_periodic_boundary_conditions.cpp )
+target_link_libraries(Bitmap_cubical_complex_periodic_boundary_conditions ${Boost_SYSTEM_LIBRARY})
+if (TBB_FOUND)
+ target_link_libraries(Bitmap_cubical_complex_periodic_boundary_conditions ${TBB_LIBRARIES})
+endif()
+add_test(Bitmap_cubical_complex_periodic_2d_torus ${CMAKE_CURRENT_BINARY_DIR}/Bitmap_cubical_complex_periodic_boundary_conditions ${CMAKE_SOURCE_DIR}/data/bitmap/2d_torus.txt)
+add_test(Bitmap_cubical_complex_periodic_3d_torus ${CMAKE_CURRENT_BINARY_DIR}/Bitmap_cubical_complex_periodic_boundary_conditions ${CMAKE_SOURCE_DIR}/data/bitmap/3d_torus.txt)
+
diff --git a/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp
new file mode 100644
index 00000000..16ad65a0
--- /dev/null
+++ b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp
@@ -0,0 +1,83 @@
+/* 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): Pawel Dlotko
+ *
+ * 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/>.
+ */
+
+
+// for persistence algorithm
+#include <gudhi/reader_utils.h>
+#include <gudhi/Bitmap_cubical_complex.h>
+#include <gudhi/Persistent_cohomology.h>
+
+// standard stuff
+#include <iostream>
+#include <sstream>
+#include <vector>
+
+int main(int argc, char** argv) {
+ srand(time(0));
+
+ std::cout << "This program computes persistent homology, by using bitmap_cubical_complex class, of cubical " <<
+ "complexes. The first parameter of the program is the dimension D of the bitmap. The next D parameters are " <<
+ "number of top dimensional cubes in each dimension of the bitmap. The program will create random cubical " <<
+ "complex of that sizes and compute persistent homology of it." << std::endl;
+
+ int p = 2;
+ double min_persistence = 0;
+
+ if (argc < 3) {
+ std::cerr << "Wrong number of parameters, the program will now terminate\n";
+ return 1;
+ }
+
+ size_t dimensionOfBitmap = (size_t) atoi(argv[1]);
+ std::vector< unsigned > sizes;
+ size_t multipliers = 1;
+ for (size_t dim = 0; dim != dimensionOfBitmap; ++dim) {
+ unsigned sizeInThisDimension = (unsigned) atoi(argv[2 + dim]);
+ sizes.push_back(sizeInThisDimension);
+ multipliers *= sizeInThisDimension;
+ }
+
+ std::vector< double > data;
+ for (size_t i = 0; i != multipliers; ++i) {
+ data.push_back(rand() / static_cast<double>(RAND_MAX));
+ }
+
+ typedef Gudhi::cubical_complex::Bitmap_cubical_complex_base<double> Bitmap_cubical_complex_base;
+ typedef Gudhi::cubical_complex::Bitmap_cubical_complex<Bitmap_cubical_complex_base> Bitmap_cubical_complex;
+ Bitmap_cubical_complex b(sizes, data);
+
+ // Compute the persistence diagram of the complex
+ typedef Gudhi::persistent_cohomology::Field_Zp Field_Zp;
+ typedef Gudhi::persistent_cohomology::Persistent_cohomology<Bitmap_cubical_complex, Field_Zp> Persistent_cohomology;
+ Persistent_cohomology pcoh(b);
+ pcoh.init_coefficients(p); // initializes the coefficient field for homology
+ pcoh.compute_persistent_cohomology(min_persistence);
+
+ std::stringstream ss;
+ ss << "randomComplex_persistence";
+ std::ofstream out(ss.str().c_str());
+ pcoh.output_diagram(out);
+ out.close();
+
+ return 0;
+}
+
diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h
new file mode 100644
index 00000000..5a87b9b8
--- /dev/null
+++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h
@@ -0,0 +1,595 @@
+/* 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): Pawel Dlotko
+ *
+ * Copyright (C) 2015 INRIA Sophia-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 BITMAP_CUBICAL_COMPLEX_H_
+#define BITMAP_CUBICAL_COMPLEX_H_
+
+#include <gudhi/Bitmap_cubical_complex_base.h>
+#include <gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h>
+
+#ifdef GUDHI_USE_TBB
+#include <tbb/parallel_sort.h>
+#endif
+
+#include <limits>
+#include <utility> // for pair<>
+#include <algorithm> // for sort
+#include <vector>
+#include <numeric> // for iota
+
+namespace Gudhi {
+
+namespace cubical_complex {
+
+// global variable, was used just for debugging.
+const bool globalDbg = false;
+
+template <typename T> class is_before_in_filtration;
+
+/**
+ * @brief Cubical complex represented as a bitmap.
+ * @ingroup cubical_complex
+ * @details This is a Bitmap_cubical_complex class. It joints a functionalities of Bitmap_cubical_complex_base and
+ * Bitmap_cubical_complex_periodic_boundary_conditions_base classes into
+ * Gudhi persistent homology engine. It is a template class that inherit from its template parameter. The template
+ * parameter is supposed to be either Bitmap_cubical_complex_base or
+ * Bitmap_cubical_complex_periodic_boundary_conditions_base class.
+ **/
+template <typename T>
+class Bitmap_cubical_complex : public T {
+ public:
+ //*********************************************//
+ // Typedefs and typenames
+ //*********************************************//
+ typedef size_t Simplex_key;
+ typedef typename T::filtration_type Filtration_value;
+ typedef Simplex_key Simplex_handle;
+
+
+ //*********************************************//
+ // Constructors
+ //*********************************************//
+ // Over here we need to define various input types. I am proposing the following ones:
+ // Perseus style
+ // TODO(PD) H5 files?
+ // TODO(PD) binary files with little endiangs / big endians ?
+ // TODO(PD) constructor from a vector of elements of a type T. ?
+
+ /**
+ * Constructor form a Perseus-style file.
+ **/
+ Bitmap_cubical_complex(const char* perseus_style_file) :
+ T(perseus_style_file), key_associated_to_simplex(this->total_number_of_cells + 1) {
+ if (globalDbg) {
+ std::cerr << "Bitmap_cubical_complex( const char* perseus_style_file )\n";
+ }
+ for (size_t i = 0; i != this->total_number_of_cells; ++i) {
+ this->key_associated_to_simplex[i] = i;
+ }
+ // we initialize this only once, in each constructor, when the bitmap is constructed.
+ // If the user decide to change some elements of the bitmap, then this procedure need
+ // to be called again.
+ this->initialize_simplex_associated_to_key();
+ }
+
+ /**
+ * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells
+ * in the following directions and vector of element of a type T
+ * with filtration on top dimensional cells.
+ **/
+ Bitmap_cubical_complex(const std::vector<unsigned>& dimensions,
+ const std::vector<typename T::filtration_type>& top_dimensional_cells) :
+ T(dimensions, top_dimensional_cells),
+ key_associated_to_simplex(this->total_number_of_cells + 1) {
+ for (size_t i = 0; i != this->total_number_of_cells; ++i) {
+ this->key_associated_to_simplex[i] = i;
+ }
+ // we initialize this only once, in each constructor, when the bitmap is constructed.
+ // If the user decide to change some elements of the bitmap, then this procedure need
+ // to be called again.
+ this->initialize_simplex_associated_to_key();
+ }
+
+ /**
+ * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells
+ * in the following directions and vector of element of a type T::filtration_type
+ * with filtration on top dimensional cells. The last parameter of the constructor is a vector of boolean of a length
+ * equal to the dimension of cubical complex.
+ * If the position i on this vector is true, then we impose periodic boundary conditions in this direction.
+ **/
+ Bitmap_cubical_complex(const std::vector<unsigned>& dimensions,
+ const std::vector<typename T::filtration_type>& top_dimensional_cells,
+ std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed) :
+ T(dimensions, top_dimensional_cells, directions_in_which_periodic_b_cond_are_to_be_imposed),
+ key_associated_to_simplex(this->total_number_of_cells + 1) {
+ for (size_t i = 0; i != this->total_number_of_cells; ++i) {
+ this->key_associated_to_simplex[i] = i;
+ }
+ // we initialize this only once, in each constructor, when the bitmap is constructed.
+ // If the user decide to change some elements of the bitmap, then this procedure need
+ // to be called again.
+ this->initialize_simplex_associated_to_key();
+ }
+
+ /**
+ * Destructor of the Bitmap_cubical_complex class.
+ **/
+ virtual ~Bitmap_cubical_complex() {}
+
+ //*********************************************//
+ // Other 'easy' functions
+ //*********************************************//
+
+ /**
+ * Returns number of all cubes in the complex.
+ **/
+ size_t num_simplices()const {
+ return this->total_number_of_cells;
+ }
+
+ /**
+ * Returns a Simplex_handle to a cube that do not exist in this complex.
+ **/
+ static Simplex_handle null_simplex() {
+ if (globalDbg) {
+ std::cerr << "Simplex_handle null_simplex()\n";
+ }
+ return std::numeric_limits<Simplex_handle>::max();
+ }
+
+ /**
+ * Returns dimension of the complex.
+ **/
+ inline size_t dimension()const {
+ return this->sizes.size();
+ }
+
+ /**
+ * Return dimension of a cell pointed by the Simplex_handle.
+ **/
+ inline unsigned dimension(Simplex_handle sh)const {
+ if (globalDbg) {
+ std::cerr << "unsigned dimension(const Simplex_handle& sh)\n";
+ }
+ if (sh != std::numeric_limits<Simplex_handle>::max()) return this->get_dimension_of_a_cell(sh);
+ return -1;
+ }
+
+ /**
+ * Return the filtration of a cell pointed by the Simplex_handle.
+ **/
+ typename T::filtration_type filtration(Simplex_handle sh) {
+ if (globalDbg) {
+ std::cerr << "T::filtration_type filtration(const Simplex_handle& sh)\n";
+ }
+ // Returns the filtration value of a simplex.
+ if (sh != std::numeric_limits<Simplex_handle>::max()) return this->data[sh];
+ return std::numeric_limits<Simplex_handle>::max();
+ }
+
+ /**
+ * Return a key which is not a key of any cube in the considered data structure.
+ **/
+ static Simplex_key null_key() {
+ if (globalDbg) {
+ std::cerr << "Simplex_key null_key()\n";
+ }
+ return std::numeric_limits<Simplex_handle>::max();
+ }
+
+ /**
+ * Return the key of a cube pointed by the Simplex_handle.
+ **/
+ Simplex_key key(Simplex_handle sh)const {
+ if (globalDbg) {
+ std::cerr << "Simplex_key key(const Simplex_handle& sh)\n";
+ }
+ if (sh != std::numeric_limits<Simplex_handle>::max()) {
+ return this->key_associated_to_simplex[sh];
+ }
+ return this->null_key();
+ }
+
+ /**
+ * Return the Simplex_handle given the key of the cube.
+ **/
+ Simplex_handle simplex(Simplex_key key) {
+ if (globalDbg) {
+ std::cerr << "Simplex_handle simplex(Simplex_key key)\n";
+ }
+ if (key != std::numeric_limits<Simplex_handle>::max()) {
+ return this->simplex_associated_to_key[ key ];
+ }
+ return null_simplex();
+ }
+
+ /**
+ * Assign key to a cube pointed by the Simplex_handle
+ **/
+ void assign_key(Simplex_handle sh, Simplex_key key) {
+ if (globalDbg) {
+ std::cerr << "void assign_key(Simplex_handle& sh, Simplex_key key)\n";
+ }
+ if (key == std::numeric_limits<Simplex_handle>::max()) return;
+ this->key_associated_to_simplex[sh] = key;
+ this->simplex_associated_to_key[key] = sh;
+ }
+
+ /**
+ * Function called from a constructor. It is needed for Filtration_simplex_iterator to work.
+ **/
+ void initialize_simplex_associated_to_key();
+
+ //*********************************************//
+ // Iterators
+ //*********************************************//
+
+ /**
+ * Boundary_simplex_range class provides ranges for boundary iterators.
+ **/
+ typedef typename std::vector< Simplex_handle >::iterator Boundary_simplex_iterator;
+ typedef typename std::vector< Simplex_handle > Boundary_simplex_range;
+
+ /**
+ * Filtration_simplex_iterator class provides an iterator though the whole structure in the order of filtration.
+ * Secondary criteria for filtration are:
+ * (1) Dimension of a cube (lower dimensional comes first).
+ * (2) Position in the data structure (the ones that are earlies in the data structure comes first).
+ **/
+ class Filtration_simplex_range;
+
+ class Filtration_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > {
+ // Iterator over all simplices of the complex in the order of the indexing scheme.
+ // 'value_type' must be 'Simplex_handle'.
+ public:
+ Filtration_simplex_iterator(Bitmap_cubical_complex* b) : b(b), position(0) { }
+
+ Filtration_simplex_iterator() : b(NULL), position(0) { }
+
+ Filtration_simplex_iterator operator++() {
+ if (globalDbg) {
+ std::cerr << "Filtration_simplex_iterator operator++\n";
+ }
+ ++this->position;
+ return (*this);
+ }
+
+ Filtration_simplex_iterator operator++(int) {
+ Filtration_simplex_iterator result = *this;
+ ++(*this);
+ return result;
+ }
+
+ Filtration_simplex_iterator& operator=(const Filtration_simplex_iterator& rhs) {
+ if (globalDbg) {
+ std::cerr << "Filtration_simplex_iterator operator =\n";
+ }
+ this->b = rhs.b;
+ this->position = rhs.position;
+ return (*this);
+ }
+
+ bool operator==(const Filtration_simplex_iterator& rhs)const {
+ if (globalDbg) {
+ std::cerr << "bool operator == ( const Filtration_simplex_iterator& rhs )\n";
+ }
+ return ( this->position == rhs.position);
+ }
+
+ bool operator!=(const Filtration_simplex_iterator& rhs)const {
+ if (globalDbg) {
+ std::cerr << "bool operator != ( const Filtration_simplex_iterator& rhs )\n";
+ }
+ return !(*this == rhs);
+ }
+
+ Simplex_handle operator*() {
+ if (globalDbg) {
+ std::cerr << "Simplex_handle operator*()\n";
+ }
+ return this->b->simplex_associated_to_key[ this->position ];
+ }
+
+ friend class Filtration_simplex_range;
+
+ private:
+ Bitmap_cubical_complex<T>* b;
+ size_t position;
+ };
+
+ /**
+ * @brief Filtration_simplex_range provides the ranges for Filtration_simplex_iterator.
+ **/
+ class Filtration_simplex_range {
+ // Range over the simplices of the complex in the order of the filtration.
+ // .begin() and .end() return type Filtration_simplex_iterator.
+ public:
+ typedef Filtration_simplex_iterator const_iterator;
+ typedef Filtration_simplex_iterator iterator;
+
+ Filtration_simplex_range(Bitmap_cubical_complex<T>* b) : b(b) { }
+
+ Filtration_simplex_iterator begin() {
+ if (globalDbg) {
+ std::cerr << "Filtration_simplex_iterator begin() \n";
+ }
+ return Filtration_simplex_iterator(this->b);
+ }
+
+ Filtration_simplex_iterator end() {
+ if (globalDbg) {
+ std::cerr << "Filtration_simplex_iterator end()\n";
+ }
+ Filtration_simplex_iterator it(this->b);
+ it.position = this->b->simplex_associated_to_key.size();
+ return it;
+ }
+
+ private:
+ Bitmap_cubical_complex<T>* b;
+ };
+
+
+
+ //*********************************************//
+ // Methods to access iterators from the container:
+
+ /**
+ * boundary_simplex_range creates an object of a Boundary_simplex_range class
+ * that provides ranges for the Boundary_simplex_iterator.
+ **/
+ Boundary_simplex_range boundary_simplex_range(Simplex_handle sh) {
+ return this->get_boundary_of_a_cell(sh);
+ }
+
+ /**
+ * filtration_simplex_range creates an object of a Filtration_simplex_range class
+ * that provides ranges for the Filtration_simplex_iterator.
+ **/
+ Filtration_simplex_range filtration_simplex_range() {
+ if (globalDbg) {
+ std::cerr << "Filtration_simplex_range filtration_simplex_range()\n";
+ }
+ // Returns a range over the simplices of the complex in the order of the filtration
+ return Filtration_simplex_range(this);
+ }
+ //*********************************************//
+
+
+
+ //*********************************************//
+ // Elements which are in Gudhi now, but I (and in all the cases I asked also Marc) do not understand why they are
+ // there.
+ // TODO(PD) the file IndexingTag.h in the Gudhi library contains an empty structure, so
+ // I understand that this is something that was planned (for simplicial maps?)
+ // but was never finished. The only idea I have here is to use the same empty structure from
+ // IndexingTag.h file, but only if the compiler needs it. If the compiler
+ // do not need it, then I would rather not add here elements which I do not understand.
+ // typedef Indexing_tag
+
+ /**
+ * Function needed for compatibility with Gudhi. Not useful for other purposes.
+ **/
+ std::pair<Simplex_handle, Simplex_handle> endpoints(Simplex_handle sh) {
+ std::vector< size_t > bdry = this->get_boundary_of_a_cell(sh);
+ if (globalDbg) {
+ std::cerr << "std::pair<Simplex_handle, Simplex_handle> endpoints( Simplex_handle sh )\n";
+ std::cerr << "bdry.size() : " << bdry.size() << std::endl;
+ }
+ // this method returns two first elements from the boundary of sh.
+ if (bdry.size() < 2)
+ throw("Error in endpoints in Bitmap_cubical_complex class. The cell have less than two elements in the "
+ "boundary.");
+ return std::make_pair(bdry[0], bdry[1]);
+ }
+
+
+ /**
+ * Class needed for compatibility with Gudhi. Not useful for other purposes.
+ **/
+ class Skeleton_simplex_range;
+
+ class Skeleton_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > {
+ // Iterator over all simplices of the complex in the order of the indexing scheme.
+ // 'value_type' must be 'Simplex_handle'.
+ public:
+ Skeleton_simplex_iterator(Bitmap_cubical_complex* b, size_t d) : b(b), dimension(d) {
+ if (globalDbg) {
+ std::cerr << "Skeleton_simplex_iterator ( Bitmap_cubical_complex* b , size_t d )\n";
+ }
+ // find the position of the first simplex of a dimension d
+ this->position = 0;
+ while (
+ (this->position != b->data.size()) &&
+ (this->b->get_dimension_of_a_cell(this->position) != this->dimension)
+ ) {
+ ++this->position;
+ }
+ }
+
+ Skeleton_simplex_iterator() : b(NULL), position(0), dimension(0) { }
+
+ Skeleton_simplex_iterator operator++() {
+ if (globalDbg) {
+ std::cerr << "Skeleton_simplex_iterator operator++()\n";
+ }
+ // increment the position as long as you did not get to the next element of the dimension dimension.
+ ++this->position;
+ while (
+ (this->position != this->b->data.size()) &&
+ (this->b->get_dimension_of_a_cell(this->position) != this->dimension)
+ ) {
+ ++this->position;
+ }
+ return (*this);
+ }
+
+ Skeleton_simplex_iterator operator++(int) {
+ Skeleton_simplex_iterator result = *this;
+ ++(*this);
+ return result;
+ }
+
+ Skeleton_simplex_iterator& operator=(const Skeleton_simplex_iterator& rhs) {
+ if (globalDbg) {
+ std::cerr << "Skeleton_simplex_iterator operator =\n";
+ }
+ this->b = rhs.b;
+ this->position = rhs.position;
+ this->dimension = rhs.dimension;
+ return (*this);
+ }
+
+ bool operator==(const Skeleton_simplex_iterator& rhs)const {
+ if (globalDbg) {
+ std::cerr << "bool operator ==\n";
+ }
+ return ( this->position == rhs.position);
+ }
+
+ bool operator!=(const Skeleton_simplex_iterator& rhs)const {
+ if (globalDbg) {
+ std::cerr << "bool operator != ( const Skeleton_simplex_iterator& rhs )\n";
+ }
+ return !(*this == rhs);
+ }
+
+ Simplex_handle operator*() {
+ if (globalDbg) {
+ std::cerr << "Simplex_handle operator*() \n";
+ }
+ return this->position;
+ }
+
+ friend class Skeleton_simplex_range;
+ private:
+ Bitmap_cubical_complex<T>* b;
+ size_t position;
+ unsigned dimension;
+ };
+
+ /**
+ * @brief Class needed for compatibility with Gudhi. Not useful for other purposes.
+ **/
+ class Skeleton_simplex_range {
+ // Range over the simplices of the complex in the order of the filtration.
+ // .begin() and .end() return type Filtration_simplex_iterator.
+ public:
+ typedef Skeleton_simplex_iterator const_iterator;
+ typedef Skeleton_simplex_iterator iterator;
+
+ Skeleton_simplex_range(Bitmap_cubical_complex<T>* b, unsigned dimension) : b(b), dimension(dimension) { }
+
+ Skeleton_simplex_iterator begin() {
+ if (globalDbg) {
+ std::cerr << "Skeleton_simplex_iterator begin()\n";
+ }
+ return Skeleton_simplex_iterator(this->b, this->dimension);
+ }
+
+ Skeleton_simplex_iterator end() {
+ if (globalDbg) {
+ std::cerr << "Skeleton_simplex_iterator end()\n";
+ }
+ Skeleton_simplex_iterator it(this->b, this->dimension);
+ it.position = this->b->data.size();
+ return it;
+ }
+
+ private:
+ Bitmap_cubical_complex<T>* b;
+ unsigned dimension;
+ };
+
+ /**
+ * Function needed for compatibility with Gudhi. Not useful for other purposes.
+ **/
+ Skeleton_simplex_range skeleton_simplex_range(unsigned dimension) {
+ if (globalDbg) {
+ std::cerr << "Skeleton_simplex_range skeleton_simplex_range( unsigned dimension )\n";
+ }
+ return Skeleton_simplex_range(this, dimension);
+ }
+
+ friend class is_before_in_filtration<T>;
+
+ protected:
+ std::vector< size_t > key_associated_to_simplex;
+ std::vector< size_t > simplex_associated_to_key;
+}; // Bitmap_cubical_complex
+
+template <typename T>
+void Bitmap_cubical_complex<T>::initialize_simplex_associated_to_key() {
+ if (globalDbg) {
+ std::cerr << "void Bitmap_cubical_complex<T>::initialize_elements_ordered_according_to_filtration() \n";
+ }
+ this->simplex_associated_to_key = std::vector<size_t>(this->data.size());
+ std::iota(std::begin(simplex_associated_to_key), std::end(simplex_associated_to_key), 0);
+#ifdef GUDHI_USE_TBB
+ tbb::parallel_sort(simplex_associated_to_key.begin(), simplex_associated_to_key.end(),
+ is_before_in_filtration<T>(this));
+#else
+ std::sort(simplex_associated_to_key.begin(), simplex_associated_to_key.end(), is_before_in_filtration<T>(this));
+#endif
+
+ // we still need to deal here with a key_associated_to_simplex:
+ for ( size_t i = 0 ; i != simplex_associated_to_key.size() ; ++i ) {
+ this->key_associated_to_simplex[ simplex_associated_to_key[i] ] = i;
+ }
+}
+
+template <typename T>
+class is_before_in_filtration {
+ public:
+ explicit is_before_in_filtration(Bitmap_cubical_complex<T> * CC)
+ : CC_(CC) { }
+
+ bool operator()(const typename Bitmap_cubical_complex<T>::Simplex_handle& sh1,
+ const typename Bitmap_cubical_complex<T>::Simplex_handle& sh2) const {
+ // Not using st_->filtration(sh1) because it uselessly tests for null_simplex.
+ typename T::filtration_type fil1 = CC_->data[sh1];
+ typename T::filtration_type fil2 = CC_->data[sh2];
+ if (fil1 != fil2) {
+ return fil1 < fil2;
+ }
+ // in this case they are on the same filtration level, so the dimension decide.
+ size_t dim1 = CC_->get_dimension_of_a_cell(sh1);
+ size_t dim2 = CC_->get_dimension_of_a_cell(sh2);
+ if (dim1 != dim2) {
+ return dim1 < dim2;
+ }
+ // in this case both filtration and dimensions of the considered cubes are the same. To have stable sort, we simply
+ // compare their positions in the bitmap:
+ return sh1 < sh2;
+ }
+
+ protected:
+ Bitmap_cubical_complex<T>* CC_;
+};
+
+} // namespace cubical_complex
+
+namespace Cubical_complex = cubical_complex;
+
+} // namespace Gudhi
+
+#endif // BITMAP_CUBICAL_COMPLEX_H_
diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h
new file mode 100644
index 00000000..4b072f10
--- /dev/null
+++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h
@@ -0,0 +1,144 @@
+/* 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): Pawel Dlotko
+ *
+ * Copyright (C) 2015 INRIA Sophia-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 BITMAP_CUBICAL_COMPLEX_COUNTER_H_
+#define BITMAP_CUBICAL_COMPLEX_COUNTER_H_
+
+#include <iostream>
+#include <vector>
+
+namespace Gudhi {
+
+namespace cubical_complex {
+
+/**
+ * @brief This is an implementation of a counter being a vector of integers.
+ * @details The constructor of the class takes as an input two vectors W and V.
+ * It assumes that W < V coordinatewise.
+ * If the initial counter W is not specified, it is assumed to be vector of zeros.
+ * The class allows to iterate between W and V by using increment() function.
+ * The increment() function returns a bool value.
+ * The current counter reach the end counter V if the value returned by the increment function is FALSE.
+ * This class is needed for the implementation of a bitmapCubicalComplex.
+ **/
+class counter {
+ public:
+ /**
+ * Constructor of a counter class. It takes only the parameter which is the end value of the counter.
+ * The default beginning value is a vector of the same length as the endd, filled-in with zeros.
+ **/
+ counter(const std::vector<unsigned>& endd) : begin(endd.size(), 0), end(endd), current(endd.size(), 0) { }
+
+ /**
+ * Constructor of a counter class. It takes as the input beginn and end vector.
+ * It assumes that begin vector is lexicographically below the end vector.
+ **/
+ counter(const std::vector< unsigned >& beginn, const std::vector< unsigned >& endd) : begin(beginn), end(endd), current(endd.size(), 0) {
+ if (beginn.size() != endd.size())
+ throw "In constructor of a counter, begin and end vectors do not have the same size. Program terminate";
+ }
+
+ /**
+ * Function to increment the counter. If the value returned by the function is true,
+ * then the incrementation process was successful.
+ * If the value of the function is false, that means, that the counter have reached its end-value.
+ **/
+ bool increment() {
+ size_t i = 0;
+ while ((i != this->end.size()) && (this->current[i] == this->end[i])) {
+ ++i;
+ }
+
+ if (i == this->end.size())return false;
+ ++this->current[i];
+ for (size_t j = 0; j != i; ++j) {
+ this->current[j] = this->begin[j];
+ }
+ return true;
+ }
+
+ /**
+ * Function to check if we are at the end of counter.
+ **/
+ bool isFinal() {
+ for (size_t i = 0; i != this->current.size(); ++i) {
+ if (this->current[i] == this->end[i])return true;
+ }
+ return false;
+ }
+
+ /**
+ * Function required in the implementation of bitmapCubicalComplexWPeriodicBoundaryCondition.
+ * Its aim is to find an counter corresponding to the element the following
+ * boundary element is identified with when periodic boundary conditions are imposed.
+ **/
+ std::vector< unsigned > find_opposite(const std::vector< bool >& directionsForPeriodicBCond) {
+ std::vector< unsigned > result;
+ for (size_t i = 0; i != this->current.size(); ++i) {
+ if ((this->current[i] == this->end[i]) && (directionsForPeriodicBCond[i] == true)) {
+ result.push_back(this->begin[i]);
+ } else {
+ result.push_back(this->current[i]);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Function checking at which positions the current value of a counter is the final value of the counter.
+ **/
+ std::vector< bool > directions_of_finals() {
+ std::vector< bool > result;
+ for (size_t i = 0; i != this->current.size(); ++i) {
+ if (this->current[i] == this->end[i]) {
+ result.push_back(true);
+ } else {
+ result.push_back(false);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Function to write counter to the stream.
+ **/
+ friend std::ostream& operator<<(std::ostream& out, const counter& c) {
+ // std::cerr << "c.current.size() : " << c.current.size() << endl;
+ for (size_t i = 0; i != c.current.size(); ++i) {
+ out << c.current[i] << " ";
+ }
+ return out;
+ }
+
+ private:
+ std::vector< unsigned > begin;
+ std::vector< unsigned > end;
+ std::vector< unsigned > current;
+};
+
+} // namespace cubical_complex
+
+namespace Cubical_complex = cubical_complex;
+
+} // namespace Gudhi
+
+#endif // BITMAP_CUBICAL_COMPLEX_COUNTER_H_
diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h
new file mode 100644
index 00000000..0442ac34
--- /dev/null
+++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h
@@ -0,0 +1,817 @@
+/* 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): Pawel Dlotko
+ *
+ * Copyright (C) 2015 INRIA Sophia-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 BITMAP_CUBICAL_COMPLEX_BASE_H_
+#define BITMAP_CUBICAL_COMPLEX_BASE_H_
+
+#include <gudhi/Bitmap_cubical_complex/counter.h>
+
+#include <iostream>
+#include <vector>
+#include <string>
+#include <fstream>
+#include <algorithm>
+#include <iterator>
+#include <limits>
+#include <utility> // for pair<>
+
+namespace Gudhi {
+
+namespace cubical_complex {
+
+/**
+ * @brief Cubical complex represented as a bitmap, class with basic implementation.
+ * @ingroup cubical_complex
+ * @details This is a class implementing a basic bitmap data structure to store cubical complexes.
+ * It implements only the most basic subroutines.
+ * The idea of the bitmap is the following. Our aim is to have a memory efficient
+ * data structure to store d-dimensional cubical complex
+ * C being a cubical decomposition
+ * of a rectangular region of a space. This is achieved by storing C as a
+ * vector of bits (this is where the name 'bitmap' came from).
+ * Each cell is represented by a single
+ * bit (in case of black and white bitmaps, or by a single element of a type T
+ * (here T is a filtration type of a bitmap, typically a double).
+ * All the informations needed for homology and
+ * persistent homology computations (like dimension of a cell, boundary and
+ * coboundary elements of a cell, are then obtained from the
+ * position of the element in C.
+ * The default filtration used in this implementation is the lower star filtration.
+ */
+template <typename T>
+class Bitmap_cubical_complex_base {
+ public:
+ typedef T filtration_type;
+
+ /**
+ *Default constructor
+ **/
+ Bitmap_cubical_complex_base() :
+ total_number_of_cells(0) { }
+ /**
+ * There are a few constructors of a Bitmap_cubical_complex_base class.
+ * First one, that takes vector<unsigned>, creates an empty bitmap of a dimension equal
+ * the number of elements in the
+ * input vector and size in the i-th dimension equal the number in the position i-of the input vector.
+ */
+ Bitmap_cubical_complex_base(const std::vector<unsigned>& sizes);
+ /**
+ * The second constructor takes as a input a Perseus style file. For more details,
+ * please consult the documentations of
+ * Perseus software as well as examples attached to this
+ * implementation.
+ **/
+ Bitmap_cubical_complex_base(const char* perseus_style_file);
+ /**
+ * The last constructor of a Bitmap_cubical_complex_base class accepts vector of dimensions (as the first one)
+ * together with vector of filtration values of top dimensional cells.
+ **/
+ Bitmap_cubical_complex_base(const std::vector<unsigned>& dimensions, const std::vector<T>& top_dimensional_cells);
+
+ /**
+ * Destructor of the Bitmap_cubical_complex_base class.
+ **/
+ virtual ~Bitmap_cubical_complex_base() { }
+
+ /**
+ * The functions get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell
+ * and get_cell_data are the basic
+ * functions that compute boundary / coboundary / dimension and the filtration
+ * value form a position of a cell in the structure of a bitmap. The input parameter of all of those function is a
+ * non-negative integer, indicating a position of a cube in the data structure.
+ * In the case of functions that compute (co)boundary, the output is a vector if non-negative integers pointing to
+ * the positions of (co)boundary element of the input cell.
+ */
+ virtual inline std::vector< size_t > get_boundary_of_a_cell(size_t cell)const;
+ /**
+ * The functions get_coboundary_of_a_cell, get_coboundary_of_a_cell,
+ * get_dimension_of_a_cell and get_cell_data are the basic
+ * functions that compute boundary / coboundary / dimension and the filtration
+ * value form a position of a cell in the structure of a bitmap.
+ * The input parameter of all of those function is a non-negative integer,
+ * indicating a position of a cube in the data structure.
+ * In the case of functions that compute (co)boundary, the output is a vector if
+ * non-negative integers pointing to the
+ * positions of (co)boundary element of the input cell.
+ **/
+ virtual inline std::vector< size_t > get_coboundary_of_a_cell(size_t cell)const;
+ /**
+ * In the case of get_dimension_of_a_cell function, the output is a non-negative integer
+ * indicating the dimension of a cell.
+ **/
+ inline unsigned get_dimension_of_a_cell(size_t cell)const;
+ /**
+ * In the case of get_cell_data, the output parameter is a reference to the value of a cube in a given position.
+ * This allows reading and changing the value of filtration. Note that if the value of a filtration is changed, the
+ * code do not check if we have a filtration or not. i.e. it do not check if the value of a filtration of a cell is
+ * not smaller than the value of a filtration of its boundary and not greater than the value of its coboundary.
+ **/
+ inline T& get_cell_data(size_t cell);
+
+
+ /**
+ * Typical input used to construct a baseBitmap class is a filtration given at the top dimensional cells.
+ * Then, there are a few ways one can pick the filtration of lower dimensional
+ * cells. The most typical one is by so called lower star filtration. This function is always called by any
+ * constructor which takes the top dimensional cells. If you use such a constructor,
+ * then there is no need to call this function. Call it only if you are putting the filtration
+ * of the cells by your own (for instance by using Top_dimensional_cells_iterator).
+ **/
+ void impose_lower_star_filtration(); // assume that top dimensional cells are already set.
+
+ /**
+ * Returns dimension of a complex.
+ **/
+ inline unsigned dimension()const {
+ return sizes.size();
+ }
+
+ /**
+ * Returns number of all cubes in the data structure.
+ **/
+ inline unsigned size()const {
+ return this->data.size();
+ }
+
+ /**
+ * Writing to stream operator. By using it we get the values T of cells in order in which they are stored in the
+ * structure. This procedure is used for debugging purposes.
+ **/
+ template <typename K>
+ friend std::ostream& operator<<(std::ostream & os, const Bitmap_cubical_complex_base<K>& b);
+
+ /**
+ * Function that put the input data to bins. By putting data to bins we mean rounding them to a sequence of values
+ * equally distributed in the range of data.
+ * Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute
+ * persistence gets worst. When dealing with this type of data, one may want to put different values on cells to
+ * some number of bins. The function put_data_to_bins( size_t number_of_bins ) is designed for that purpose.
+ * The parameter of the function is the number of bins (distinct values) we want to have in the cubical complex.
+ **/
+ void put_data_to_bins(size_t number_of_bins);
+
+ /**
+ * Function that put the input data to bins. By putting data to bins we mean rounding them to a sequence of values
+ * equally distributed in the range of data.
+ * Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute
+ * persistence gets worst. When dealing with this type of data, one may want to put different values on cells to
+ * some number of bins. The function put_data_to_bins( T diameter_of_bin ) is designed for that purpose.
+ * The parameter of it is the diameter of each bin. Note that the bottleneck distance between the persistence
+ * diagram of the cubical complex before and after using such a function will be bounded by the parameter
+ * diameter_of_bin.
+ **/
+ void put_data_to_bins(T diameter_of_bin);
+
+ /**
+ * Functions to find min and max values of filtration.
+ **/
+ std::pair< T, T > min_max_filtration();
+
+ // ITERATORS
+
+ /**
+ * @brief Iterator through all cells in the complex (in order they appear in the structure -- i.e.
+ * in lexicographical order).
+ **/
+ class All_cells_iterator : std::iterator< std::input_iterator_tag, T > {
+ public:
+ All_cells_iterator() {
+ this->counter = 0;
+ }
+
+ All_cells_iterator operator++() {
+ // first find first element of the counter that can be increased:
+ ++this->counter;
+ return *this;
+ }
+
+ All_cells_iterator operator++(int) {
+ All_cells_iterator result = *this;
+ ++(*this);
+ return result;
+ }
+
+ All_cells_iterator& operator=(const All_cells_iterator& rhs) {
+ this->counter = rhs.counter;
+ return *this;
+ }
+
+ bool operator==(const All_cells_iterator& rhs)const {
+ if (this->counter != rhs.counter)return false;
+ return true;
+ }
+
+ bool operator!=(const All_cells_iterator& rhs)const {
+ return !(*this == rhs);
+ }
+
+ /*
+ * The operator * returns position of a cube in the structure of cubical complex. This position can be then used as
+ * an argument of the following functions:
+ * get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell to get information about the cell
+ * boundary and coboundary and dimension
+ * and in function get_cell_data to get a filtration of a cell.
+ */
+ size_t operator*() {
+ return this->counter;
+ }
+ friend class Bitmap_cubical_complex_base;
+ protected:
+ size_t counter;
+ };
+
+ /**
+ * Function returning a All_cells_iterator to the first cell of the bitmap.
+ **/
+ All_cells_iterator all_cells_iterator_begin() {
+ All_cells_iterator a;
+ return a;
+ }
+
+ /**
+ * Function returning a All_cells_iterator to the last cell of the bitmap.
+ **/
+ All_cells_iterator all_cells_iterator_end() {
+ All_cells_iterator a;
+ a.counter = this->data.size();
+ return a;
+ }
+
+ /**
+ * @brief All_cells_range class provides ranges for All_cells_iterator
+ **/
+ class All_cells_range {
+ public:
+ All_cells_range(Bitmap_cubical_complex_base* b) : b(b) { }
+
+ All_cells_iterator begin() {
+ return b->all_cells_iterator_begin();
+ }
+
+ All_cells_iterator end() {
+ return b->all_cells_iterator_end();
+ }
+ private:
+ Bitmap_cubical_complex_base<T>* b;
+ };
+
+ All_cells_range all_cells_range() {
+ return All_cells_range(this);
+ }
+
+
+ /**
+ * Boundary_range class provides ranges for boundary iterators.
+ **/
+ typedef typename std::vector< size_t >::const_iterator Boundary_iterator;
+ typedef typename std::vector< size_t > Boundary_range;
+
+ /**
+ * boundary_simplex_range creates an object of a Boundary_simplex_range class
+ * that provides ranges for the Boundary_simplex_iterator.
+ **/
+ Boundary_range boundary_range(size_t sh) {
+ return this->get_boundary_of_a_cell(sh);
+ }
+
+ /**
+ * Coboundary_range class provides ranges for boundary iterators.
+ **/
+ typedef typename std::vector< size_t >::const_iterator Coboundary_iterator;
+ typedef typename std::vector< size_t > Coboundary_range;
+
+ /**
+ * boundary_simplex_range creates an object of a Boundary_simplex_range class
+ * that provides ranges for the Boundary_simplex_iterator.
+ **/
+ Coboundary_range coboundary_range(size_t sh) {
+ return this->get_coboundary_of_a_cell(sh);
+ }
+
+ /**
+ * @brief Iterator through top dimensional cells of the complex. The cells appear in order they are stored
+ * in the structure (i.e. in lexicographical order)
+ **/
+ class Top_dimensional_cells_iterator : std::iterator< std::input_iterator_tag, T > {
+ public:
+ Top_dimensional_cells_iterator(Bitmap_cubical_complex_base& b) : b(b) {
+ this->counter = std::vector<size_t>(b.dimension());
+ // std::fill( this->counter.begin() , this->counter.end() , 0 );
+ }
+
+ Top_dimensional_cells_iterator operator++() {
+ // first find first element of the counter that can be increased:
+ size_t dim = 0;
+ while ((dim != this->b.dimension()) && (this->counter[dim] == this->b.sizes[dim] - 1))++dim;
+
+ if (dim != this->b.dimension()) {
+ ++this->counter[dim];
+ for (size_t i = 0; i != dim; ++i) {
+ this->counter[i] = 0;
+ }
+ } else {
+ ++this->counter[0];
+ }
+ return *this;
+ }
+
+ Top_dimensional_cells_iterator operator++(int) {
+ Top_dimensional_cells_iterator result = *this;
+ ++(*this);
+ return result;
+ }
+
+ Top_dimensional_cells_iterator& operator=(const Top_dimensional_cells_iterator& rhs) {
+ this->counter = rhs.counter;
+ this->b = rhs.b;
+ return *this;
+ }
+
+ bool operator==(const Top_dimensional_cells_iterator& rhs)const {
+ if (&this->b != &rhs.b)return false;
+ if (this->counter.size() != rhs.counter.size())return false;
+ for (size_t i = 0; i != this->counter.size(); ++i) {
+ if (this->counter[i] != rhs.counter[i])return false;
+ }
+ return true;
+ }
+
+ bool operator!=(const Top_dimensional_cells_iterator& rhs)const {
+ return !(*this == rhs);
+ }
+
+ /*
+ * The operator * returns position of a cube in the structure of cubical complex. This position can be then used as
+ * an argument of the following functions:
+ * get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell to get information about the cell
+ * boundary and coboundary and dimension
+ * and in function get_cell_data to get a filtration of a cell.
+ */
+ size_t operator*() {
+ return this->compute_index_in_bitmap();
+ }
+
+ size_t compute_index_in_bitmap()const {
+ size_t index = 0;
+ for (size_t i = 0; i != this->counter.size(); ++i) {
+ index += (2 * this->counter[i] + 1) * this->b.multipliers[i];
+ }
+ return index;
+ }
+
+ void print_counter()const {
+ for (size_t i = 0; i != this->counter.size(); ++i) {
+ std::cout << this->counter[i] << " ";
+ }
+ }
+ friend class Bitmap_cubical_complex_base;
+ protected:
+ std::vector< size_t > counter;
+ Bitmap_cubical_complex_base& b;
+ };
+
+ /**
+ * Function returning a Top_dimensional_cells_iterator to the first top dimensional cell of the bitmap.
+ **/
+ Top_dimensional_cells_iterator top_dimensional_cells_iterator_begin() {
+ Top_dimensional_cells_iterator a(*this);
+ return a;
+ }
+
+ /**
+ * Function returning a Top_dimensional_cells_iterator to the last top dimensional cell of the bitmap.
+ **/
+ Top_dimensional_cells_iterator top_dimensional_cells_iterator_end() {
+ Top_dimensional_cells_iterator a(*this);
+ for (size_t i = 0; i != this->dimension(); ++i) {
+ a.counter[i] = this->sizes[i] - 1;
+ }
+ a.counter[0]++;
+ return a;
+ }
+
+ /**
+ * @brief Top_dimensional_cells_iterator_range class provides ranges for Top_dimensional_cells_iterator_range
+ **/
+ class Top_dimensional_cells_range {
+ public:
+ Top_dimensional_cells_range(Bitmap_cubical_complex_base* b) : b(b) { }
+
+ Top_dimensional_cells_iterator begin() {
+ return b->top_dimensional_cells_iterator_begin();
+ }
+
+ Top_dimensional_cells_iterator end() {
+ return b->top_dimensional_cells_iterator_end();
+ }
+ private:
+ Bitmap_cubical_complex_base<T>* b;
+ };
+
+ Top_dimensional_cells_range top_dimensional_cells_range() {
+ return Top_dimensional_cells_range(this);
+ }
+
+
+ //****************************************************************************************************************//
+ //****************************************************************************************************************//
+ //****************************************************************************************************************//
+ //****************************************************************************************************************//
+
+ inline size_t number_cells()const {
+ return this->total_number_of_cells;
+ }
+
+ //****************************************************************************************************************//
+ //****************************************************************************************************************//
+ //****************************************************************************************************************//
+ //****************************************************************************************************************//
+
+ protected:
+ std::vector<unsigned> sizes;
+ std::vector<unsigned> multipliers;
+ std::vector<T> data;
+ size_t total_number_of_cells;
+
+ void set_up_containers(const std::vector<unsigned>& sizes) {
+ unsigned multiplier = 1;
+ for (size_t i = 0; i != sizes.size(); ++i) {
+ this->sizes.push_back(sizes[i]);
+ this->multipliers.push_back(multiplier);
+ multiplier *= 2 * sizes[i] + 1;
+ }
+ this->data = std::vector<T>(multiplier, std::numeric_limits<T>::max());
+ this->total_number_of_cells = multiplier;
+ }
+
+ size_t compute_position_in_bitmap(const std::vector< unsigned >& counter) {
+ size_t position = 0;
+ for (size_t i = 0; i != this->multipliers.size(); ++i) {
+ position += this->multipliers[i] * counter[i];
+ }
+ return position;
+ }
+
+ std::vector<unsigned> compute_counter_for_given_cell(size_t cell)const {
+ std::vector<unsigned> counter;
+ counter.reserve(this->sizes.size());
+ for (size_t dim = this->sizes.size(); dim != 0; --dim) {
+ counter.push_back(cell / this->multipliers[dim - 1]);
+ cell = cell % this->multipliers[dim - 1];
+ }
+ std::reverse(counter.begin(), counter.end());
+ return counter;
+ }
+ void read_perseus_style_file(const char* perseus_style_file);
+ void setup_bitmap_based_on_top_dimensional_cells_list(const std::vector<unsigned>& sizes_in_following_directions,
+ const std::vector<T>& top_dimensional_cells);
+ Bitmap_cubical_complex_base(const char* perseus_style_file, std::vector<bool> directions);
+ Bitmap_cubical_complex_base(const std::vector<unsigned>& sizes, std::vector<bool> directions);
+ Bitmap_cubical_complex_base(const std::vector<unsigned>& dimensions,
+ const std::vector<T>& top_dimensional_cells,
+ std::vector<bool> directions);
+};
+
+template <typename T>
+void Bitmap_cubical_complex_base<T>::put_data_to_bins(size_t number_of_bins) {
+ bool bdg = false;
+
+ std::pair< T, T > min_max = this->min_max_filtration();
+ T dx = (min_max.second - min_max.first) / (T) number_of_bins;
+
+ // now put the data into the appropriate bins:
+ for (size_t i = 0; i != this->data.size(); ++i) {
+ if (bdg) {
+ std::cerr << "Before binning : " << this->data[i] << std::endl;
+ }
+ this->data[i] = min_max.first + dx * (this->data[i] - min_max.first) / number_of_bins;
+ if (bdg) {
+ std::cerr << "After binning : " << this->data[i] << std::endl;
+ getchar();
+ }
+ }
+}
+
+template <typename T>
+void Bitmap_cubical_complex_base<T>::put_data_to_bins(T diameter_of_bin) {
+ bool bdg = false;
+ std::pair< T, T > min_max = this->min_max_filtration();
+
+ size_t number_of_bins = (min_max.second - min_max.first) / diameter_of_bin;
+ // now put the data into the appropriate bins:
+ for (size_t i = 0; i != this->data.size(); ++i) {
+ if (bdg) {
+ std::cerr << "Before binning : " << this->data[i] << std::endl;
+ }
+ this->data[i] = min_max.first + diameter_of_bin * (this->data[i] - min_max.first) / number_of_bins;
+ if (bdg) {
+ std::cerr << "After binning : " << this->data[i] << std::endl;
+ getchar();
+ }
+ }
+}
+
+template <typename T>
+std::pair< T, T > Bitmap_cubical_complex_base<T>::min_max_filtration() {
+ std::pair< T, T > min_max(std::numeric_limits<T>::max(), std::numeric_limits<T>::min());
+ for (size_t i = 0; i != this->data.size(); ++i) {
+ if (this->data[i] < min_max.first)min_max.first = this->data[i];
+ if (this->data[i] > min_max.second)min_max.second = this->data[i];
+ }
+ return min_max;
+}
+
+template <typename K>
+std::ostream& operator<<(std::ostream & out, const Bitmap_cubical_complex_base<K>& b) {
+ for (typename Bitmap_cubical_complex_base<K>::all_cells_const_iterator
+ it = b.all_cells_const_begin(); it != b.all_cells_const_end(); ++it) {
+ out << *it << " ";
+ }
+ return out;
+}
+
+template <typename T>
+Bitmap_cubical_complex_base<T>::Bitmap_cubical_complex_base
+(const std::vector<unsigned>& sizes) {
+ this->set_up_containers(sizes);
+}
+
+template <typename T>
+void Bitmap_cubical_complex_base<T>::setup_bitmap_based_on_top_dimensional_cells_list(const std::vector<unsigned>& sizes_in_following_directions,
+ const std::vector<T>& top_dimensional_cells) {
+ this->set_up_containers(sizes_in_following_directions);
+
+ size_t number_of_top_dimensional_elements = 1;
+ for (size_t i = 0; i != sizes_in_following_directions.size(); ++i) {
+ number_of_top_dimensional_elements *= sizes_in_following_directions[i];
+ }
+ if (number_of_top_dimensional_elements != top_dimensional_cells.size()) {
+ std::cerr << "Error in constructor Bitmap_cubical_complex_base ( std::vector<size_t> sizes_in_following_directions"
+ << ", std::vector<T> top_dimensional_cells ). Number of top dimensional elements that follow from "
+ << "sizes_in_following_directions vector is different than the size of top_dimensional_cells vector."
+ << std::endl;
+ throw("Error in constructor Bitmap_cubical_complex_base( std::vector<size_t> sizes_in_following_directions,"
+ "std::vector<T> top_dimensional_cells ). Number of top dimensional elements that follow from "
+ "sizes_in_following_directions vector is different than the size of top_dimensional_cells vector.");
+ }
+
+ Bitmap_cubical_complex_base<T>::Top_dimensional_cells_iterator it(*this);
+ size_t index = 0;
+ for (it = this->top_dimensional_cells_iterator_begin(); it != this->top_dimensional_cells_iterator_end(); ++it) {
+ this->get_cell_data(*it) = top_dimensional_cells[index];
+ ++index;
+ }
+ this->impose_lower_star_filtration();
+}
+
+template <typename T>
+Bitmap_cubical_complex_base<T>::Bitmap_cubical_complex_base
+(const std::vector<unsigned>& sizes_in_following_directions, const std::vector<T>& top_dimensional_cells) {
+ this->setup_bitmap_based_on_top_dimensional_cells_list(sizes_in_following_directions, top_dimensional_cells);
+}
+
+template <typename T>
+void Bitmap_cubical_complex_base<T>::read_perseus_style_file(const char* perseus_style_file) {
+ bool dbg = false;
+ std::ifstream inFiltration;
+ inFiltration.open(perseus_style_file);
+ unsigned dimensionOfData;
+ inFiltration >> dimensionOfData;
+
+ if (dbg) {
+ std::cerr << "dimensionOfData : " << dimensionOfData << std::endl;
+ getchar();
+ }
+
+ std::vector<unsigned> sizes;
+ sizes.reserve(dimensionOfData);
+ for (size_t i = 0; i != dimensionOfData; ++i) {
+ unsigned size_in_this_dimension;
+ inFiltration >> size_in_this_dimension;
+ sizes.push_back(size_in_this_dimension);
+ if (dbg) {
+ std::cerr << "size_in_this_dimension : " << size_in_this_dimension << std::endl;
+ }
+ }
+ this->set_up_containers(sizes);
+
+ Bitmap_cubical_complex_base<T>::Top_dimensional_cells_iterator it(*this);
+ it = this->top_dimensional_cells_iterator_begin();
+
+ while (!inFiltration.eof()) {
+ T filtrationLevel;
+ inFiltration >> filtrationLevel;
+ if (dbg) {
+ std::cerr << "Cell of an index : "
+ << it.compute_index_in_bitmap()
+ << " and dimension: "
+ << this->get_dimension_of_a_cell(it.compute_index_in_bitmap())
+ << " get the value : " << filtrationLevel << std::endl;
+ }
+ this->get_cell_data(*it) = filtrationLevel;
+ ++it;
+ }
+ inFiltration.close();
+ this->impose_lower_star_filtration();
+}
+
+template <typename T>
+Bitmap_cubical_complex_base<T>::Bitmap_cubical_complex_base(const char* perseus_style_file,
+ std::vector<bool> directions) {
+ // this constructor is here just for compatibility with a class that creates cubical complexes with periodic boundary
+ // conditions.
+ // It ignores the last parameter of the function.
+ this->read_perseus_style_file(perseus_style_file);
+}
+
+template <typename T>
+Bitmap_cubical_complex_base<T>::Bitmap_cubical_complex_base(const std::vector<unsigned>& sizes,
+ std::vector<bool> directions) {
+ // this constructor is here just for compatibility with a class that creates cubical complexes with periodic boundary
+ // conditions.
+ // It ignores the last parameter of the function.
+ this->set_up_containers(sizes);
+}
+
+template <typename T>
+Bitmap_cubical_complex_base<T>::Bitmap_cubical_complex_base(const std::vector<unsigned>& dimensions,
+ const std::vector<T>& top_dimensional_cells,
+ std::vector<bool> directions) {
+ // this constructor is here just for compatibility with a class that creates cubical complexes with periodic boundary
+ // conditions.
+ // It ignores the last parameter of the function.
+ this->setup_bitmap_based_on_top_dimensional_cells_list(dimensions, top_dimensional_cells);
+}
+
+template <typename T>
+Bitmap_cubical_complex_base<T>::Bitmap_cubical_complex_base(const char* perseus_style_file) {
+ this->read_perseus_style_file(perseus_style_file);
+}
+
+template <typename T>
+std::vector< size_t > Bitmap_cubical_complex_base<T>::get_boundary_of_a_cell(size_t cell)const {
+ std::vector< size_t > boundary_elements;
+
+ // Speed traded of for memory. Check if it is better in practice.
+ boundary_elements.reserve(this->dimension()*2);
+
+ size_t cell1 = cell;
+ for (size_t i = this->multipliers.size(); i != 0; --i) {
+ unsigned position = cell1 / this->multipliers[i - 1];
+ if (position % 2 == 1) {
+ boundary_elements.push_back(cell - this->multipliers[ i - 1 ]);
+ boundary_elements.push_back(cell + this->multipliers[ i - 1 ]);
+ }
+ cell1 = cell1 % this->multipliers[i - 1];
+ }
+ return boundary_elements;
+}
+
+template <typename T>
+std::vector< size_t > Bitmap_cubical_complex_base<T>::get_coboundary_of_a_cell(size_t cell)const {
+ std::vector<unsigned> counter = this->compute_counter_for_given_cell(cell);
+ std::vector< size_t > coboundary_elements;
+ size_t cell1 = cell;
+ for (size_t i = this->multipliers.size(); i != 0; --i) {
+ unsigned position = cell1 / this->multipliers[i - 1];
+ if (position % 2 == 0) {
+ if ((cell > this->multipliers[i - 1]) && (counter[i - 1] != 0)) {
+ coboundary_elements.push_back(cell - this->multipliers[i - 1]);
+ }
+ if (
+ (cell + this->multipliers[i - 1] < this->data.size()) && (counter[i - 1] != 2 * this->sizes[i - 1])) {
+ coboundary_elements.push_back(cell + this->multipliers[i - 1]);
+ }
+ }
+ cell1 = cell1 % this->multipliers[i - 1];
+ }
+ return coboundary_elements;
+}
+
+template <typename T>
+unsigned Bitmap_cubical_complex_base<T>::get_dimension_of_a_cell(size_t cell)const {
+ bool dbg = false;
+ if (dbg) std::cerr << "\n\n\n Computing position o a cell of an index : " << cell << std::endl;
+ unsigned dimension = 0;
+ for (size_t i = this->multipliers.size(); i != 0; --i) {
+ unsigned position = cell / this->multipliers[i - 1];
+
+ if (dbg) {
+ std::cerr << "i-1 :" << i - 1 << std::endl;
+ std::cerr << "cell : " << cell << std::endl;
+ std::cerr << "position : " << position << std::endl;
+ std::cerr << "multipliers[" << i - 1 << "] = " << this->multipliers[i - 1] << std::endl;
+ getchar();
+ }
+
+ if (position % 2 == 1) {
+ if (dbg) std::cerr << "Nonzero length in this direction \n";
+ dimension++;
+ }
+ cell = cell % this->multipliers[i - 1];
+ }
+ return dimension;
+}
+
+template <typename T>
+inline T& Bitmap_cubical_complex_base<T>::get_cell_data(size_t cell) {
+ return this->data[cell];
+}
+
+template <typename T>
+void Bitmap_cubical_complex_base<T>::impose_lower_star_filtration() {
+ bool dbg = false;
+
+ // this vector will be used to check which elements have already been taken care of in imposing lower star filtration
+ std::vector<bool> is_this_cell_considered(this->data.size(), false);
+
+ size_t size_to_reserve = 1;
+ for (size_t i = 0; i != this->multipliers.size(); ++i) {
+ size_to_reserve *= (size_t) ((this->multipliers[i] - 1) / 2);
+ }
+
+ std::vector<size_t> indices_to_consider;
+ indices_to_consider.reserve(size_to_reserve);
+ // we assume here that we already have a filtration on the top dimensional cells and
+ // we have to extend it to lower ones.
+ typename Bitmap_cubical_complex_base<T>::Top_dimensional_cells_iterator it(*this);
+ for (it = this->top_dimensional_cells_iterator_begin(); it != this->top_dimensional_cells_iterator_end(); ++it) {
+ indices_to_consider.push_back(it.compute_index_in_bitmap());
+ }
+
+ while (indices_to_consider.size()) {
+ if (dbg) {
+ std::cerr << "indices_to_consider in this iteration \n";
+ for (size_t i = 0; i != indices_to_consider.size(); ++i) {
+ std::cout << indices_to_consider[i] << " ";
+ }
+ getchar();
+ }
+ std::vector<size_t> new_indices_to_consider;
+ for (size_t i = 0; i != indices_to_consider.size(); ++i) {
+ std::vector<size_t> bd = this->get_boundary_of_a_cell(indices_to_consider[i]);
+ for (size_t boundaryIt = 0; boundaryIt != bd.size(); ++boundaryIt) {
+ if (dbg) {
+ std::cerr << "filtration of a cell : " << bd[boundaryIt] << " is : " << this->data[ bd[boundaryIt] ]
+ << " while of a cell: " << indices_to_consider[i] << " is: " << this->data[ indices_to_consider[i] ]
+ << std::endl;
+ getchar();
+ }
+ if (this->data[ bd[boundaryIt] ] > this->data[ indices_to_consider[i] ]) {
+ this->data[ bd[boundaryIt] ] = this->data[ indices_to_consider[i] ];
+ if (dbg) {
+ std::cerr << "Setting the value of a cell : " << bd[boundaryIt] << " to : "
+ << this->data[ indices_to_consider[i] ] << std::endl;
+ getchar();
+ }
+ }
+ if (is_this_cell_considered[ bd[boundaryIt] ] == false) {
+ new_indices_to_consider.push_back(bd[boundaryIt]);
+ is_this_cell_considered[ bd[boundaryIt] ] = true;
+ }
+ }
+ }
+ indices_to_consider.swap(new_indices_to_consider);
+ }
+}
+
+template <typename T>
+bool compareFirstElementsOfTuples(const std::pair< std::pair< T, size_t >, char >& first,
+ const std::pair< std::pair< T, size_t >, char >& second) {
+ if (first.first.first < second.first.first) {
+ return true;
+ } else {
+ if (first.first.first > second.first.first) {
+ return false;
+ }
+ // in this case first.first.first == second.first.first, so we need to compare dimensions
+ return first.second < second.second;
+ }
+}
+
+} // namespace cubical_complex
+
+namespace Cubical_complex = cubical_complex;
+
+} // namespace Gudhi
+
+#endif // BITMAP_CUBICAL_COMPLEX_BASE_H_
diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h
new file mode 100644
index 00000000..c3cc93dd
--- /dev/null
+++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h
@@ -0,0 +1,308 @@
+/* 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): Pawel Dlotko
+ *
+ * Copyright (C) 2015 INRIA Sophia-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 BITMAP_CUBICAL_COMPLEX_PERIODIC_BOUNDARY_CONDITIONS_BASE_H_
+#define BITMAP_CUBICAL_COMPLEX_PERIODIC_BOUNDARY_CONDITIONS_BASE_H_
+
+#include <gudhi/Bitmap_cubical_complex_base.h>
+
+#include <cmath>
+#include <limits> // for numeric_limits<>
+#include <vector>
+
+namespace Gudhi {
+
+namespace cubical_complex {
+
+// in this class, we are storing all the elements which are in normal bitmap (i.e. the bitmap without the periodic
+// boundary conditions). But, we set up the iterators and the procedures to compute boundary and coboundary in the way
+// that it is all right. We assume here that all the cells that are on the left / bottom and so on remains, while all
+// the cells on the right / top are not in the Bitmap_cubical_complex_periodic_boundary_conditions_base
+
+/**
+ * @brief Cubical complex with periodic boundary conditions represented as a bitmap.
+ * @ingroup cubical_complex
+ * @details This is a class implementing a bitmap data structure with periodic boundary conditions. Most of the functions are
+ * identical to the functions from Bitmap_cubical_complex_base.
+ * The ones that needed to be updated are the constructors and get_boundary_of_a_cell and get_coboundary_of_a_cell.
+ */
+template <typename T>
+class Bitmap_cubical_complex_periodic_boundary_conditions_base : public Bitmap_cubical_complex_base<T> {
+ public:
+ // constructors that take an extra parameter:
+
+ /**
+ * Default constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class.
+ */
+ Bitmap_cubical_complex_periodic_boundary_conditions_base() { }
+ /**
+ * A constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class that takes the following
+ * parameters: (1) vector with numbers of top dimensional cells in all dimensions and (2) vector of booleans. If
+ * at i-th position of this vector there is true value, that means that periodic boundary conditions are to be
+ * imposed in this direction. In case of false, the periodic boundary conditions will not be imposed in the direction
+ * i.
+ */
+ Bitmap_cubical_complex_periodic_boundary_conditions_base(const std::vector<unsigned>& sizes,
+ const std::vector<bool>& directions_in_which_periodic_b_cond_are_to_be_imposed);
+ /**
+ * A constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class that takes the name of Perseus
+ * style file as an input. Please consult the documentation about the specification of the file.
+ */
+ Bitmap_cubical_complex_periodic_boundary_conditions_base(const char* perseusStyleFile);
+ /**
+ * A constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class that takes the following
+ * parameters: (1) vector with numbers of top dimensional cells in all dimensions and (2) vector of top dimensional
+ * cells (ordered lexicographically) and (3) vector of booleans. If at i-th position of this vector there is true
+ * value, that means that periodic boundary conditions are to be imposed in this direction. In case of false, the
+ * periodic boundary conditions will not be imposed in the direction i.
+ */
+ Bitmap_cubical_complex_periodic_boundary_conditions_base(const std::vector<unsigned>& dimensions,
+ const std::vector<T>& topDimensionalCells,
+ const std::vector< bool >& directions_in_which_periodic_b_cond_are_to_be_imposed);
+
+ /**
+ * Destructor of the Bitmap_cubical_complex_periodic_boundary_conditions_base class.
+ **/
+ virtual ~Bitmap_cubical_complex_periodic_boundary_conditions_base() {}
+
+ // overwritten methods co compute boundary and coboundary
+ /**
+ * A version of a function that return boundary of a given cell for an object of
+ * Bitmap_cubical_complex_periodic_boundary_conditions_base class.
+ */
+ virtual std::vector< size_t > get_boundary_of_a_cell(size_t cell) const;
+
+ /**
+ * A version of a function that return coboundary of a given cell for an object of
+ * Bitmap_cubical_complex_periodic_boundary_conditions_base class.
+ */
+ virtual std::vector< size_t > get_coboundary_of_a_cell(size_t cell) const;
+
+ protected:
+ std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed;
+
+ void set_up_containers(const std::vector<unsigned>& sizes) {
+ unsigned multiplier = 1;
+ for (size_t i = 0; i != sizes.size(); ++i) {
+ this->sizes.push_back(sizes[i]);
+ this->multipliers.push_back(multiplier);
+
+ if (directions_in_which_periodic_b_cond_are_to_be_imposed[i]) {
+ multiplier *= 2 * sizes[i];
+ } else {
+ multiplier *= 2 * sizes[i] + 1;
+ }
+ }
+ // std::reverse( this->sizes.begin() , this->sizes.end() );
+ this->data = std::vector<T>(multiplier, std::numeric_limits<T>::max());
+ this->total_number_of_cells = multiplier;
+ }
+ Bitmap_cubical_complex_periodic_boundary_conditions_base(const std::vector<unsigned>& sizes);
+ Bitmap_cubical_complex_periodic_boundary_conditions_base(const std::vector<unsigned>& dimensions,
+ const std::vector<T>& topDimensionalCells);
+ void construct_complex_based_on_top_dimensional_cells(const std::vector<unsigned>& dimensions,
+ const std::vector<T>& topDimensionalCells,
+ const std::vector<bool>& directions_in_which_periodic_b_cond_are_to_be_imposed);
+};
+
+template <typename T>
+void Bitmap_cubical_complex_periodic_boundary_conditions_base<T>::construct_complex_based_on_top_dimensional_cells(const std::vector<unsigned>& dimensions,
+ const std::vector<T>& topDimensionalCells,
+ const std::vector<bool>& directions_in_which_periodic_b_cond_are_to_be_imposed) {
+ this->directions_in_which_periodic_b_cond_are_to_be_imposed = directions_in_which_periodic_b_cond_are_to_be_imposed;
+ this->set_up_containers(dimensions);
+
+ size_t i = 0;
+ for (auto it = this->top_dimensional_cells_iterator_begin(); it != this->top_dimensional_cells_iterator_end(); ++it) {
+ this->get_cell_data(*it) = topDimensionalCells[i];
+ ++i;
+ }
+ this->impose_lower_star_filtration();
+}
+
+template <typename T>
+Bitmap_cubical_complex_periodic_boundary_conditions_base<T>::Bitmap_cubical_complex_periodic_boundary_conditions_base(const std::vector<unsigned>& sizes,
+ const std::vector<bool>& directions_in_which_periodic_b_cond_are_to_be_imposed) {
+ this->directions_in_which_periodic_b_cond_are_to_be_imposed(directions_in_which_periodic_b_cond_are_to_be_imposed);
+ this->set_up_containers(sizes);
+}
+
+template <typename T>
+Bitmap_cubical_complex_periodic_boundary_conditions_base<T>::Bitmap_cubical_complex_periodic_boundary_conditions_base(const char* perseus_style_file) {
+ // for Perseus style files:
+ bool dbg = false;
+
+ std::ifstream inFiltration;
+ inFiltration.open(perseus_style_file);
+ unsigned dimensionOfData;
+ inFiltration >> dimensionOfData;
+
+ this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector<bool>(dimensionOfData, false);
+
+ std::vector<unsigned> sizes;
+ sizes.reserve(dimensionOfData);
+ for (size_t i = 0; i != dimensionOfData; ++i) {
+ int size_in_this_dimension;
+ inFiltration >> size_in_this_dimension;
+ if (size_in_this_dimension < 0) {
+ this->directions_in_which_periodic_b_cond_are_to_be_imposed[i] = true;
+ }
+ sizes.push_back(abs(size_in_this_dimension));
+ }
+ this->set_up_containers(sizes);
+
+ typename Bitmap_cubical_complex_periodic_boundary_conditions_base<T>::Top_dimensional_cells_iterator it(*this);
+ it = this->top_dimensional_cells_iterator_begin();
+
+ while (!inFiltration.eof()) {
+ double filtrationLevel;
+ inFiltration >> filtrationLevel;
+ if (inFiltration.eof())break;
+
+ if (dbg) {
+ std::cerr << "Cell of an index : "
+ << it.compute_index_in_bitmap()
+ << " and dimension: "
+ << this->get_dimension_of_a_cell(it.compute_index_in_bitmap())
+ << " get the value : " << filtrationLevel << std::endl;
+ }
+ this->get_cell_data(*it) = filtrationLevel;
+ ++it;
+ }
+ inFiltration.close();
+ this->impose_lower_star_filtration();
+}
+
+template <typename T>
+Bitmap_cubical_complex_periodic_boundary_conditions_base<T>::Bitmap_cubical_complex_periodic_boundary_conditions_base(const std::vector<unsigned>& sizes) {
+ this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector<bool>(sizes.size(), false);
+ this->set_up_containers(sizes);
+}
+
+template <typename T>
+Bitmap_cubical_complex_periodic_boundary_conditions_base<T>::Bitmap_cubical_complex_periodic_boundary_conditions_base(const std::vector<unsigned>& dimensions,
+ const std::vector<T>& topDimensionalCells) {
+ std::vector<bool> directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector<bool>(dimensions.size(), false);
+ this->construct_complex_based_on_top_dimensional_cells(dimensions, topDimensionalCells,
+ directions_in_which_periodic_b_cond_are_to_be_imposed);
+}
+
+template <typename T>
+Bitmap_cubical_complex_periodic_boundary_conditions_base<T>::
+Bitmap_cubical_complex_periodic_boundary_conditions_base(const std::vector<unsigned>& dimensions,
+ const std::vector<T>& topDimensionalCells,
+ const std::vector<bool>& directions_in_which_periodic_b_cond_are_to_be_imposed) {
+ this->construct_complex_based_on_top_dimensional_cells(dimensions, topDimensionalCells,
+ directions_in_which_periodic_b_cond_are_to_be_imposed);
+}
+
+// ***********************Methods************************ //
+
+template <typename T>
+std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_base<T>::get_boundary_of_a_cell(size_t cell) const {
+ bool dbg = false;
+ if (dbg) {
+ std::cerr << "Computations of boundary of a cell : " << cell << std::endl;
+ }
+
+ std::vector< size_t > boundary_elements;
+ size_t cell1 = cell;
+ for (size_t i = this->multipliers.size(); i != 0; --i) {
+ unsigned position = cell1 / this->multipliers[i - 1];
+ // this cell have a nonzero length in this direction, therefore we can compute its boundary in this direction.
+
+ if (position % 2 == 1) {
+ // if there are no periodic boundary conditions in this direction, we do not have to do anything.
+ if (!directions_in_which_periodic_b_cond_are_to_be_imposed[i - 1]) {
+ // std::cerr << "A\n";
+ boundary_elements.push_back(cell - this->multipliers[ i - 1 ]);
+ boundary_elements.push_back(cell + this->multipliers[ i - 1 ]);
+ if (dbg) {
+ std::cerr << cell - this->multipliers[ i - 1 ] << " " << cell + this->multipliers[ i - 1 ] << " ";
+ }
+ } else {
+ // in this direction we have to do boundary conditions. Therefore, we need to check if we are not at the end.
+ if (position != 2 * this->sizes[ i - 1 ] - 1) {
+ // std::cerr << "B\n";
+ boundary_elements.push_back(cell - this->multipliers[ i - 1 ]);
+ boundary_elements.push_back(cell + this->multipliers[ i - 1 ]);
+ if (dbg) {
+ std::cerr << cell - this->multipliers[ i - 1 ] << " " << cell + this->multipliers[ i - 1 ] << " ";
+ }
+ } else {
+ // std::cerr << "C\n";
+ boundary_elements.push_back(cell - this->multipliers[ i - 1 ]);
+ boundary_elements.push_back(cell - (2 * this->sizes[ i - 1 ] - 1) * this->multipliers[ i - 1 ]);
+ if (dbg) {
+ std::cerr << cell - this->multipliers[ i - 1 ] << " " <<
+ cell - (2 * this->sizes[ i - 1 ] - 1) * this->multipliers[ i - 1 ] << " ";
+ }
+ }
+ }
+ }
+ cell1 = cell1 % this->multipliers[i - 1];
+ }
+ return boundary_elements;
+}
+
+template <typename T>
+std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_base<T>::get_coboundary_of_a_cell(size_t cell) const {
+ std::vector<unsigned> counter = this->compute_counter_for_given_cell(cell);
+ std::vector< size_t > coboundary_elements;
+ size_t cell1 = cell;
+ for (size_t i = this->multipliers.size(); i != 0; --i) {
+ unsigned position = cell1 / this->multipliers[i - 1];
+ // if the cell has zero length in this direction, then it will have cbd in this direction.
+ if (position % 2 == 0) {
+ if (!this->directions_in_which_periodic_b_cond_are_to_be_imposed[i - 1]) {
+ // no periodic boundary conditions in this direction
+ if ((counter[i - 1] != 0) && (cell > this->multipliers[i - 1])) {
+ coboundary_elements.push_back(cell - this->multipliers[i - 1]);
+ }
+ if ((counter[i - 1] != 2 * this->sizes[i - 1]) && (cell + this->multipliers[i - 1] < this->data.size())) {
+ coboundary_elements.push_back(cell + this->multipliers[i - 1]);
+ }
+ } else {
+ // we want to have periodic boundary conditions in this direction
+ if (counter[i - 1] != 0) {
+ coboundary_elements.push_back(cell - this->multipliers[i - 1]);
+ coboundary_elements.push_back(cell + this->multipliers[i - 1]);
+ } else {
+ // in this case counter[i-1] == 0.
+ coboundary_elements.push_back(cell + this->multipliers[i - 1]);
+ coboundary_elements.push_back(cell + (2 * this->sizes[ i - 1 ] - 1) * this->multipliers[i - 1]);
+ }
+ }
+ }
+
+ cell1 = cell1 % this->multipliers[i - 1];
+ }
+ return coboundary_elements;
+}
+
+} // namespace cubical_complex
+
+namespace Cubical_complex = cubical_complex;
+
+} // namespace Gudhi
+
+#endif // BITMAP_CUBICAL_COMPLEX_PERIODIC_BOUNDARY_CONDITIONS_BASE_H_
diff --git a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp
new file mode 100644
index 00000000..db90eb94
--- /dev/null
+++ b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp
@@ -0,0 +1,1378 @@
+/* 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): Pawel Dlotko
+ *
+ * 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/>.
+ */
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE "cubical_complex"
+#include <boost/test/unit_test.hpp>
+
+#include <gudhi/reader_utils.h>
+#include <gudhi/Bitmap_cubical_complex.h>
+#include <gudhi/Persistent_cohomology.h>
+
+// standard stuff
+#include <iostream>
+#include <sstream>
+#include <vector>
+
+
+typedef Gudhi::cubical_complex::Bitmap_cubical_complex_base<double> Bitmap_cubical_complex_base;
+typedef Gudhi::cubical_complex::Bitmap_cubical_complex<Bitmap_cubical_complex_base> Bitmap_cubical_complex;
+
+typedef Gudhi::cubical_complex::Bitmap_cubical_complex_periodic_boundary_conditions_base<double>
+Bitmap_cubical_complex_periodic_boundary_conditions_base;
+typedef Gudhi::cubical_complex::Bitmap_cubical_complex<Bitmap_cubical_complex_periodic_boundary_conditions_base>
+Bitmap_cubical_complex_periodic_boundary_conditions;
+
+BOOST_AUTO_TEST_CASE(check_dimension) {
+ std::vector< double > increasingFiltrationOfTopDimensionalCells({1, 2, 3, 4, 5, 6, 7, 8, 9});
+
+ std::vector<unsigned> dimensions({3, 3});
+
+ Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells);
+ BOOST_CHECK(increasing.dimension() == 2);
+}
+
+BOOST_AUTO_TEST_CASE(topDimensionalCellsIterator_test) {
+ std::vector< double > expectedFiltrationValues1({0, 0, 0, 0, 100, 0, 0, 0, 0});
+
+ std::vector< double > expectedFiltrationValues2({1, 2, 3, 4, 5, 6, 7, 8, 9});
+
+ std::vector< double > increasingFiltrationOfTopDimensionalCells({1, 2, 3, 4, 5, 6, 7, 8, 9});
+
+ std::vector< double > oneDimensionalCycle({0, 0, 0, 0, 100, 0, 0, 0, 0});
+
+ std::vector<unsigned> dimensions({3, 3});
+
+ Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells);
+ Bitmap_cubical_complex hole(dimensions, oneDimensionalCycle);
+
+
+ int i = 0;
+ for (Bitmap_cubical_complex::Top_dimensional_cells_iterator
+ it = increasing.top_dimensional_cells_iterator_begin(); it != increasing.top_dimensional_cells_iterator_end(); ++it) {
+ BOOST_CHECK(increasing.get_cell_data(*it) == expectedFiltrationValues2[i]);
+ ++i;
+ }
+ i = 0;
+ for (Bitmap_cubical_complex::Top_dimensional_cells_iterator
+ it = hole.top_dimensional_cells_iterator_begin(); it != hole.top_dimensional_cells_iterator_end(); ++it) {
+ BOOST_CHECK(hole.get_cell_data(*it) == expectedFiltrationValues1[i]);
+ ++i;
+ }
+}
+
+BOOST_AUTO_TEST_CASE(compute_boundary_test_1) {
+ std::vector<double> boundary0;
+ std::vector<double> boundary1;
+ boundary1.push_back(0);
+ boundary1.push_back(2);
+ std::vector<double> boundary2;
+ std::vector<double> boundary3;
+ boundary3.push_back(2);
+ boundary3.push_back(4);
+ std::vector<double> boundary4;
+ std::vector<double> boundary5;
+ boundary5.push_back(4);
+ boundary5.push_back(6);
+ std::vector<double> boundary6;
+ std::vector<double> boundary7;
+ boundary7.push_back(0);
+ boundary7.push_back(14);
+ std::vector<double> boundary8;
+ boundary8.push_back(1);
+ boundary8.push_back(15);
+ boundary8.push_back(7);
+ boundary8.push_back(9);
+ std::vector<double> boundary9;
+ boundary9.push_back(2);
+ boundary9.push_back(16);
+ std::vector<double> boundary10;
+ boundary10.push_back(3);
+ boundary10.push_back(17);
+ boundary10.push_back(9);
+ boundary10.push_back(11);
+ std::vector<double> boundary11;
+ boundary11.push_back(4);
+ boundary11.push_back(18);
+ std::vector<double> boundary12;
+ boundary12.push_back(5);
+ boundary12.push_back(19);
+ boundary12.push_back(11);
+ boundary12.push_back(13);
+ std::vector<double> boundary13;
+ boundary13.push_back(6);
+ boundary13.push_back(20);
+ std::vector<double> boundary14;
+ std::vector<double> boundary15;
+ boundary15.push_back(14);
+ boundary15.push_back(16);
+ std::vector<double> boundary16;
+ std::vector<double> boundary17;
+ boundary17.push_back(16);
+ boundary17.push_back(18);
+ std::vector<double> boundary18;
+ std::vector<double> boundary19;
+ boundary19.push_back(18);
+ boundary19.push_back(20);
+ std::vector<double> boundary20;
+ std::vector<double> boundary21;
+ boundary21.push_back(14);
+ boundary21.push_back(28);
+ std::vector<double> boundary22;
+ boundary22.push_back(15);
+ boundary22.push_back(29);
+ boundary22.push_back(21);
+ boundary22.push_back(23);
+ std::vector<double> boundary23;
+ boundary23.push_back(16);
+ boundary23.push_back(30);
+ std::vector<double> boundary24;
+ boundary24.push_back(17);
+ boundary24.push_back(31);
+ boundary24.push_back(23);
+ boundary24.push_back(25);
+ std::vector<double> boundary25;
+ boundary25.push_back(18);
+ boundary25.push_back(32);
+ std::vector<double> boundary26;
+ boundary26.push_back(19);
+ boundary26.push_back(33);
+ boundary26.push_back(25);
+ boundary26.push_back(27);
+ std::vector<double> boundary27;
+ boundary27.push_back(20);
+ boundary27.push_back(34);
+ std::vector<double> boundary28;
+ std::vector<double> boundary29;
+ boundary29.push_back(28);
+ boundary29.push_back(30);
+ std::vector<double> boundary30;
+ std::vector<double> boundary31;
+ boundary31.push_back(30);
+ boundary31.push_back(32);
+ std::vector<double> boundary32;
+ std::vector<double> boundary33;
+ boundary33.push_back(32);
+ boundary33.push_back(34);
+ std::vector<double> boundary34;
+ std::vector<double> boundary35;
+ boundary35.push_back(28);
+ boundary35.push_back(42);
+ std::vector<double> boundary36;
+ boundary36.push_back(29);
+ boundary36.push_back(43);
+ boundary36.push_back(35);
+ boundary36.push_back(37);
+ std::vector<double> boundary37;
+ boundary37.push_back(30);
+ boundary37.push_back(44);
+ std::vector<double> boundary38;
+ boundary38.push_back(31);
+ boundary38.push_back(45);
+ boundary38.push_back(37);
+ boundary38.push_back(39);
+ std::vector<double> boundary39;
+ boundary39.push_back(32);
+ boundary39.push_back(46);
+ std::vector<double> boundary40;
+ boundary40.push_back(33);
+ boundary40.push_back(47);
+ boundary40.push_back(39);
+ boundary40.push_back(41);
+ std::vector<double> boundary41;
+ boundary41.push_back(34);
+ boundary41.push_back(48);
+ std::vector<double> boundary42;
+ std::vector<double> boundary43;
+ boundary43.push_back(42);
+ boundary43.push_back(44);
+ std::vector<double> boundary44;
+ std::vector<double> boundary45;
+ boundary45.push_back(44);
+ boundary45.push_back(46);
+ std::vector<double> boundary46;
+ std::vector<double> boundary47;
+ boundary47.push_back(46);
+ boundary47.push_back(48);
+ std::vector<double> boundary48;
+ std::vector< std::vector<double> > boundaries;
+ boundaries.push_back(boundary0);
+ boundaries.push_back(boundary1);
+ boundaries.push_back(boundary2);
+ boundaries.push_back(boundary3);
+ boundaries.push_back(boundary4);
+ boundaries.push_back(boundary5);
+ boundaries.push_back(boundary6);
+ boundaries.push_back(boundary7);
+ boundaries.push_back(boundary8);
+ boundaries.push_back(boundary9);
+ boundaries.push_back(boundary10);
+ boundaries.push_back(boundary11);
+ boundaries.push_back(boundary12);
+ boundaries.push_back(boundary13);
+ boundaries.push_back(boundary14);
+ boundaries.push_back(boundary15);
+ boundaries.push_back(boundary16);
+ boundaries.push_back(boundary17);
+ boundaries.push_back(boundary18);
+ boundaries.push_back(boundary19);
+ boundaries.push_back(boundary20);
+ boundaries.push_back(boundary21);
+ boundaries.push_back(boundary22);
+ boundaries.push_back(boundary23);
+ boundaries.push_back(boundary24);
+ boundaries.push_back(boundary25);
+ boundaries.push_back(boundary26);
+ boundaries.push_back(boundary27);
+ boundaries.push_back(boundary28);
+ boundaries.push_back(boundary29);
+ boundaries.push_back(boundary30);
+ boundaries.push_back(boundary31);
+ boundaries.push_back(boundary32);
+ boundaries.push_back(boundary33);
+ boundaries.push_back(boundary34);
+ boundaries.push_back(boundary35);
+ boundaries.push_back(boundary36);
+ boundaries.push_back(boundary37);
+ boundaries.push_back(boundary38);
+ boundaries.push_back(boundary39);
+ boundaries.push_back(boundary40);
+ boundaries.push_back(boundary41);
+ boundaries.push_back(boundary42);
+ boundaries.push_back(boundary43);
+ boundaries.push_back(boundary44);
+ boundaries.push_back(boundary45);
+ boundaries.push_back(boundary46);
+ boundaries.push_back(boundary47);
+ boundaries.push_back(boundary48);
+
+
+
+ std::vector< double > increasingFiltrationOfTopDimensionalCells({1, 2, 3, 4, 5, 6, 7, 8, 9});
+
+ std::vector<unsigned> dimensions({3, 3});
+
+ Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells);
+ for (size_t i = 0; i != increasing.size(); ++i) {
+ std::vector< size_t > bd = increasing.get_boundary_of_a_cell(i);
+ for (size_t j = 0; j != bd.size(); ++j) {
+ BOOST_CHECK(boundaries[i][j] == bd[j]);
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(compute_boundary_test_2) {
+ std::vector< double > increasingFiltrationOfTopDimensionalCells({1, 2, 3, 4, 5, 6, 7, 8, 9});
+
+ std::vector<unsigned> dimensions({3, 3});
+
+ Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells);
+
+
+ std::vector<double> coboundaryElements;
+ coboundaryElements.push_back(7);
+ coboundaryElements.push_back(1);
+ coboundaryElements.push_back(8);
+ coboundaryElements.push_back(9);
+ coboundaryElements.push_back(1);
+ coboundaryElements.push_back(3);
+ coboundaryElements.push_back(10);
+ coboundaryElements.push_back(11);
+ coboundaryElements.push_back(3);
+ coboundaryElements.push_back(5);
+ coboundaryElements.push_back(12);
+ coboundaryElements.push_back(13);
+ coboundaryElements.push_back(5);
+ coboundaryElements.push_back(8);
+ coboundaryElements.push_back(8);
+ coboundaryElements.push_back(10);
+ coboundaryElements.push_back(10);
+ coboundaryElements.push_back(12);
+ coboundaryElements.push_back(12);
+ coboundaryElements.push_back(7);
+ coboundaryElements.push_back(21);
+ coboundaryElements.push_back(15);
+ coboundaryElements.push_back(8);
+ coboundaryElements.push_back(22);
+ coboundaryElements.push_back(9);
+ coboundaryElements.push_back(23);
+ coboundaryElements.push_back(15);
+ coboundaryElements.push_back(17);
+ coboundaryElements.push_back(10);
+ coboundaryElements.push_back(24);
+ coboundaryElements.push_back(11);
+ coboundaryElements.push_back(25);
+ coboundaryElements.push_back(17);
+ coboundaryElements.push_back(19);
+ coboundaryElements.push_back(12);
+ coboundaryElements.push_back(26);
+ coboundaryElements.push_back(13);
+ coboundaryElements.push_back(27);
+ coboundaryElements.push_back(19);
+ coboundaryElements.push_back(22);
+ coboundaryElements.push_back(22);
+ coboundaryElements.push_back(24);
+ coboundaryElements.push_back(24);
+ coboundaryElements.push_back(26);
+ coboundaryElements.push_back(26);
+ coboundaryElements.push_back(21);
+ coboundaryElements.push_back(35);
+ coboundaryElements.push_back(29);
+ coboundaryElements.push_back(22);
+ coboundaryElements.push_back(36);
+ coboundaryElements.push_back(23);
+ coboundaryElements.push_back(37);
+ coboundaryElements.push_back(29);
+ coboundaryElements.push_back(31);
+ coboundaryElements.push_back(24);
+ coboundaryElements.push_back(38);
+ coboundaryElements.push_back(25);
+ coboundaryElements.push_back(39);
+ coboundaryElements.push_back(31);
+ coboundaryElements.push_back(33);
+ coboundaryElements.push_back(26);
+ coboundaryElements.push_back(40);
+ coboundaryElements.push_back(27);
+ coboundaryElements.push_back(41);
+ coboundaryElements.push_back(33);
+ coboundaryElements.push_back(36);
+ coboundaryElements.push_back(36);
+ coboundaryElements.push_back(38);
+ coboundaryElements.push_back(38);
+ coboundaryElements.push_back(40);
+ coboundaryElements.push_back(40);
+ coboundaryElements.push_back(35);
+ coboundaryElements.push_back(43);
+ coboundaryElements.push_back(36);
+ coboundaryElements.push_back(37);
+ coboundaryElements.push_back(43);
+ coboundaryElements.push_back(45);
+ coboundaryElements.push_back(38);
+ coboundaryElements.push_back(39);
+ coboundaryElements.push_back(45);
+ coboundaryElements.push_back(47);
+ coboundaryElements.push_back(40);
+ coboundaryElements.push_back(41);
+ coboundaryElements.push_back(47);
+ size_t number = 0;
+ for (size_t i = 0; i != increasing.size(); ++i) {
+ std::vector< size_t > bd = increasing.get_coboundary_of_a_cell(i);
+ for (size_t j = 0; j != bd.size(); ++j) {
+ BOOST_CHECK(coboundaryElements[number] == bd[j]);
+ ++number;
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(compute_boundary_test_3) {
+ std::vector< double > increasingFiltrationOfTopDimensionalCells({1, 2, 3, 4, 5, 6, 7, 8, 9});
+
+ std::vector<unsigned> dimensions({3, 3});
+
+ Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells);
+
+ std::vector<unsigned> dim;
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(1);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(1);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(1);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(0);
+
+ for (size_t i = 0; i != increasing.size(); ++i) {
+ BOOST_CHECK(increasing.get_dimension_of_a_cell(i) == dim[i]);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(Filtration_simplex_iterator_test) {
+ std::vector< double > increasingFiltrationOfTopDimensionalCells({1, 2, 3, 4, 5, 6, 7, 8, 9});
+
+ std::vector<unsigned> dimensions({3, 3});
+
+ Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells);
+
+ std::vector< unsigned > dim;
+ dim.push_back(0);
+ dim.push_back(0);
+ dim.push_back(0);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(0);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(0);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(0);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(0);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(2);
+ dim.push_back(0);
+ dim.push_back(1);
+ dim.push_back(1);
+ dim.push_back(2);
+
+ std::vector<double> fil;
+ fil.push_back(1);
+ fil.push_back(1);
+ fil.push_back(1);
+ fil.push_back(1);
+ fil.push_back(1);
+ fil.push_back(1);
+ fil.push_back(1);
+ fil.push_back(1);
+ fil.push_back(1);
+ fil.push_back(2);
+ fil.push_back(2);
+ fil.push_back(2);
+ fil.push_back(2);
+ fil.push_back(2);
+ fil.push_back(2);
+ fil.push_back(3);
+ fil.push_back(3);
+ fil.push_back(3);
+ fil.push_back(3);
+ fil.push_back(3);
+ fil.push_back(3);
+ fil.push_back(4);
+ fil.push_back(4);
+ fil.push_back(4);
+ fil.push_back(4);
+ fil.push_back(4);
+ fil.push_back(4);
+ fil.push_back(5);
+ fil.push_back(5);
+ fil.push_back(5);
+ fil.push_back(5);
+ fil.push_back(6);
+ fil.push_back(6);
+ fil.push_back(6);
+ fil.push_back(6);
+ fil.push_back(7);
+ fil.push_back(7);
+ fil.push_back(7);
+ fil.push_back(7);
+ fil.push_back(7);
+ fil.push_back(7);
+ fil.push_back(8);
+ fil.push_back(8);
+ fil.push_back(8);
+ fil.push_back(8);
+ fil.push_back(9);
+ fil.push_back(9);
+ fil.push_back(9);
+ fil.push_back(9);
+
+
+ Bitmap_cubical_complex::Filtration_simplex_range range = increasing.filtration_simplex_range();
+ size_t position = 0;
+ for (Bitmap_cubical_complex::Filtration_simplex_iterator it = range.begin(); it != range.end(); ++it) {
+ BOOST_CHECK(increasing.dimension(*it) == dim[position]);
+ BOOST_CHECK(increasing.filtration(*it) == fil[position]);
+ ++position;
+ }
+}
+
+BOOST_AUTO_TEST_CASE(boudary_operator_2d_bitmap_with_periodic_bcond) {
+ std::vector< double > filtration({0, 0, 0, 0});
+
+ std::vector<unsigned> dimensions({2, 2});
+
+ std::vector<bool> periodic_directions({true, true});
+
+ Bitmap_cubical_complex_periodic_boundary_conditions cmplx(dimensions, filtration, periodic_directions);
+ BOOST_CHECK(cmplx.dimension() == 2);
+
+
+ std::vector<double> boundary0;
+ std::vector<double> boundary1;
+ boundary1.push_back(0);
+ boundary1.push_back(2);
+ std::vector<double> boundary2;
+ std::vector<double> boundary3;
+ boundary3.push_back(2);
+ boundary3.push_back(0);
+ std::vector<double> boundary4;
+ boundary4.push_back(0);
+ boundary4.push_back(8);
+ std::vector<double> boundary5;
+ boundary5.push_back(1);
+ boundary5.push_back(9);
+ boundary5.push_back(4);
+ boundary5.push_back(6);
+ std::vector<double> boundary6;
+ boundary6.push_back(2);
+ boundary6.push_back(10);
+ std::vector<double> boundary7;
+ boundary7.push_back(3);
+ boundary7.push_back(11);
+ boundary7.push_back(6);
+ boundary7.push_back(4);
+ std::vector<double> boundary8;
+ std::vector<double> boundary9;
+ boundary9.push_back(8);
+ boundary9.push_back(10);
+ std::vector<double> boundary10;
+ std::vector<double> boundary11;
+ boundary11.push_back(10);
+ boundary11.push_back(8);
+ std::vector<double> boundary12;
+ boundary12.push_back(8);
+ boundary12.push_back(0);
+ std::vector<double> boundary13;
+ boundary13.push_back(9);
+ boundary13.push_back(1);
+ boundary13.push_back(12);
+ boundary13.push_back(14);
+ std::vector<double> boundary14;
+ boundary14.push_back(10);
+ boundary14.push_back(2);
+ std::vector<double> boundary15;
+ boundary15.push_back(11);
+ boundary15.push_back(3);
+ boundary15.push_back(14);
+ boundary15.push_back(12);
+
+ std::vector< std::vector<double> > boundaries;
+ boundaries.push_back(boundary0);
+ boundaries.push_back(boundary1);
+ boundaries.push_back(boundary2);
+ boundaries.push_back(boundary3);
+ boundaries.push_back(boundary4);
+ boundaries.push_back(boundary5);
+ boundaries.push_back(boundary6);
+ boundaries.push_back(boundary7);
+ boundaries.push_back(boundary8);
+ boundaries.push_back(boundary9);
+ boundaries.push_back(boundary10);
+ boundaries.push_back(boundary11);
+ boundaries.push_back(boundary12);
+ boundaries.push_back(boundary13);
+ boundaries.push_back(boundary14);
+ boundaries.push_back(boundary15);
+
+ for (size_t i = 0; i != cmplx.size(); ++i) {
+ std::vector< size_t > bd = cmplx.get_boundary_of_a_cell(i);
+ for (size_t j = 0; j != bd.size(); ++j) {
+ BOOST_CHECK(boundaries[i][j] == bd[j]);
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(coboudary_operator_2d_bitmap_with_periodic_bcond) {
+ std::vector< double > filtration({0, 0, 0, 0});
+
+ std::vector<unsigned> dimensions({2, 2});
+
+ std::vector<bool> periodic_directions({true, true});
+
+ Bitmap_cubical_complex_periodic_boundary_conditions cmplx(dimensions, filtration, periodic_directions);
+ BOOST_CHECK(cmplx.dimension() == 2);
+
+
+ std::vector<double> coboundary0;
+ coboundary0.push_back(4);
+ coboundary0.push_back(12);
+ coboundary0.push_back(1);
+ coboundary0.push_back(3);
+ std::vector<double> coboundary1;
+ coboundary1.push_back(5);
+ coboundary1.push_back(13);
+ std::vector<double> coboundary2;
+ coboundary2.push_back(6);
+ coboundary2.push_back(14);
+ coboundary2.push_back(1);
+ coboundary2.push_back(3);
+ std::vector<double> coboundary3;
+ coboundary3.push_back(7);
+ coboundary3.push_back(15);
+ std::vector<double> coboundary4;
+ coboundary4.push_back(5);
+ coboundary4.push_back(7);
+ std::vector<double> coboundary5;
+ std::vector<double> coboundary6;
+ coboundary6.push_back(5);
+ coboundary6.push_back(7);
+ std::vector<double> coboundary7;
+ std::vector<double> coboundary8;
+ coboundary8.push_back(4);
+ coboundary8.push_back(12);
+ coboundary8.push_back(9);
+ coboundary8.push_back(11);
+ std::vector<double> coboundary9;
+ coboundary9.push_back(5);
+ coboundary9.push_back(13);
+ std::vector<double> coboundary10;
+ coboundary10.push_back(6);
+ coboundary10.push_back(14);
+ coboundary10.push_back(9);
+ coboundary10.push_back(11);
+ std::vector<double> coboundary11;
+ coboundary11.push_back(7);
+ coboundary11.push_back(15);
+ std::vector<double> coboundary12;
+ coboundary12.push_back(13);
+ coboundary12.push_back(15);
+ std::vector<double> coboundary13;
+ std::vector<double> coboundary14;
+ coboundary14.push_back(13);
+ coboundary14.push_back(15);
+ std::vector<double> coboundary15;
+
+ std::vector< std::vector<double> > coboundaries;
+ coboundaries.push_back(coboundary0);
+ coboundaries.push_back(coboundary1);
+ coboundaries.push_back(coboundary2);
+ coboundaries.push_back(coboundary3);
+ coboundaries.push_back(coboundary4);
+ coboundaries.push_back(coboundary5);
+ coboundaries.push_back(coboundary6);
+ coboundaries.push_back(coboundary7);
+ coboundaries.push_back(coboundary8);
+ coboundaries.push_back(coboundary9);
+ coboundaries.push_back(coboundary10);
+ coboundaries.push_back(coboundary11);
+ coboundaries.push_back(coboundary12);
+ coboundaries.push_back(coboundary13);
+ coboundaries.push_back(coboundary14);
+ coboundaries.push_back(coboundary15);
+
+ for (size_t i = 0; i != cmplx.size(); ++i) {
+ std::vector< size_t > cbd = cmplx.get_coboundary_of_a_cell(i);
+ for (size_t j = 0; j != cbd.size(); ++j) {
+ BOOST_CHECK(coboundaries[i][j] == cbd[j]);
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(bitmap_2d_with_periodic_bcond_filtration) {
+ std::vector< double > filtrationOrg({0, 1, 2, 3});
+
+ std::vector<unsigned> dimensions({2, 2});
+
+ std::vector<bool> periodic_directions({true, true});
+
+ Bitmap_cubical_complex_periodic_boundary_conditions cmplx(dimensions, filtrationOrg, periodic_directions);
+ BOOST_CHECK(cmplx.dimension() == 2);
+
+
+ std::vector<double> filtration;
+ filtration.push_back(0); // 0
+ filtration.push_back(0); // 1
+ filtration.push_back(0); // 2
+ filtration.push_back(1); // 3
+ filtration.push_back(0); // 4
+ filtration.push_back(0); // 5
+ filtration.push_back(0); // 6
+ filtration.push_back(1); // 7
+ filtration.push_back(0); // 8
+ filtration.push_back(0); // 9
+ filtration.push_back(0); // 10
+ filtration.push_back(1); // 11
+ filtration.push_back(2); // 12
+ filtration.push_back(2); // 13
+ filtration.push_back(2); // 14
+ filtration.push_back(3); // 15
+
+
+ for (size_t i = 0; i != cmplx.size(); ++i) {
+ BOOST_CHECK(filtration[i] == cmplx.get_cell_data(i));
+ }
+}
+BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical_complex_base_check)
+{
+ std::vector< double > expected_filtration;
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(3);
+ expected_filtration.push_back(3);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(3);
+ expected_filtration.push_back(3);
+
+ std::vector<unsigned> expected_dimension;
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(2);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(2);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(2);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(2);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+
+ std::vector<size_t> expected_boundary;
+ expected_boundary.push_back(0);
+ expected_boundary.push_back(2);
+ expected_boundary.push_back(2);
+ expected_boundary.push_back(4);
+ expected_boundary.push_back(0);
+ expected_boundary.push_back(10);
+ expected_boundary.push_back(1);
+ expected_boundary.push_back(11);
+ expected_boundary.push_back(5);
+ expected_boundary.push_back(7);
+ expected_boundary.push_back(2);
+ expected_boundary.push_back(12);
+ expected_boundary.push_back(3);
+ expected_boundary.push_back(13);
+ expected_boundary.push_back(7);
+ expected_boundary.push_back(9);
+ expected_boundary.push_back(4);
+ expected_boundary.push_back(14);
+ expected_boundary.push_back(10);
+ expected_boundary.push_back(12);
+ expected_boundary.push_back(12);
+ expected_boundary.push_back(14);
+ expected_boundary.push_back(10);
+ expected_boundary.push_back(20);
+ expected_boundary.push_back(11);
+ expected_boundary.push_back(21);
+ expected_boundary.push_back(15);
+ expected_boundary.push_back(17);
+ expected_boundary.push_back(12);
+ expected_boundary.push_back(22);
+ expected_boundary.push_back(13);
+ expected_boundary.push_back(23);
+ expected_boundary.push_back(17);
+ expected_boundary.push_back(19);
+ expected_boundary.push_back(14);
+ expected_boundary.push_back(24);
+ expected_boundary.push_back(20);
+ expected_boundary.push_back(22);
+ expected_boundary.push_back(22);
+ expected_boundary.push_back(24);
+
+
+ std::vector<size_t> expected_coboundary;
+ expected_coboundary.push_back(5);
+ expected_coboundary.push_back(1);
+ expected_coboundary.push_back(6);
+ expected_coboundary.push_back(7);
+ expected_coboundary.push_back(1);
+ expected_coboundary.push_back(3);
+ expected_coboundary.push_back(8);
+ expected_coboundary.push_back(9);
+ expected_coboundary.push_back(3);
+ expected_coboundary.push_back(6);
+ expected_coboundary.push_back(6);
+ expected_coboundary.push_back(8);
+ expected_coboundary.push_back(8);
+ expected_coboundary.push_back(5);
+ expected_coboundary.push_back(15);
+ expected_coboundary.push_back(11);
+ expected_coboundary.push_back(6);
+ expected_coboundary.push_back(16);
+ expected_coboundary.push_back(7);
+ expected_coboundary.push_back(17);
+ expected_coboundary.push_back(11);
+ expected_coboundary.push_back(13);
+ expected_coboundary.push_back(8);
+ expected_coboundary.push_back(18);
+ expected_coboundary.push_back(9);
+ expected_coboundary.push_back(19);
+ expected_coboundary.push_back(13);
+ expected_coboundary.push_back(16);
+ expected_coboundary.push_back(16);
+ expected_coboundary.push_back(18);
+ expected_coboundary.push_back(18);
+ expected_coboundary.push_back(15);
+ expected_coboundary.push_back(21);
+ expected_coboundary.push_back(16);
+ expected_coboundary.push_back(17);
+ expected_coboundary.push_back(21);
+ expected_coboundary.push_back(23);
+ expected_coboundary.push_back(18);
+ expected_coboundary.push_back(19);
+ expected_coboundary.push_back(23);
+
+
+
+ std::vector< unsigned > sizes(2);
+ sizes[0] = 2;
+ sizes[1] = 2;
+
+ std::vector< double > data(4);
+ data[0] = 0;
+ data[1] = 1;
+ data[2] = 2;
+ data[3] = 3;
+
+ Bitmap_cubical_complex_base ba( sizes , data );
+ int i = 0;
+ int bd_it = 0;
+ int cbd_it = 0;
+ for ( Bitmap_cubical_complex_base::All_cells_iterator it = ba.all_cells_iterator_begin() ; it != ba.all_cells_iterator_end() ; ++it )
+ {
+ BOOST_CHECK( expected_filtration[i] == ba.get_cell_data( *it ) );
+ BOOST_CHECK( expected_dimension[i] == ba.get_dimension_of_a_cell( *it ) );
+
+ Bitmap_cubical_complex_base::Boundary_range bdrange = ba.boundary_range(*it);
+ for ( Bitmap_cubical_complex_base::Boundary_iterator bd = bdrange.begin() ; bd != bdrange.end() ; ++bd )
+ {
+ BOOST_CHECK( expected_boundary[bd_it] == *bd );
+ ++bd_it;
+ }
+
+ Bitmap_cubical_complex_base::Coboundary_range cbdrange = ba.coboundary_range(*it);
+ for ( Bitmap_cubical_complex_base::Coboundary_iterator cbd = cbdrange.begin() ; cbd != cbdrange.end() ; ++cbd )
+ {
+ BOOST_CHECK( expected_coboundary[cbd_it] == *cbd );
+ ++cbd_it;
+ }
+ ++i;
+ }
+}
+
+
+
+
+
+
+
+
+BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical_complex_base_check_range_check_2)
+{
+ std::vector< double > expected_filtration;
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(3);
+ expected_filtration.push_back(3);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(3);
+ expected_filtration.push_back(3);
+
+ std::vector<unsigned> expected_dimension;
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(2);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(2);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(2);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(2);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+
+ std::vector<size_t> expected_boundary;
+ expected_boundary.push_back(0);
+ expected_boundary.push_back(2);
+ expected_boundary.push_back(2);
+ expected_boundary.push_back(4);
+ expected_boundary.push_back(0);
+ expected_boundary.push_back(10);
+ expected_boundary.push_back(1);
+ expected_boundary.push_back(11);
+ expected_boundary.push_back(5);
+ expected_boundary.push_back(7);
+ expected_boundary.push_back(2);
+ expected_boundary.push_back(12);
+ expected_boundary.push_back(3);
+ expected_boundary.push_back(13);
+ expected_boundary.push_back(7);
+ expected_boundary.push_back(9);
+ expected_boundary.push_back(4);
+ expected_boundary.push_back(14);
+ expected_boundary.push_back(10);
+ expected_boundary.push_back(12);
+ expected_boundary.push_back(12);
+ expected_boundary.push_back(14);
+ expected_boundary.push_back(10);
+ expected_boundary.push_back(20);
+ expected_boundary.push_back(11);
+ expected_boundary.push_back(21);
+ expected_boundary.push_back(15);
+ expected_boundary.push_back(17);
+ expected_boundary.push_back(12);
+ expected_boundary.push_back(22);
+ expected_boundary.push_back(13);
+ expected_boundary.push_back(23);
+ expected_boundary.push_back(17);
+ expected_boundary.push_back(19);
+ expected_boundary.push_back(14);
+ expected_boundary.push_back(24);
+ expected_boundary.push_back(20);
+ expected_boundary.push_back(22);
+ expected_boundary.push_back(22);
+ expected_boundary.push_back(24);
+
+
+ std::vector<size_t> expected_coboundary;
+ expected_coboundary.push_back(5);
+ expected_coboundary.push_back(1);
+ expected_coboundary.push_back(6);
+ expected_coboundary.push_back(7);
+ expected_coboundary.push_back(1);
+ expected_coboundary.push_back(3);
+ expected_coboundary.push_back(8);
+ expected_coboundary.push_back(9);
+ expected_coboundary.push_back(3);
+ expected_coboundary.push_back(6);
+ expected_coboundary.push_back(6);
+ expected_coboundary.push_back(8);
+ expected_coboundary.push_back(8);
+ expected_coboundary.push_back(5);
+ expected_coboundary.push_back(15);
+ expected_coboundary.push_back(11);
+ expected_coboundary.push_back(6);
+ expected_coboundary.push_back(16);
+ expected_coboundary.push_back(7);
+ expected_coboundary.push_back(17);
+ expected_coboundary.push_back(11);
+ expected_coboundary.push_back(13);
+ expected_coboundary.push_back(8);
+ expected_coboundary.push_back(18);
+ expected_coboundary.push_back(9);
+ expected_coboundary.push_back(19);
+ expected_coboundary.push_back(13);
+ expected_coboundary.push_back(16);
+ expected_coboundary.push_back(16);
+ expected_coboundary.push_back(18);
+ expected_coboundary.push_back(18);
+ expected_coboundary.push_back(15);
+ expected_coboundary.push_back(21);
+ expected_coboundary.push_back(16);
+ expected_coboundary.push_back(17);
+ expected_coboundary.push_back(21);
+ expected_coboundary.push_back(23);
+ expected_coboundary.push_back(18);
+ expected_coboundary.push_back(19);
+ expected_coboundary.push_back(23);
+
+
+
+ std::vector< unsigned > sizes(2);
+ sizes[0] = 2;
+ sizes[1] = 2;
+
+ std::vector< double > data(4);
+ data[0] = 0;
+ data[1] = 1;
+ data[2] = 2;
+ data[3] = 3;
+
+ Bitmap_cubical_complex_base ba( sizes , data );
+ int i = 0;
+ int bd_it = 0;
+ int cbd_it = 0;
+
+ Bitmap_cubical_complex_base::All_cells_range range(&ba);
+ for ( Bitmap_cubical_complex_base::All_cells_iterator it = range.begin() ; it != range.end() ; ++it )
+ {
+ BOOST_CHECK( expected_filtration[i] == ba.get_cell_data( *it ) );
+ BOOST_CHECK( expected_dimension[i] == ba.get_dimension_of_a_cell( *it ) );
+
+ Bitmap_cubical_complex_base::Boundary_range bdrange = ba.boundary_range(*it);
+ for ( Bitmap_cubical_complex_base::Boundary_iterator bd = bdrange.begin() ; bd != bdrange.end() ; ++bd )
+ {
+ BOOST_CHECK( expected_boundary[bd_it] == *bd );
+ ++bd_it;
+ }
+
+ Bitmap_cubical_complex_base::Coboundary_range cbdrange = ba.coboundary_range(*it);
+ for ( Bitmap_cubical_complex_base::Coboundary_iterator cbd = cbdrange.begin() ; cbd != cbdrange.end() ; ++cbd )
+ {
+ BOOST_CHECK( expected_coboundary[cbd_it] == *cbd );
+ ++cbd_it;
+ }
+ ++i;
+ }
+}
+
+
+
+
+
+
+BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical_complex_base_check_range_check)
+{
+ std::vector< double > expected_filtration;
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(3);
+ expected_filtration.push_back(3);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(3);
+ expected_filtration.push_back(3);
+
+ std::vector<unsigned> expected_dimension;
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(2);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(2);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(2);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(2);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+ expected_dimension.push_back(1);
+ expected_dimension.push_back(0);
+
+ std::vector<size_t> expected_boundary;
+ expected_boundary.push_back(0);
+ expected_boundary.push_back(2);
+ expected_boundary.push_back(2);
+ expected_boundary.push_back(4);
+ expected_boundary.push_back(0);
+ expected_boundary.push_back(10);
+ expected_boundary.push_back(1);
+ expected_boundary.push_back(11);
+ expected_boundary.push_back(5);
+ expected_boundary.push_back(7);
+ expected_boundary.push_back(2);
+ expected_boundary.push_back(12);
+ expected_boundary.push_back(3);
+ expected_boundary.push_back(13);
+ expected_boundary.push_back(7);
+ expected_boundary.push_back(9);
+ expected_boundary.push_back(4);
+ expected_boundary.push_back(14);
+ expected_boundary.push_back(10);
+ expected_boundary.push_back(12);
+ expected_boundary.push_back(12);
+ expected_boundary.push_back(14);
+ expected_boundary.push_back(10);
+ expected_boundary.push_back(20);
+ expected_boundary.push_back(11);
+ expected_boundary.push_back(21);
+ expected_boundary.push_back(15);
+ expected_boundary.push_back(17);
+ expected_boundary.push_back(12);
+ expected_boundary.push_back(22);
+ expected_boundary.push_back(13);
+ expected_boundary.push_back(23);
+ expected_boundary.push_back(17);
+ expected_boundary.push_back(19);
+ expected_boundary.push_back(14);
+ expected_boundary.push_back(24);
+ expected_boundary.push_back(20);
+ expected_boundary.push_back(22);
+ expected_boundary.push_back(22);
+ expected_boundary.push_back(24);
+
+
+ std::vector<size_t> expected_coboundary;
+ expected_coboundary.push_back(5);
+ expected_coboundary.push_back(1);
+ expected_coboundary.push_back(6);
+ expected_coboundary.push_back(7);
+ expected_coboundary.push_back(1);
+ expected_coboundary.push_back(3);
+ expected_coboundary.push_back(8);
+ expected_coboundary.push_back(9);
+ expected_coboundary.push_back(3);
+ expected_coboundary.push_back(6);
+ expected_coboundary.push_back(6);
+ expected_coboundary.push_back(8);
+ expected_coboundary.push_back(8);
+ expected_coboundary.push_back(5);
+ expected_coboundary.push_back(15);
+ expected_coboundary.push_back(11);
+ expected_coboundary.push_back(6);
+ expected_coboundary.push_back(16);
+ expected_coboundary.push_back(7);
+ expected_coboundary.push_back(17);
+ expected_coboundary.push_back(11);
+ expected_coboundary.push_back(13);
+ expected_coboundary.push_back(8);
+ expected_coboundary.push_back(18);
+ expected_coboundary.push_back(9);
+ expected_coboundary.push_back(19);
+ expected_coboundary.push_back(13);
+ expected_coboundary.push_back(16);
+ expected_coboundary.push_back(16);
+ expected_coboundary.push_back(18);
+ expected_coboundary.push_back(18);
+ expected_coboundary.push_back(15);
+ expected_coboundary.push_back(21);
+ expected_coboundary.push_back(16);
+ expected_coboundary.push_back(17);
+ expected_coboundary.push_back(21);
+ expected_coboundary.push_back(23);
+ expected_coboundary.push_back(18);
+ expected_coboundary.push_back(19);
+ expected_coboundary.push_back(23);
+
+
+
+ std::vector< unsigned > sizes(2);
+ sizes[0] = 2;
+ sizes[1] = 2;
+
+ std::vector< double > data(4);
+ data[0] = 0;
+ data[1] = 1;
+ data[2] = 2;
+ data[3] = 3;
+
+ Bitmap_cubical_complex_base ba( sizes , data );
+ int i = 0;
+ int bd_it = 0;
+ int cbd_it = 0;
+
+ Bitmap_cubical_complex_base::All_cells_range range = ba.all_cells_range();
+ for ( Bitmap_cubical_complex_base::All_cells_iterator it = range.begin() ; it != range.end() ; ++it )
+ {
+ BOOST_CHECK( expected_filtration[i] == ba.get_cell_data( *it ) );
+ BOOST_CHECK( expected_dimension[i] == ba.get_dimension_of_a_cell( *it ) );
+
+ Bitmap_cubical_complex_base::Boundary_range bdrange = ba.boundary_range(*it);
+ for ( Bitmap_cubical_complex_base::Boundary_iterator bd = bdrange.begin() ; bd != bdrange.end() ; ++bd )
+ {
+ BOOST_CHECK( expected_boundary[bd_it] == *bd );
+ ++bd_it;
+ }
+
+ Bitmap_cubical_complex_base::Coboundary_range cbdrange = ba.coboundary_range(*it);
+ for ( Bitmap_cubical_complex_base::Coboundary_iterator cbd = cbdrange.begin() ; cbd != cbdrange.end() ; ++cbd )
+ {
+ BOOST_CHECK( expected_coboundary[cbd_it] == *cbd );
+ ++cbd_it;
+ }
+ ++i;
+ }
+}
+
+BOOST_AUTO_TEST_CASE(Top_dimensional_cells_iterator_range_check)
+{
+ std::vector< double > expected_filtration;
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(0);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(1);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(3);
+ expected_filtration.push_back(3);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(2);
+ expected_filtration.push_back(3);
+ expected_filtration.push_back(3);
+
+
+ std::vector< unsigned > sizes(2);
+ sizes[0] = 2;
+ sizes[1] = 2;
+
+ std::vector< double > data(4);
+ data[0] = 0;
+ data[1] = 1;
+ data[2] = 2;
+ data[3] = 3;
+
+ Bitmap_cubical_complex_base ba( sizes , data );
+ int i = 0;
+
+ Bitmap_cubical_complex_base::Top_dimensional_cells_range range = ba.top_dimensional_cells_range();
+ for ( Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it = range.begin() ; it != range.end() ; ++it )
+ {
+ BOOST_CHECK( data[i] == ba.get_cell_data( *it ) );
+ BOOST_CHECK( ba.get_dimension_of_a_cell( *it ) == 2 );
+ ++i;
+ }
+}
+
diff --git a/src/Bitmap_cubical_complex/test/CMakeLists.txt b/src/Bitmap_cubical_complex/test/CMakeLists.txt
new file mode 100644
index 00000000..daf0e14f
--- /dev/null
+++ b/src/Bitmap_cubical_complex/test/CMakeLists.txt
@@ -0,0 +1,24 @@
+cmake_minimum_required(VERSION 2.6)
+project(Bitmap_cubical_complex_tests)
+
+if (GCOVR_PATH)
+ # for gcovr to make coverage reports - Corbera Jenkins plugin
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
+endif()
+if (GPROF_PATH)
+ # for gprof to make coverage reports - Jenkins
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg")
+endif()
+
+add_executable ( BitmapCCUT Bitmap_test.cpp )
+target_link_libraries(BitmapCCUT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+if (TBB_FOUND)
+ target_link_libraries(BitmapCCUT ${TBB_LIBRARIES})
+endif()
+
+# Unitary tests
+add_test(NAME BitmapCCUT
+ COMMAND ${CMAKE_CURRENT_BINARY_DIR}/BitmapCCUT
+ # XML format for Jenkins xUnit plugin
+ --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/BitmapCCUT.xml --log_level=test_suite --report_level=no)
+
diff --git a/src/Bottleneck/example/CMakeLists.txt b/src/Bottleneck/example/CMakeLists.txt
index 2ff009c4..77797202 100644
--- a/src/Bottleneck/example/CMakeLists.txt
+++ b/src/Bottleneck/example/CMakeLists.txt
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 2.6)
-project(GUDHIBottleneckExample)
+project(Bottleneck_examples)
add_executable ( RandomDiagrams random_diagrams.cpp )
add_test(RandomDiagrams ${CMAKE_CURRENT_BINARY_DIR}/RandomDiagrams)
diff --git a/src/Bottleneck/test/CMakeLists.txt b/src/Bottleneck/test/CMakeLists.txt
index 3dfd80cd..9d88ab25 100644
--- a/src/Bottleneck/test/CMakeLists.txt
+++ b/src/Bottleneck/test/CMakeLists.txt
@@ -1,17 +1,13 @@
cmake_minimum_required(VERSION 2.6)
-project(GUDHIBottleneckUT)
+project(Bottleneck_tests)
if (GCOVR_PATH)
# for gcovr to make coverage reports - Corbera Jenkins plugin
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
- set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fprofile-arcs -ftest-coverage")
- set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fprofile-arcs -ftest-coverage")
endif()
if (GPROF_PATH)
# for gprof to make coverage reports - Jenkins
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg")
- set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pg")
- set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pg")
endif()
add_executable ( BottleneckUT bottleneck_unit_test.cpp )
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index a84090e9..e26b2d25 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -2,36 +2,90 @@ cmake_minimum_required(VERSION 2.6)
project(GUDHI)
include("CMakeGUDHIVersion.txt")
+# Generate GUDHI official version file
+configure_file(GUDHIVersion.cmake.in "${CMAKE_SOURCE_DIR}/GUDHIVersion.cmake" @ONLY)
enable_testing()
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules/")
-find_package(Boost REQUIRED COMPONENTS system filesystem program_options chrono timer REQUIRED)
+find_package(Boost REQUIRED COMPONENTS system filesystem program_options chrono timer date_time REQUIRED)
-if (NOT CMAKE_BUILD_TYPE)
- set(CMAKE_BUILD_TYPE "Release")
-endif()
-if(MSVC)
- SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4267 /wd4668 /wd4311 /wd4800 /wd4820 /wd4503 /wd4244 /wd4345 /wd4996 /wd4396 /wd4018")
+if(NOT Boost_FOUND)
+ message(FATAL_ERROR "NOTICE: This program requires Boost and will not be compiled.")
else()
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
-endif()
-
-set(Boost_USE_STATIC_LIBS ON)
-set(Boost_USE_MULTITHREADED ON)
-set(Boost_USE_STATIC_RUNTIME OFF)
-
-find_package(GMP)
-if(GMP_FOUND)
- find_package(GMPXX)
-endif()
-find_package(CGAL)
+ # For "make doxygen"
+ set(GUDHI_USER_VERSION_DIR ${CMAKE_SOURCE_DIR})
+ include(${CMAKE_MODULE_PATH}/GUDHI_doxygen_target.txt)
+
+ find_package(GMP)
+ if(GMP_FOUND)
+ message(STATUS "GMP_LIBRARIES = ${GMP_LIBRARIES}")
+ INCLUDE_DIRECTORIES(${GMP_INCLUDE_DIR})
+ find_package(GMPXX)
+ if(GMPXX_FOUND)
+ message(STATUS "GMPXX_LIBRARIES = ${GMPXX_LIBRARIES}")
+ INCLUDE_DIRECTORIES(${GMPXX_INCLUDE_DIR})
+ endif()
+ endif()
+
+ # In CMakeLists.txt, when include(${CGAL_USE_FILE}), CMAKE_CXX_FLAGS are overwritten.
+ # cf. http://doc.cgal.org/latest/Manual/installation.html#title40
+ # A workaround is to include(${CGAL_USE_FILE}) before adding "-std=c++11".
+ # A fix would be to use https://cmake.org/cmake/help/v3.1/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html
+ # or even better https://cmake.org/cmake/help/v3.1/variable/CMAKE_CXX_STANDARD.html
+ # but it implies to use cmake version 3.1 at least.
+
+ # find CGAL in QUIET mode for cmake to be less verbose when CGAL is not found.
+ find_package(CGAL QUIET)
+ # Only CGAL versions > 4.4 supports what Gudhi uses from CGAL
+ if (CGAL_VERSION VERSION_LESS 4.4.0 AND CGAL_FOUND)
+ message("CGAL version ${CGAL_VERSION} is considered too old to be used by Gudhi.")
+ unset(CGAL_FOUND)
+ endif(CGAL_VERSION VERSION_LESS 4.4.0 AND CGAL_FOUND)
+ if(CGAL_FOUND)
+ message(STATUS "CGAL version: ${CGAL_VERSION}.")
+ include( ${CGAL_USE_FILE} )
+
+ if (NOT CGAL_VERSION VERSION_LESS 4.8.0)
+ include_directories(BEFORE "include/gudhi_patches")
+ endif()
+ endif()
+
+ if(MSVC)
+ # Turn off some VC++ warnings
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4267 /wd4668 /wd4311 /wd4800 /wd4820 /wd4503 /wd4244 /wd4345 /wd4996 /wd4396 /wd4018")
+ else()
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -pedantic")
+ endif()
+
+ if(CMAKE_BUILD_TYPE MATCHES Debug)
+ message("++ Debug compilation flags are: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_DEBUG}")
+ else()
+ message("++ Release compilation flags are: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE}")
+ endif()
+
+ set(Boost_USE_STATIC_LIBS ON)
+ set(Boost_USE_MULTITHREADED ON)
+ set(Boost_USE_STATIC_RUNTIME OFF)
+
+ # Find TBB package for parallel sort - not mandatory, just optional.
+ set(TBB_FIND_QUIETLY ON)
+ find_package(TBB)
+ if (TBB_FOUND)
+ include(${TBB_USE_FILE})
+ message("TBB found in ${TBB_LIBRARY_DIRS}")
+ add_definitions(-DGUDHI_USE_TBB)
+ endif()
+
+ find_package(Eigen3 3.1.0)
+ if (EIGEN3_FOUND)
+ message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.")
+ include( ${EIGEN3_USE_FILE} )
+ #include_directories (BEFORE "../../include")
+ endif (EIGEN3_FOUND)
-if(NOT Boost_FOUND)
- message(FATAL_ERROR "NOTICE: This demo requires Boost and will not be compiled.")
-else()
# BOOST ISSUE result_of vs C++11
add_definitions(-DBOOST_RESULT_OF_USE_DECLTYPE)
# BOOST ISSUE with Libraries name resolution under Windows
@@ -40,14 +94,27 @@ else()
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
LINK_DIRECTORIES(${Boost_LIBRARY_DIRS})
+ if (DEBUG_TRACES)
+ message(STATUS "DEBUG_TRACES are activated")
+ # For programs to be more verbose
+ add_definitions(-DDEBUG_TRACES)
+ endif()
+
#---------------------------------------------------------------------------------------
# Gudhi compilation part
include_directories(include)
+ add_subdirectory(example/common)
add_subdirectory(example/Simplex_tree)
add_subdirectory(example/Persistent_cohomology)
add_subdirectory(example/Skeleton_blocker)
add_subdirectory(example/Contraction)
+ add_subdirectory(example/Bitmap_cubical_complex)
+ add_subdirectory(example/Witness_complex)
+ add_subdirectory(example/Alpha_complex)
+ add_subdirectory(example/Spatial_searching)
+ add_subdirectory(example/Subsampling)
+ add_subdirectory(example/Tangential_complex)
# data points generator
add_subdirectory(data/points/generator)
@@ -63,8 +130,9 @@ else()
# (this registers the build-tree with a global CMake-registry)
export(PACKAGE GUDHI)
+ message("++ make install will install ${PROJECT_NAME} in the following directory : ${CMAKE_INSTALL_PREFIX}")
# Create the GUDHIConfig.cmake and GUDHIConfigVersion files
- set(CONF_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/include")
+ set(CONF_INCLUDE_DIRS "${CMAKE_INSTALL_PREFIX}/include")
configure_file(GUDHIConfig.cmake.in "${PROJECT_BINARY_DIR}/GUDHIConfig.cmake" @ONLY)
configure_file(GUDHIConfigVersion.cmake.in "${PROJECT_BINARY_DIR}/GUDHIConfigVersion.cmake" @ONLY)
@@ -75,7 +143,7 @@ else()
# Install the GUDHIConfig.cmake and GUDHIConfigVersion.cmake
install(FILES
- "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/GUDHIConfig.cmake"
+ "${PROJECT_BINARY_DIR}/GUDHIConfig.cmake"
"${PROJECT_BINARY_DIR}/GUDHIConfigVersion.cmake"
DESTINATION share/gudhi)
diff --git a/src/Contraction/doc/sphere_contraction_representation.png b/src/Contraction/doc/sphere_contraction_representation.png
new file mode 100644
index 00000000..edf37bf3
--- /dev/null
+++ b/src/Contraction/doc/sphere_contraction_representation.png
Binary files differ
diff --git a/src/Contraction/example/CMakeLists.txt b/src/Contraction/example/CMakeLists.txt
index 4889b82f..4c09a0a7 100644
--- a/src/Contraction/example/CMakeLists.txt
+++ b/src/Contraction/example/CMakeLists.txt
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 2.6)
-project(GUDHIskbl)
+project(Contraction_examples)
add_executable(RipsContraction Rips_contraction.cpp)
@@ -9,5 +9,7 @@ target_link_libraries(RipsContraction ${Boost_TIMER_LIBRARY} ${Boost_SYSTEM_LIBR
target_link_libraries(GarlandHeckbert ${Boost_TIMER_LIBRARY} ${Boost_SYSTEM_LIBRARY})
-add_test(RipsContraction.sphere.0.2 ${CMAKE_CURRENT_BINARY_DIR}/RipsContraction ${CMAKE_SOURCE_DIR}/data/points/sphere3D_2646.off 0.2)
-add_test(RipsContraction.S0310000 ${CMAKE_CURRENT_BINARY_DIR}/RipsContraction ${CMAKE_SOURCE_DIR}/data/points/SO3_10000.off 0.3)
+add_test(RipsContraction.tore3D.0.2 ${CMAKE_CURRENT_BINARY_DIR}/RipsContraction ${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off 0.2)
+# TODO(DS) : These tests are too long under Windows
+#add_test(RipsContraction.sphere.0.2 ${CMAKE_CURRENT_BINARY_DIR}/RipsContraction ${CMAKE_SOURCE_DIR}/data/points/sphere3D_2646.off 0.2)
+#add_test(RipsContraction.S0310000 ${CMAKE_CURRENT_BINARY_DIR}/RipsContraction ${CMAKE_SOURCE_DIR}/data/points/SO3_10000.off 0.3)
diff --git a/src/Contraction/example/Garland_heckbert.cpp b/src/Contraction/example/Garland_heckbert.cpp
index 70f29b6a..5347830c 100644
--- a/src/Contraction/example/Garland_heckbert.cpp
+++ b/src/Contraction/example/Garland_heckbert.cpp
@@ -35,9 +35,8 @@
#include "Garland_heckbert/Error_quadric.h"
-using namespace std;
using namespace Gudhi;
-using namespace skbl;
+using namespace skeleton_blocker;
using namespace contraction;
struct Geometry_trait {
@@ -145,12 +144,13 @@ class GH_visitor : public Gudhi::contraction::Contraction_visitor<EdgeProfile> {
int main(int argc, char *argv[]) {
if (argc != 4) {
- std::cerr << "Usage " << argv[0] << " input.off output.off N to load the file input.off, contract N edges and save "
- << "the result to output.off.\n";
+ std::cerr << "Usage " << argv[0] <<
+ " input.off output.off N to load the file input.off, contract N edges and save the result to output.off.\n";
return EXIT_FAILURE;
}
Complex complex;
+ typedef Complex::Vertex_handle Vertex_handle;
// load the points
Skeleton_blocker_off_reader<Complex> off_reader(argv[1], complex);
@@ -159,8 +159,12 @@ int main(int argc, char *argv[]) {
return EXIT_FAILURE;
}
- std::cout << "Load complex with " << complex.num_vertices() << " vertices" << std::endl;
+ if (!complex.empty() && !(complex.point(Vertex_handle(0)).dimension() == 3)) {
+ std::cerr << "Only points of dimension 3 are supported." << std::endl;
+ return EXIT_FAILURE;
+ }
+ std::cout << "Load complex with " << complex.num_vertices() << " vertices" << std::endl;
int num_contractions = atoi(argv[3]);
@@ -178,7 +182,7 @@ int main(int argc, char *argv[]) {
std::cout << "Final complex has " <<
complex.num_vertices() << " vertices, " <<
- complex.num_edges() << " edges and" <<
+ complex.num_edges() << " edges and " <<
complex.num_triangles() << " triangles." << std::endl;
// write simplified complex
@@ -187,6 +191,8 @@ int main(int argc, char *argv[]) {
return EXIT_SUCCESS;
}
+#endif // GARLAND_HECKBERT_H_
+
+
-#endif // GARLAND_HECKBERT_H_
diff --git a/src/Contraction/example/Garland_heckbert/Error_quadric.h b/src/Contraction/example/Garland_heckbert/Error_quadric.h
index a033aa00..076f1be0 100644
--- a/src/Contraction/example/Garland_heckbert/Error_quadric.h
+++ b/src/Contraction/example/Garland_heckbert/Error_quadric.h
@@ -1,182 +1,182 @@
-/* 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-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 ERROR_QUADRIC_H_
-#define ERROR_QUADRIC_H_
-
-#include <boost/optional/optional.hpp>
-
-#include <vector>
-#include <utility>
-
-template <typename Point> class Error_quadric {
- private:
- double coeff[10];
-
- public:
- Error_quadric() {
- clear();
- }
-
- /**
- * Quadric corresponding to the L2 distance to the plane.
- *
- * According to the notation of Garland Heckbert, they
- * denote a quadric symetric matrix as :
- * Q = [ q11 q12 q13 q14]
- * [ q12 q22 q23 q24]
- * [ q13 q23 q33 q34]
- * [ q14 q24 q34 q44]
- *
- * which is represented by a vector with 10 elts that
- * are denoted ci for clarity with :
- * Q = [ c0 c1 c2 c3 ]
- * [ c1 c4 c5 c6 ]
- * [ c2 c5 c7 c8 ]
- * [ c3 c6 c8 c9 ]
- *
- * The constructor return the quadrics that represents
- * the squared distance to the plane defined by triangle p0,p1,p2
- * times the area of triangle p0,p1,p2.
- */
- Error_quadric(const Point & p0, const Point & p1, const Point & p2) {
- Point normal(unit_normal(p0, p1, p2));
- double a = normal[0];
- double b = normal[1];
- double c = normal[2];
- double d = -a * p0[0] - b * p0[1] - c * p0[2];
- coeff[0] = a*a;
- coeff[1] = a*b;
- coeff[2] = a*c;
- coeff[3] = a*d;
- coeff[4] = b*b;
- coeff[5] = b*c;
- coeff[6] = b*d;
- coeff[7] = c*c;
- coeff[8] = c*d;
- coeff[9] = d*d;
-
- double area_p0p1p2 = std::sqrt(squared_area(p0, p1, p2));
- for (auto& x : coeff)
- x *= area_p0p1p2;
- }
-
- inline double squared_area(const Point& p0, const Point& p1, const Point& p2) {
- // if (x1,x2,x3) = p1-p0 and (y1,y2,y3) = p2-p0
- // then the squared area is = (u^2+v^2+w^2)/4
- // with: u = x2 * y3 - x3 * y2;
- // v = x3 * y1 - x1 * y3;
- // w = x1 * y2 - x2 * y1;
- Point p0p1(p1 - p0);
- Point p0p2(p2 - p0);
- double A = p0p1[1] * p0p2[2] - p0p1[2] * p0p2[1];
- double B = p0p1[2] * p0p2[0] - p0p1[0] * p0p2[2];
- double C = p0p1[0] * p0p2[1] - p0p1[1] * p0p2[0];
- return 1. / 4. * (A * A + B * B + C * C);
- }
-
- void clear() {
- for (auto& x : coeff)
- x = 0;
- }
-
- Error_quadric& operator+=(const Error_quadric& other) {
- if (this != &other) {
- for (int i = 0; i < 10; ++i)
- coeff[i] += other.coeff[i];
- }
- return *this;
- }
-
- /**
- * @return The quadric quost defined by the scalar product v^T Q v where Q is the quadratic form of Garland/Heckbert
- */
- inline double cost(const Point& point) const {
- double cost =
- coeff[0] * point.x() * point.x() + coeff[4] * point.y() * point.y() + coeff[7] * point.z() * point.z()
- + 2 * (coeff[1] * point.x() * point.y() + coeff[5] * point.y() * point.z() + coeff[2] * point.z() * point.x())
- + 2 * (coeff[3] * point.x() + coeff[6] * point.y() + coeff[8] * point.z())
- + coeff[9];
- if (cost < 0) {
- return 0;
- } else {
- return cost;
- }
- }
-
- inline double grad_determinant() const {
- return
- coeff[0] * coeff[4] * coeff[7]
- - coeff[0] * coeff[5] * coeff[5]
- - coeff[1] * coeff[1] * coeff[7]
- + 2 * coeff[1] * coeff[5] * coeff[2]
- - coeff[4] * coeff[2] * coeff[2];
- }
-
- /**
- * Return the point such that it minimizes the gradient of the quadric.
- * Det must be passed with the determinant value of the gradient (should be non zero).
- */
- inline Point solve_linear_gradient(double det) const {
- return Point({
- (-coeff[1] * coeff[5] * coeff[8] + coeff[1] * coeff[7] * coeff[6] + coeff[2] * coeff[8] * coeff[4] -
- coeff[2] * coeff[5] * coeff[6] - coeff[3] * coeff[4] * coeff[7] + coeff[3] * coeff[5] * coeff[5])
- / det,
- (coeff[0] * coeff[5] * coeff[8] - coeff[0] * coeff[7] * coeff[6] - coeff[5] * coeff[2] * coeff[3] -
- coeff[1] * coeff[2] * coeff[8] + coeff[6] * coeff[2] * coeff[2] + coeff[1] * coeff[3] * coeff[7])
- / det,
- (-coeff[8] * coeff[0] * coeff[4] + coeff[8] * coeff[1] * coeff[1] + coeff[2] * coeff[3] * coeff[4] +
- coeff[5] * coeff[0] * coeff[6] - coeff[5] * coeff[1] * coeff[3] - coeff[1] * coeff[2] * coeff[6])
- / det
- });
- }
-
- /**
- * returns the point that minimizes the quadric.
- * It inverses the quadric if its determinant is higher that a given threshold .
- * If the determinant is lower than this value the returned value is uninitialized.
- */
- boost::optional<Point> min_cost(double scale = 1) const {
- // const double min_determinant = 1e-4 * scale*scale;
- const double min_determinant = 1e-5;
- boost::optional<Point> pt_res;
- double det = grad_determinant();
- if (std::abs(det) > min_determinant)
- pt_res = solve_linear_gradient(det);
- return pt_res;
- }
-
- friend std::ostream& operator<<(std::ostream& stream, const Error_quadric& quadric) {
- stream << "\n[ " << quadric.coeff[0] << "," << quadric.coeff[1] << "," << quadric.coeff[2] << "," <<
- quadric.coeff[3] << ";\n";
- stream << " " << quadric.coeff[1] << "," << quadric.coeff[4] << "," << quadric.coeff[5] << "," <<
- quadric.coeff[6] << ";\n";
- stream << " " << quadric.coeff[2] << "," << quadric.coeff[5] << "," << quadric.coeff[7] << "," <<
- quadric.coeff[8] << ";\n";
- stream << " " << quadric.coeff[3] << "," << quadric.coeff[6] << "," << quadric.coeff[8] << "," <<
- quadric.coeff[9] << "]";
- return stream;
- }
-};
-
-#endif // ERROR_QUADRIC_H_
+/* 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-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 ERROR_QUADRIC_H_
+#define ERROR_QUADRIC_H_
+
+#include <boost/optional/optional.hpp>
+
+#include <vector>
+#include <utility>
+
+template <typename Point> class Error_quadric {
+ private:
+ double coeff[10];
+
+ public:
+ Error_quadric() {
+ clear();
+ }
+
+ /**
+ * Quadric corresponding to the L2 distance to the plane.
+ *
+ * According to the notation of Garland Heckbert, they
+ * denote a quadric symetric matrix as :
+ * Q = [ q11 q12 q13 q14]
+ * [ q12 q22 q23 q24]
+ * [ q13 q23 q33 q34]
+ * [ q14 q24 q34 q44]
+ *
+ * which is represented by a vector with 10 elts that
+ * are denoted ci for clarity with :
+ * Q = [ c0 c1 c2 c3 ]
+ * [ c1 c4 c5 c6 ]
+ * [ c2 c5 c7 c8 ]
+ * [ c3 c6 c8 c9 ]
+ *
+ * The constructor return the quadrics that represents
+ * the squared distance to the plane defined by triangle p0,p1,p2
+ * times the area of triangle p0,p1,p2.
+ */
+ Error_quadric(const Point & p0, const Point & p1, const Point & p2) {
+ Point normal(unit_normal(p0, p1, p2));
+ double a = normal[0];
+ double b = normal[1];
+ double c = normal[2];
+ double d = -a * p0[0] - b * p0[1] - c * p0[2];
+ coeff[0] = a*a;
+ coeff[1] = a*b;
+ coeff[2] = a*c;
+ coeff[3] = a*d;
+ coeff[4] = b*b;
+ coeff[5] = b*c;
+ coeff[6] = b*d;
+ coeff[7] = c*c;
+ coeff[8] = c*d;
+ coeff[9] = d*d;
+
+ double area_p0p1p2 = std::sqrt(squared_area(p0, p1, p2));
+ for (auto& x : coeff)
+ x *= area_p0p1p2;
+ }
+
+ inline double squared_area(const Point& p0, const Point& p1, const Point& p2) {
+ // if (x1,x2,x3) = p1-p0 and (y1,y2,y3) = p2-p0
+ // then the squared area is = (u^2+v^2+w^2)/4
+ // with: u = x2 * y3 - x3 * y2;
+ // v = x3 * y1 - x1 * y3;
+ // w = x1 * y2 - x2 * y1;
+ Point p0p1(p1 - p0);
+ Point p0p2(p2 - p0);
+ double A = p0p1[1] * p0p2[2] - p0p1[2] * p0p2[1];
+ double B = p0p1[2] * p0p2[0] - p0p1[0] * p0p2[2];
+ double C = p0p1[0] * p0p2[1] - p0p1[1] * p0p2[0];
+ return 1. / 4. * (A * A + B * B + C * C);
+ }
+
+ void clear() {
+ for (auto& x : coeff)
+ x = 0;
+ }
+
+ Error_quadric& operator+=(const Error_quadric& other) {
+ if (this != &other) {
+ for (int i = 0; i < 10; ++i)
+ coeff[i] += other.coeff[i];
+ }
+ return *this;
+ }
+
+ /**
+ * @return The quadric quost defined by the scalar product v^T Q v where Q is the quadratic form of Garland/Heckbert
+ */
+ inline double cost(const Point& point) const {
+ double cost =
+ coeff[0] * point.x() * point.x() + coeff[4] * point.y() * point.y() + coeff[7] * point.z() * point.z()
+ + 2 * (coeff[1] * point.x() * point.y() + coeff[5] * point.y() * point.z() + coeff[2] * point.z() * point.x())
+ + 2 * (coeff[3] * point.x() + coeff[6] * point.y() + coeff[8] * point.z())
+ + coeff[9];
+ if (cost < 0) {
+ return 0;
+ } else {
+ return cost;
+ }
+ }
+
+ inline double grad_determinant() const {
+ return
+ coeff[0] * coeff[4] * coeff[7]
+ - coeff[0] * coeff[5] * coeff[5]
+ - coeff[1] * coeff[1] * coeff[7]
+ + 2 * coeff[1] * coeff[5] * coeff[2]
+ - coeff[4] * coeff[2] * coeff[2];
+ }
+
+ /**
+ * Return the point such that it minimizes the gradient of the quadric.
+ * Det must be passed with the determinant value of the gradient (should be non zero).
+ */
+ inline Point solve_linear_gradient(double det) const {
+ return Point({
+ (-coeff[1] * coeff[5] * coeff[8] + coeff[1] * coeff[7] * coeff[6] + coeff[2] * coeff[8] * coeff[4] -
+ coeff[2] * coeff[5] * coeff[6] - coeff[3] * coeff[4] * coeff[7] + coeff[3] * coeff[5] * coeff[5])
+ / det,
+ (coeff[0] * coeff[5] * coeff[8] - coeff[0] * coeff[7] * coeff[6] - coeff[5] * coeff[2] * coeff[3] -
+ coeff[1] * coeff[2] * coeff[8] + coeff[6] * coeff[2] * coeff[2] + coeff[1] * coeff[3] * coeff[7])
+ / det,
+ (-coeff[8] * coeff[0] * coeff[4] + coeff[8] * coeff[1] * coeff[1] + coeff[2] * coeff[3] * coeff[4] +
+ coeff[5] * coeff[0] * coeff[6] - coeff[5] * coeff[1] * coeff[3] - coeff[1] * coeff[2] * coeff[6])
+ / det
+ });
+ }
+
+ /**
+ * returns the point that minimizes the quadric.
+ * It inverses the quadric if its determinant is higher that a given threshold .
+ * If the determinant is lower than this value the returned value is uninitialized.
+ */
+ boost::optional<Point> min_cost(double scale = 1) const {
+ // const double min_determinant = 1e-4 * scale*scale;
+ const double min_determinant = 1e-5;
+ boost::optional<Point> pt_res;
+ double det = grad_determinant();
+ if (std::abs(det) > min_determinant)
+ pt_res = solve_linear_gradient(det);
+ return pt_res;
+ }
+
+ friend std::ostream& operator<<(std::ostream& stream, const Error_quadric& quadric) {
+ stream << "\n[ " << quadric.coeff[0] << "," << quadric.coeff[1] << "," << quadric.coeff[2] << "," <<
+ quadric.coeff[3] << ";\n";
+ stream << " " << quadric.coeff[1] << "," << quadric.coeff[4] << "," << quadric.coeff[5] << "," <<
+ quadric.coeff[6] << ";\n";
+ stream << " " << quadric.coeff[2] << "," << quadric.coeff[5] << "," << quadric.coeff[7] << "," <<
+ quadric.coeff[8] << ";\n";
+ stream << " " << quadric.coeff[3] << "," << quadric.coeff[6] << "," << quadric.coeff[8] << "," <<
+ quadric.coeff[9] << "]";
+ return stream;
+ }
+};
+
+#endif // ERROR_QUADRIC_H_
diff --git a/src/Contraction/example/Rips_contraction.cpp b/src/Contraction/example/Rips_contraction.cpp
index d21246ed..7f19e239 100644
--- a/src/Contraction/example/Rips_contraction.cpp
+++ b/src/Contraction/example/Rips_contraction.cpp
@@ -27,9 +27,8 @@
#include <boost/timer/timer.hpp>
#include <iostream>
-using namespace std;
using namespace Gudhi;
-using namespace skbl;
+using namespace skeleton_blocker;
using namespace contraction;
struct Geometry_trait {
@@ -49,7 +48,7 @@ void build_rips(ComplexType& complex, double offset) {
for (auto p = vertices.begin(); p != vertices.end(); ++p)
for (auto q = p; ++q != vertices.end(); /**/) {
if (squared_dist(complex.point(*p), complex.point(*q)) < 4 * offset * offset)
- complex.add_edge(*p, *q);
+ complex.add_edge_without_blockers(*p, *q);
}
}
@@ -87,7 +86,7 @@ int main(int argc, char *argv[]) {
contractor.contract_edges();
std::cout << "Counting final number of simplices \n";
- unsigned num_simplices = std::distance(complex.simplex_range().begin(), complex.simplex_range().end());
+ unsigned num_simplices = std::distance(complex.complex_simplex_range().begin(), complex.complex_simplex_range().end());
std::cout << "Final complex has " <<
complex.num_vertices() << " vertices, " <<
diff --git a/src/Contraction/include/gudhi/Contraction/policies/Link_condition_valid_contraction.h b/src/Contraction/include/gudhi/Contraction/policies/Link_condition_valid_contraction.h
index 919df243..250bba27 100644
--- a/src/Contraction/include/gudhi/Contraction/policies/Link_condition_valid_contraction.h
+++ b/src/Contraction/include/gudhi/Contraction/policies/Link_condition_valid_contraction.h
@@ -23,8 +23,8 @@
#ifndef CONTRACTION_POLICIES_LINK_CONDITION_VALID_CONTRACTION_H_
#define CONTRACTION_POLICIES_LINK_CONDITION_VALID_CONTRACTION_H_
-#include <gudhi/Utils.h>
#include <gudhi/Contraction/policies/Valid_contraction_policy.h>
+#include <gudhi/Debug_utils.h>
namespace Gudhi {
diff --git a/src/Contraction/include/gudhi/Edge_contraction.h b/src/Contraction/include/gudhi/Edge_contraction.h
index dfce8d1b..61f2d945 100644
--- a/src/Contraction/include/gudhi/Edge_contraction.h
+++ b/src/Contraction/include/gudhi/Edge_contraction.h
@@ -30,23 +30,23 @@
#include <gudhi/Contraction/policies/Valid_contraction_policy.h>
#include <gudhi/Contraction/policies/Dummy_valid_contraction.h>
#include <gudhi/Contraction/policies/Link_condition_valid_contraction.h>
-#include <gudhi/Utils.h>
+#include <gudhi/Debug_utils.h>
namespace Gudhi {
namespace contraction {
-/** \defgroup contr Contraction
+/** \defgroup contr Edge 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
of most used geometrical complexes of topological data analysis such as the Rips or the Delaunay complexes. In practice, the
-size of this data-structure is even uch lower than the total number of simplices.
+size of this data-structure is even much lower than the total number of simplices.
The edge contraction operation consists in identifying two vertices of a simplicial complex.
A lot of algorithms have been developed in computer graphics that allows to reduce efficiently the size of 2-dimensional simplicial complexes
@@ -127,7 +127,7 @@ while ensuring its homotopy type is preserved during the contraction (edge are c
using namespace std;
using namespace Gudhi;
-using namespace skbl;
+using namespace skeleton_blocker;
using namespace contraction;
struct Geometry_trait{
@@ -158,7 +158,7 @@ void build_rips(ComplexType& complex, double offset){
for (auto p = vertices.begin(); p != vertices.end(); ++p)
for (auto q = p; ++q != vertices.end(); )
if (eucl_distance(complex.point(*p), complex.point(*q)) < 2 * offset)
- complex.add_edge(*p,*q);
+ complex.add_edge_without_blockers(*p,*q);
}
int main (int argc, char *argv[])
@@ -194,7 +194,7 @@ int main (int argc, char *argv[])
contractor.contract_edges();
std::cout << "Counting final number of simplices \n";
- unsigned num_simplices = std::distance(complex.simplex_range().begin(),complex.simplex_range().end());
+ unsigned num_simplices = std::distance(complex.star_simplex_range().begin(),complex.star_simplex_range().end());
std::cout << "Final complex has "<<
complex.num_vertices()<<" vertices, "<<
@@ -226,7 +226,6 @@ Time to simplify and enumerate simplices:
\copyright GNU General Public License v3.
-\verbatim Contact: David Salinas, david.salinas@inria.fr \endverbatim
*/
/** @} */ // end defgroup
} // namespace contraction
diff --git a/src/Contraction/include/gudhi/Skeleton_blocker_contractor.h b/src/Contraction/include/gudhi/Skeleton_blocker_contractor.h
index 2759b540..df884c93 100644
--- a/src/Contraction/include/gudhi/Skeleton_blocker_contractor.h
+++ b/src/Contraction/include/gudhi/Skeleton_blocker_contractor.h
@@ -37,7 +37,7 @@
#include <gudhi/Contraction/policies/Contraction_visitor.h>
#include <gudhi/Skeleton_blocker/Skeleton_blocker_complex_visitor.h>
-#include <gudhi/Utils.h>
+#include <gudhi/Debug_utils.h>
#include <boost/scoped_array.hpp>
@@ -100,20 +100,15 @@ Contraction_visitor<Profile>* make_remove_popable_blockers_visitor() {
*
*/
template<class GeometricSimplifiableComplex, class EdgeProfile = Edge_profile<GeometricSimplifiableComplex>>
-class Skeleton_blocker_contractor : private skbl::Dummy_complex_visitor<
+class Skeleton_blocker_contractor : private skeleton_blocker::Dummy_complex_visitor<
typename GeometricSimplifiableComplex::Vertex_handle> {
GeometricSimplifiableComplex& complex_;
public:
typedef typename GeometricSimplifiableComplex::Graph_vertex Graph_vertex;
typedef typename GeometricSimplifiableComplex::Vertex_handle Vertex_handle;
- typedef typename GeometricSimplifiableComplex::Simplex_handle Simplex_handle;
- typedef typename GeometricSimplifiableComplex::Simplex_handle_iterator Simplex_handle_iterator;
-
-
-
+ typedef typename GeometricSimplifiableComplex::Simplex Simplex;
typedef typename GeometricSimplifiableComplex::Root_vertex_handle Root_vertex_handle;
-
typedef typename GeometricSimplifiableComplex::Graph_edge Graph_edge;
typedef typename GeometricSimplifiableComplex::Edge_handle Edge_handle;
typedef typename GeometricSimplifiableComplex::Point Point;
@@ -535,14 +530,14 @@ typename GeometricSimplifiableComplex::Vertex_handle> {
* All the edges that passes through the blocker may be edge-contractible
* again and are thus reinserted in the heap.
*/
- void on_delete_blocker(const Simplex_handle * blocker) override {
+ void on_delete_blocker(const Simplex * blocker) override {
// we go for all pairs xy that belongs to the blocker
// note that such pairs xy are necessarily edges of the complex
// by definition of a blocker
// todo uniqument utile pour la link condition
// laisser a l'utilisateur ? booleen update_heap_on_removed_blocker?
- Simplex_handle blocker_copy(*blocker);
+ Simplex blocker_copy(*blocker);
for (auto x = blocker_copy.begin(); x != blocker_copy.end(); ++x) {
for (auto y = x; ++y != blocker_copy.end();) {
auto edge_descr(complex_[std::make_pair(*x, *y)]);
diff --git a/src/Doxyfile b/src/Doxyfile
index 85c496a8..943869ad 100644
--- a/src/Doxyfile
+++ b/src/Doxyfile
@@ -32,19 +32,19 @@ DOXYFILE_ENCODING = UTF-8
# title of most generated pages and in a few other places.
# The default value is: My Project.
-PROJECT_NAME = "Gudhi"
+PROJECT_NAME = "GUDHI"
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
# could be handy for archiving the generated documentation or if some version
# control system is used.
-PROJECT_NUMBER = "1.1.0"
+PROJECT_NUMBER = "1.3.1"
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
# quick idea about the purpose of the project. Keep the description short.
-PROJECT_BRIEF =
+PROJECT_BRIEF = "C++ library for Topological Data Analysis (TDA) and Higher Dimensional Geometry Understanding."
# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
# the documentation. The maximum height of the logo should not exceed 55 pixels
@@ -153,7 +153,7 @@ STRIP_FROM_PATH =
# specify the list of include paths that are normally passed to the compiler
# using the -I flag.
-STRIP_FROM_INC_PATH =
+STRIP_FROM_INC_PATH = include concept
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
# less readable) file names. This can be useful is your file systems doesn't
@@ -580,27 +580,27 @@ STRICT_PROTO_MATCHING = NO
# documentation.
# The default value is: YES.
-GENERATE_TODOLIST = YES
+GENERATE_TODOLIST = NO
# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
# test list. This list is created by putting \test commands in the
# documentation.
# The default value is: YES.
-GENERATE_TESTLIST = YES
+GENERATE_TESTLIST = NO
# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
# list. This list is created by putting \bug commands in the documentation.
# The default value is: YES.
-GENERATE_BUGLIST = YES
+GENERATE_BUGLIST = NO
# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
# the deprecated list. This list is created by putting \deprecated commands in
# the documentation.
# The default value is: YES.
-GENERATE_DEPRECATEDLIST= YES
+GENERATE_DEPRECATEDLIST= NO
# The ENABLED_SECTIONS tag can be used to enable conditional documentation
# sections, marked by \if <section_label> ... \endif and \cond <section_label>
@@ -672,7 +672,9 @@ LAYOUT_FILE =
# search path. Do not use file names with spaces, bibtex cannot handle them. See
# also \cite for info how to create references.
-CITE_BIB_FILES = biblio/bibliography.bib
+CITE_BIB_FILES = biblio/bibliography.bib \
+ biblio/how_to_cite_cgal.bib \
+ biblio/how_to_cite_gudhi.bib
#---------------------------------------------------------------------------
# Configuration options related to warning and progress messages
@@ -778,7 +780,11 @@ RECURSIVE = YES
# Note that relative paths are relative to the directory from which doxygen is
# run.
-EXCLUDE =
+EXCLUDE = data/ \
+ example/ \
+ GudhUI/ \
+ cmake/ \
+ debian/
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
@@ -811,14 +817,15 @@ EXCLUDE_SYMBOLS =
# that contain example code fragments that are included (see the \include
# command).
-EXAMPLE_PATH =
+EXAMPLE_PATH = biblio/ \
+ example/
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
# *.h) to filter out the source-files in the directories. If left blank all
# files are included.
-EXAMPLE_PATTERNS =
+EXAMPLE_PATTERNS =
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
# searched for input files to be used with the \include or \dontinclude commands
@@ -832,9 +839,16 @@ EXAMPLE_RECURSIVE = NO
# \image command).
IMAGE_PATH = doc/Skeleton_blocker/ \
+ doc/Alpha_complex/ \
doc/common/ \
- doc/Contraction/
-
+ doc/Contraction/ \
+ doc/Simplex_tree/ \
+ doc/Persistent_cohomology/ \
+ doc/Witness_complex/ \
+ doc/Bitmap_cubical_complex/ \
+ doc/Subsampling/ \
+ doc/Spatial_searching/ \
+ doc/Tangential_complex/
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
@@ -1038,7 +1052,7 @@ HTML_FILE_EXTENSION = .html
# of the possible markers and block names see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_HEADER =
+HTML_HEADER = doc/common/header.html
# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
# generated HTML page. If the tag is left blank doxygen will generate a standard
@@ -1048,7 +1062,7 @@ HTML_HEADER =
# that doxygen normally uses.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_FOOTER =
+HTML_FOOTER = doc/common/footer.html
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
# sheet that is used by each HTML page. It can be used to fine-tune the look of
@@ -1060,7 +1074,7 @@ HTML_FOOTER =
# obsolete.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_STYLESHEET =
+HTML_STYLESHEET = doc/common/stylesheet.css
# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user-
# defined cascading style sheet that is included after the standard style sheets
@@ -1338,7 +1352,7 @@ ECLIPSE_DOC_ID = org.doxygen.Project
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
-DISABLE_INDEX = NO
+DISABLE_INDEX = YES
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
# structure should be generated to display hierarchical information. If the tag
@@ -1355,7 +1369,7 @@ DISABLE_INDEX = NO
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
-GENERATE_TREEVIEW = NO
+GENERATE_TREEVIEW = YES
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
# doxygen will group on one line in the generated HTML documentation.
@@ -1543,7 +1557,7 @@ EXTRA_SEARCH_MAPPINGS =
# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
# The default value is: YES.
-GENERATE_LATEX = YES
+GENERATE_LATEX = NO
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
@@ -1595,7 +1609,7 @@ PAPER_TYPE = a4
# If left blank no extra packages will be included.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-EXTRA_PACKAGES = amsfonts amsmath amssymb
+EXTRA_PACKAGES = amsfonts amsmath amssymb algorithm algpseudocode
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
# generated LaTeX document. The header should contain everything until the first
@@ -1792,18 +1806,6 @@ GENERATE_XML = NO
XML_OUTPUT = xml
-# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a
-# validating XML parser to check the syntax of the XML files.
-# This tag requires that the tag GENERATE_XML is set to YES.
-
-XML_SCHEMA =
-
-# The XML_DTD tag can be used to specify a XML DTD, which can be used by a
-# validating XML parser to check the syntax of the XML files.
-# This tag requires that the tag GENERATE_XML is set to YES.
-
-XML_DTD =
-
# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
# listings (including syntax highlighting and cross-referencing information) to
# the XML output. Note that enabling this will significantly increase the size
diff --git a/src/GudhUI/CMakeLists.txt b/src/GudhUI/CMakeLists.txt
index c852c43f..d3a52b60 100644
--- a/src/GudhUI/CMakeLists.txt
+++ b/src/GudhUI/CMakeLists.txt
@@ -33,25 +33,6 @@ if ( CGAL_FOUND AND Qt5_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND )
SET(Boost_USE_STATIC_LIBS ON)
SET(Boost_USE_MULTITHREAD OFF)
- INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
- LINK_DIRECTORIES(${Boost_LIBRARY_DIRS})
-
- include(${CGAL_USE_FILE})
- # In CMakeLists.txt, when include(${CGAL_USE_FILE}), CXX_FLAGS are overwritten.
- # cf. http://doc.cgal.org/latest/Manual/installation.html#title40
- # A workaround is to add "-std=c++11" again.
- # A fix would be to use https://cmake.org/cmake/help/v3.1/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html
- # or even better https://cmake.org/cmake/help/v3.1/variable/CMAKE_CXX_STANDARD.html
- # but it implies to use cmake version 3.1 at least.
- if(NOT MSVC)
- include(CheckCXXCompilerFlag)
- CHECK_CXX_COMPILER_FLAG(-std=c++11 COMPILER_SUPPORTS_CXX11)
- if(COMPILER_SUPPORTS_CXX11)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
- endif()
- endif()
- # - End of workaround
-
include_directories (${QGLVIEWER_INCLUDE_DIR})
#####################################################################
@@ -69,6 +50,11 @@ if ( CGAL_FOUND AND Qt5_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND )
target_link_libraries( GudhUI Qt5::Widgets Qt5::Xml Qt5::OpenGL )
target_link_libraries( GudhUI ${QGLVIEWER_LIBRARIES} )
target_link_libraries( GudhUI ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} )
+if (TBB_FOUND)
+ target_link_libraries( GudhUI ${TBB_LIBRARIES})
+endif()
+
+###############################################################################
else()
message(STATUS "NOTICE: GudhUI requires CGAL, the QGLViewer, OpenGL and Qt5, and will not be compiled.")
diff --git a/src/GudhUI/gui/MainWindow.h b/src/GudhUI/gui/MainWindow.h
index 7e11ddd6..15664dcb 100644
--- a/src/GudhUI/gui/MainWindow.h
+++ b/src/GudhUI/gui/MainWindow.h
@@ -23,6 +23,9 @@
#ifndef GUI_MAINWINDOW_H_
#define GUI_MAINWINDOW_H_
+// Workaround https://svn.boost.org/trac/boost/ticket/12534
+#include <boost/container/flat_map.hpp>
+
#include <QMainWindow>
#include "ui_main_window.h"
#include "model/Model.h"
diff --git a/src/GudhUI/gui/MenuEdgeContraction.ui b/src/GudhUI/gui/MenuEdgeContraction.ui
index da2e5c82..b1696431 100644
--- a/src/GudhUI/gui/MenuEdgeContraction.ui
+++ b/src/GudhUI/gui/MenuEdgeContraction.ui
@@ -1,118 +1,118 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>MenuEdgeContraction</class>
- <widget class="QDialog" name="MenuEdgeContraction">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>362</width>
- <height>209</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Edge contraction</string>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="5" column="2">
- <widget class="QSpinBox" name="spinBox_nb_remaining_vertices">
- <property name="minimum">
- <number>1</number>
- </property>
- <property name="maximum">
- <number>999999999</number>
- </property>
- <property name="value">
- <number>1</number>
- </property>
- </widget>
- </item>
- <item row="7" column="2">
- <widget class="QCheckBox" name="checkBox_link_condition">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="text">
- <string>Link condition</string>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item row="3" column="2" alignment="Qt::AlignRight">
- <widget class="QLabel" name="txt_nb_collapses">
- <property name="text">
- <string>1</string>
- </property>
- </widget>
- </item>
- <item row="6" column="0">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Policy</string>
- </property>
- </widget>
- </item>
- <item row="6" column="2">
- <widget class="QComboBox" name="m_simplificationMethod">
- <item>
- <property name="text">
- <string>Length_midpoint</string>
- </property>
- </item>
- </widget>
- </item>
- <item row="2" column="2" alignment="Qt::AlignRight">
- <widget class="QLabel" name="txt_nb_vertices">
- <property name="text">
- <string>0</string>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_5">
- <property name="text">
- <string>Number of vertices</string>
- </property>
- </widget>
- </item>
- <item row="3" column="0" colspan="2">
- <widget class="QLabel" name="label_3">
- <property name="text">
- <string>Number of contractions</string>
- </property>
- </widget>
- </item>
- <item row="5" column="0" colspan="2">
- <widget class="QLabel" name="label_4">
- <property name="text">
- <string>Number of vertices after </string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QSlider" name="horizontalSlider">
- <property name="minimum">
- <number>0</number>
- </property>
- <property name="maximum">
- <number>100</number>
- </property>
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- </widget>
- </item>
- <item row="1" column="2">
- <widget class="QPushButton" name="pushButton_collapse">
- <property name="text">
- <string>Perform collapse</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MenuEdgeContraction</class>
+ <widget class="QDialog" name="MenuEdgeContraction">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>362</width>
+ <height>209</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Edge contraction</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="5" column="2">
+ <widget class="QSpinBox" name="spinBox_nb_remaining_vertices">
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ <property name="maximum">
+ <number>999999999</number>
+ </property>
+ <property name="value">
+ <number>1</number>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="2">
+ <widget class="QCheckBox" name="checkBox_link_condition">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Link condition</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="2" alignment="Qt::AlignRight">
+ <widget class="QLabel" name="txt_nb_collapses">
+ <property name="text">
+ <string>1</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Policy</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="2">
+ <widget class="QComboBox" name="m_simplificationMethod">
+ <item>
+ <property name="text">
+ <string>Length_midpoint</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="2" column="2" alignment="Qt::AlignRight">
+ <widget class="QLabel" name="txt_nb_vertices">
+ <property name="text">
+ <string>0</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>Number of vertices</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="2">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Number of contractions</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0" colspan="2">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Number of vertices after </string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QSlider" name="horizontalSlider">
+ <property name="minimum">
+ <number>0</number>
+ </property>
+ <property name="maximum">
+ <number>100</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QPushButton" name="pushButton_collapse">
+ <property name="text">
+ <string>Perform collapse</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/GudhUI/gui/gudhui.cpp b/src/GudhUI/gui/gudhui.cpp
index 377cd2f2..276c4a5f 100644
--- a/src/GudhUI/gui/gudhui.cpp
+++ b/src/GudhUI/gui/gudhui.cpp
@@ -1,38 +1,38 @@
-/* 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/>.
- *
- */
-
-#include "MainWindow.h"
-#include <QApplication>
-#include <CGAL/Qt/resources.h>
-
-int main(int argc, char** argv) {
- QApplication application(argc, argv);
- application.setOrganizationDomain("inria.fr");
- application.setOrganizationName("INRIA");
- application.setApplicationName("GudhUI");
-
- MainWindow mw;
- application.setQuitOnLastWindowClosed(false);
- mw.show();
- return application.exec();
-}
+/* 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/>.
+ *
+ */
+
+#include "MainWindow.h"
+#include <QApplication>
+#include <CGAL/Qt/resources.h>
+
+int main(int argc, char** argv) {
+ QApplication application(argc, argv);
+ application.setOrganizationDomain("inria.fr");
+ application.setOrganizationName("INRIA");
+ application.setApplicationName("GudhUI");
+
+ MainWindow mw;
+ application.setQuitOnLastWindowClosed(false);
+ mw.show();
+ return application.exec();
+}
diff --git a/src/GudhUI/model/Complex_typedefs.h b/src/GudhUI/model/Complex_typedefs.h
index c310d4a6..a4df2c94 100644
--- a/src/GudhUI/model/Complex_typedefs.h
+++ b/src/GudhUI/model/Complex_typedefs.h
@@ -41,7 +41,7 @@ struct Geometry_trait : public CGAL::Cartesian_d<double> {
typedef Geometry_trait::Point Point;
using namespace Gudhi;
-using namespace Gudhi::skbl;
+using namespace Gudhi::skeleton_blocker;
typedef Skeleton_blocker_simple_geometric_traits<Geometry_trait> Complex_geometric_traits;
typedef Skeleton_blocker_geometric_complex< Complex_geometric_traits > Complex;
diff --git a/src/GudhUI/model/Model.h b/src/GudhUI/model/Model.h
index d78cbad9..fc284cc6 100644
--- a/src/GudhUI/model/Model.h
+++ b/src/GudhUI/model/Model.h
@@ -71,9 +71,9 @@ class CGAL_geometric_flag_complex_wrapper {
void maximal_face(std::vector<int> vertices) {
if (!load_only_points_) {
- std::cout << "size:" << vertices.size() << std::endl;
- for (int i = 0; i < vertices.size(); ++i)
- for (int j = i + 1; j < vertices.size(); ++j)
+ // std::cout << "size:" << vertices.size() << std::endl;
+ for (std::size_t i = 0; i < vertices.size(); ++i)
+ for (std::size_t j = i + 1; j < vertices.size(); ++j)
complex_.add_edge(Vertex_handle(vertices[i]), Vertex_handle(vertices[j]));
}
}
@@ -187,7 +187,7 @@ class Model {
}
void contract_edges(unsigned num_contractions) {
- Clock c;
+ Gudhi::Clock c;
Edge_contractor<Complex> contractor(complex_, num_contractions);
std::cout << "Time to simplify: " << c.num_seconds() << "s" << std::endl;
}
@@ -248,8 +248,8 @@ class Model {
unsigned num_simplices = 0;
int euler = 0;
int dimension = 0;
- Clock clock;
- for (const auto &s : complex_.simplex_range()) {
+ Gudhi::Clock clock;
+ for (const auto &s : complex_.complex_simplex_range()) {
num_simplices++;
dimension = (std::max)(s.dimension(), dimension);
if (s.dimension() % 2 == 0)
@@ -271,7 +271,7 @@ class Model {
#ifdef _WIN32
std::cout << "Works only on linux x64 for the moment\n";
#else
- Clock clock;
+ Gudhi::Clock clock;
run_chomp();
clock.end();
#endif
@@ -281,7 +281,7 @@ class Model {
unsigned num_simplices = 0;
int euler = 0;
int dimension = 0;
- for (const auto &s : complex_.simplex_range()) {
+ for (const auto &s : complex_.complex_simplex_range()) {
num_simplices++;
dimension = (std::max)(s.dimension(), dimension);
if (s.dimension() % 2 == 0)
@@ -328,7 +328,7 @@ class Model {
void save_complex_in_file_for_chomp() {
std::ofstream file;
file.open("chomp.sim");
- for (const auto &s : complex_.simplex_range()) {
+ for (const auto &s : complex_.complex_simplex_range()) {
bool first = true;
file << "(";
for (auto x : s) {
diff --git a/src/GudhUI/utils/Bar_code_persistence.h b/src/GudhUI/utils/Bar_code_persistence.h
new file mode 100644
index 00000000..b527d684
--- /dev/null
+++ b/src/GudhUI/utils/Bar_code_persistence.h
@@ -0,0 +1,90 @@
+#include <math.h> // isfinite
+
+#include <QtGui/QApplication>
+
+#include <QGraphicsView>
+#include <QGraphicsScene>
+#include <QPointF>
+#include <QVector>
+#include <QGraphicsTextItem>
+
+#include <iostream>
+#include <vector>
+#include <limits> // NaN, infinity
+#include <utility> // for pair
+#include <string>
+
+#ifndef UTILS_BAR_CODE_PERSISTENCE_H_
+#define UTILS_BAR_CODE_PERSISTENCE_H_
+
+class Bar_code_persistence {
+ private:
+ typedef std::vector<std::pair<double, double>> Persistence;
+ Persistence persistence_vector;
+ double min_birth;
+ double max_death;
+
+ public:
+ Bar_code_persistence()
+ : min_birth(std::numeric_limits<double>::quiet_NaN()),
+ max_death(std::numeric_limits<double>::quiet_NaN()) { }
+
+ void insert(double birth, double death) {
+ persistence_vector.push_back(std::make_pair(birth, death));
+ if (std::isfinite(birth)) {
+ if ((birth < min_birth) || (std::isnan(min_birth)))
+ min_birth = birth;
+ if ((birth > max_death) || (std::isnan(max_death)))
+ max_death = birth;
+ }
+ if (std::isfinite(death))
+ if ((death > max_death) || (std::isnan(max_death)))
+ max_death = death;
+ }
+
+ void show(const std::string& window_title) {
+ // Create a view, put a scene in it
+ QGraphicsView * view = new QGraphicsView();
+ QGraphicsScene * scene = new QGraphicsScene();
+ view->setScene(scene);
+ double ratio = 600.0 / (max_death - min_birth);
+ // std::cout << "min_birth=" << min_birth << " - max_death=" << max_death << " - ratio=" << ratio << std::endl;
+
+ double height = 0.0, birth = 0.0, death = 0.0;
+ int pers_num = 1;
+ for (auto& persistence : persistence_vector) {
+ height = 5.0 * pers_num;
+ // std::cout << "[" << pers_num << "] birth=" << persistence.first << " - death=" << persistence.second << std::endl;
+ if (std::isfinite(persistence.first))
+ birth = ((persistence.first - min_birth) * ratio) + 50.0;
+ else
+ birth = 0.0;
+
+ if (std::isfinite(persistence.second))
+ death = ((persistence.second - min_birth) * ratio) + 50.0;
+ else
+ death = 700.0;
+
+ scene->addLine(birth, height, death, height, QPen(Qt::blue, 2));
+ pers_num++;
+ }
+ height += 10.0;
+ // scale line
+ scene->addLine(0, height, 700.0, height, QPen(Qt::black, 1));
+ int modulo = 0;
+ for (double scale = 50.0; scale < 700.0; scale += 50.0) {
+ modulo++;
+ // scale small dash
+ scene->addLine(scale, height - 3.0, scale, height + 3.0, QPen(Qt::black, 1));
+ // scale text
+ QString scale_value = QString::number(((scale - 50.0) / ratio) + min_birth);
+ QGraphicsTextItem* dimText = scene->addText(scale_value, QFont("Helvetica", 8));
+ dimText->setPos(scale - (3.0 * scale_value.size()), height + 9.0 * (modulo % 2));
+ }
+ view->setWindowTitle(window_title.c_str());
+ // Show the view
+ view->show();
+ }
+};
+
+#endif // UTILS_BAR_CODE_PERSISTENCE_H_
diff --git a/src/GudhUI/utils/Edge_contractor.h b/src/GudhUI/utils/Edge_contractor.h
index 45079a40..8a29ff4b 100644
--- a/src/GudhUI/utils/Edge_contractor.h
+++ b/src/GudhUI/utils/Edge_contractor.h
@@ -65,7 +65,7 @@ template<typename SkBlComplex> class Edge_contractor {
Placement_type operator()(const EdgeProfile& profile) const override {
std::vector<double> mid_coords(profile.p0().dimension(), 0);
- for (size_t i = 0; i < profile.p0().dimension(); ++i) {
+ for (int i = 0; i < profile.p0().dimension(); ++i) {
mid_coords[i] = (profile.p0()[i] + profile.p1()[i]) / 2.;
}
return Point(profile.p0().dimension(), mid_coords.begin(), mid_coords.end());
diff --git a/src/GudhUI/utils/Furthest_point_epsilon_net.h b/src/GudhUI/utils/Furthest_point_epsilon_net.h
index f2a216f6..98346daa 100644
--- a/src/GudhUI/utils/Furthest_point_epsilon_net.h
+++ b/src/GudhUI/utils/Furthest_point_epsilon_net.h
@@ -73,7 +73,7 @@ template<typename SkBlComplex> class Furthest_point_epsilon_net {
complex_(complex) {
if (!complex.empty()) {
init_filtration();
- for (int k = 2; k < net_filtration_.size(); ++k) {
+ for (std::size_t k = 2; k < net_filtration_.size(); ++k) {
update_radius_value(k);
}
}
diff --git a/src/GudhUI/utils/Is_manifold.h b/src/GudhUI/utils/Is_manifold.h
index b6b19ee0..0640ea47 100644
--- a/src/GudhUI/utils/Is_manifold.h
+++ b/src/GudhUI/utils/Is_manifold.h
@@ -69,7 +69,7 @@ template<typename SkBlComplex> class Is_manifold {
private:
unsigned local_dimension(Vertex_handle v) {
unsigned dim = 0;
- for (const auto& s : input_complex_.simplex_range(v))
+ for (const auto& s : input_complex_.star_simplex_range(v))
dim = (std::max)(dim, (unsigned) s.dimension());
return dim;
}
diff --git a/src/GudhUI/utils/K_nearest_builder.h b/src/GudhUI/utils/K_nearest_builder.h
index cab24b7c..7be0a4f4 100644
--- a/src/GudhUI/utils/K_nearest_builder.h
+++ b/src/GudhUI/utils/K_nearest_builder.h
@@ -29,12 +29,10 @@
#include <CGAL/Search_traits_d.h>
#include <CGAL/Search_traits_adapter.h>
#include <CGAL/property_map.h>
-#include <boost/iterator/iterator_facade.hpp>
-#include <boost/iterator/zip_iterator.hpp>
#include <unordered_map>
-#include <tuple>
#include <list>
+#include <utility>
#include "utils/UI_utils.h"
#include "model/Complex_typedefs.h"
@@ -43,9 +41,9 @@ template<typename SkBlComplex> class K_nearest_builder {
private:
typedef Geometry_trait Kernel;
typedef Point Point_d;
- typedef boost::tuple<Point_d, unsigned> Point_d_with_id;
+ typedef std::pair<Point_d, unsigned> Point_d_with_id;
typedef CGAL::Search_traits_d<Kernel> Traits_base;
- typedef CGAL::Search_traits_adapter<Point_d_with_id, CGAL::Nth_of_tuple_property_map<0, Point_d_with_id>,
+ typedef CGAL::Search_traits_adapter<Point_d_with_id, CGAL::First_of_pair_property_map<Point_d_with_id>,
Traits_base> Traits;
typedef CGAL::Orthogonal_k_neighbor_search<Traits> Neighbor_search;
typedef Neighbor_search::Tree Tree;
@@ -81,7 +79,7 @@ template<typename SkBlComplex> class K_nearest_builder {
for (auto p : complex_.vertex_range()) {
Neighbor_search search(tree, complex_.point(p), k + 1);
for (auto it = ++search.begin(); it != search.end(); ++it) {
- Vertex_handle q(boost::get<1>(it->first));
+ Vertex_handle q(std::get<1>(it->first));
if (p != q && complex_.contains_vertex(p) && complex_.contains_vertex(q))
complex_.add_edge(p, q);
}
diff --git a/src/GudhUI/utils/Persistence_compute.h b/src/GudhUI/utils/Persistence_compute.h
index 0b9961d3..97165490 100644
--- a/src/GudhUI/utils/Persistence_compute.h
+++ b/src/GudhUI/utils/Persistence_compute.h
@@ -46,10 +46,6 @@ struct Persistence_params {
* Show persistence into output stream
*/
template<typename SkBlComplex> class Persistence_compute {
- private:
- SkBlComplex& complex_;
- std::ostream& stream_;
-
public:
typedef typename SkBlComplex::Vertex_handle Vertex_handle;
typedef typename SkBlComplex::Edge_handle Edge_handle;
@@ -61,9 +57,7 @@ template<typename SkBlComplex> class Persistence_compute {
* double threshold
* int p for coefficient Z_p
*/
- Persistence_compute(SkBlComplex& complex, std::ostream& stream, const Persistence_params& params) :
- // double threshold = 0.5,unsigned dim_max = 8):
- complex_(complex), stream_(stream) {
+ Persistence_compute(SkBlComplex& complex, std::ostream& stream, const Persistence_params& params) {
// for now everything is copied, todo boost adapt iterators to points of SkBlComplex instead of copying to an
// initial vector
typedef std::vector<double> Point_t;
@@ -87,10 +81,10 @@ template<typename SkBlComplex> class Persistence_compute {
pcoh.init_coefficients(params.p);
// put params.min_pers
pcoh.compute_persistent_cohomology(params.min_pers);
- stream_ << "persistence: \n";
- stream_ << "p dimension birth death: \n";
+ stream << "persistence: \n";
+ stream << "p dimension birth death: \n";
- pcoh.output_diagram(stream_);
+ pcoh.output_diagram(stream);
}
};
diff --git a/src/GudhUI/view/FirstCoordProjector.h b/src/GudhUI/view/FirstCoordProjector.h
index 529d2d42..1333f5d3 100644
--- a/src/GudhUI/view/FirstCoordProjector.h
+++ b/src/GudhUI/view/FirstCoordProjector.h
@@ -32,8 +32,12 @@ class FirstCoordProjector3D : public Projector3D {
typedef Projector3D::Point_3 Point_3;
Point_3 operator()(const Point& p) const {
- assert(p.dimension() >= 3);
- return Point_3(p.x(), p.y(), p.z());
+ if (p.dimension() >= 3)
+ return Point_3(p.x(), p.y(), p.z());
+ else if (p.dimension() >= 2)
+ return Point_3(p.x(), p.y(), 0.0);
+ else
+ return Point_3(0.0, 0.0, 0.0);
}
};
diff --git a/src/GudhUI/view/Viewer.h b/src/GudhUI/view/Viewer.h
index 48427099..797ddc53 100644
--- a/src/GudhUI/view/Viewer.h
+++ b/src/GudhUI/view/Viewer.h
@@ -1,117 +1,117 @@
-/* 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 VIEW_VIEWER_H_
-#define VIEW_VIEWER_H_
-
-#include <QGLViewer/qglviewer.h>
-
-#include <vector>
-
-#include "View_parameter.h"
-#include "model/Complex_typedefs.h"
-#include "Color.h"
-#include "Viewer_instructor.h"
-
-class Viewer_instructor;
-
-class Viewer : public QGLViewer {
- Q_OBJECT
-
- Viewer_instructor * instructor;
-
- /**
- * light angles
- */
- double theta, phi;
- typedef Complex::GT Gudhi_kernel;
- typedef Gudhi_kernel::Point_3 Point_3;
-
- public:
- Viewer(QWidget* parent);
-
- void set_instructor(Viewer_instructor* instructor_);
-
- void show_entire_scene();
-
- void draw();
-
- void set_bounding_box(const Point_3 & lower_left, const Point_3 & upper_right);
-
- void update_GL();
-
- void init_scene();
-
- void init_light();
-
- void set_light();
-
- void set_light_direction(double theta, double phi);
-
- /**
- * set the light in the direction of the observer
- */
- void set_light_direction();
-
- protected:
- virtual void postSelection(const QPoint& point);
-
- public:
- ////////////////////////
- // draw
- ////////////////////////
- void set_size_point(double size_points);
-
- void set_color(const Color& color);
-
- void draw_point(const Point_3& p, const Color& color, double size_points);
-
- void begin_draw_points(double size, bool light = false);
-
- void draw_points(const Point_3 & point);
-
- void end_draw_points();
-
- void draw_edge(const Point_3 &a, const Point_3 &b, const Color& color, double size);
-
- void begin_draw_edges(double size, bool light = false);
-
- void draw_edges(const Point_3 &a, const Point_3 &b);
-
- void end_draw_edges();
-
- void begin_draw_triangles(double size, bool light, bool transparent = false);
-
- void draw_triangles(const Point_3& p1, const Point_3& p2, const Point_3& p3);
-
- // todo remove
- void draw_triangles(const std::vector<Point_3*>& points);
-
- void end_draw_triangles();
-
-
- signals:
- void click(const Point_3& position);
-};
-
-#endif // VIEW_VIEWER_H_
+/* 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 VIEW_VIEWER_H_
+#define VIEW_VIEWER_H_
+
+#include <QGLViewer/qglviewer.h>
+
+#include <vector>
+
+#include "View_parameter.h"
+#include "model/Complex_typedefs.h"
+#include "Color.h"
+#include "Viewer_instructor.h"
+
+class Viewer_instructor;
+
+class Viewer : public QGLViewer {
+ Q_OBJECT
+
+ Viewer_instructor * instructor;
+
+ /**
+ * light angles
+ */
+ double theta, phi;
+ typedef Complex::GT Gudhi_kernel;
+ typedef Gudhi_kernel::Point_3 Point_3;
+
+ public:
+ Viewer(QWidget* parent);
+
+ void set_instructor(Viewer_instructor* instructor_);
+
+ void show_entire_scene();
+
+ void draw();
+
+ void set_bounding_box(const Point_3 & lower_left, const Point_3 & upper_right);
+
+ void update_GL();
+
+ void init_scene();
+
+ void init_light();
+
+ void set_light();
+
+ void set_light_direction(double theta, double phi);
+
+ /**
+ * set the light in the direction of the observer
+ */
+ void set_light_direction();
+
+ protected:
+ virtual void postSelection(const QPoint& point);
+
+ public:
+ ////////////////////////
+ // draw
+ ////////////////////////
+ void set_size_point(double size_points);
+
+ void set_color(const Color& color);
+
+ void draw_point(const Point_3& p, const Color& color, double size_points);
+
+ void begin_draw_points(double size, bool light = false);
+
+ void draw_points(const Point_3 & point);
+
+ void end_draw_points();
+
+ void draw_edge(const Point_3 &a, const Point_3 &b, const Color& color, double size);
+
+ void begin_draw_edges(double size, bool light = false);
+
+ void draw_edges(const Point_3 &a, const Point_3 &b);
+
+ void end_draw_edges();
+
+ void begin_draw_triangles(double size, bool light, bool transparent = false);
+
+ void draw_triangles(const Point_3& p1, const Point_3& p2, const Point_3& p3);
+
+ // todo remove
+ void draw_triangles(const std::vector<Point_3*>& points);
+
+ void end_draw_triangles();
+
+
+ signals:
+ void click(const Point_3& position);
+};
+
+#endif // VIEW_VIEWER_H_
diff --git a/src/GudhUI/view/Viewer_instructor.cpp b/src/GudhUI/view/Viewer_instructor.cpp
index 4446d209..1ddd4d8b 100644
--- a/src/GudhUI/view/Viewer_instructor.cpp
+++ b/src/GudhUI/view/Viewer_instructor.cpp
@@ -159,7 +159,7 @@ void Viewer_instructor::set_color_edge(Edge_handle eh) {
viewer_->set_color(Color(view_params_.light_edges, view_params_.light_edges, view_params_.light_edges));
}
-void Viewer_instructor::set_color_triangle(const Simplex_handle& triangle) {
+void Viewer_instructor::set_color_triangle(const Simplex& triangle) {
viewer_->set_color(Color(view_params_.light_triangles, view_params_.light_triangles, view_params_.light_triangles));
}
diff --git a/src/GudhUI/view/Viewer_instructor.h b/src/GudhUI/view/Viewer_instructor.h
index 96b25c77..05c5c1fc 100644
--- a/src/GudhUI/view/Viewer_instructor.h
+++ b/src/GudhUI/view/Viewer_instructor.h
@@ -1,114 +1,114 @@
-/* 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 VIEW_VIEWER_INSTRUCTOR_H_
-#define VIEW_VIEWER_INSTRUCTOR_H_
-
-// todo do a viewer instructor that have directely a pointer to a QGLviewer and buffer ot not triangles
-
-#include <QFileDialog>
-#include <QKeyEvent>
-#include <QGLViewer/camera.h>
-
-#include <memory>
-#include <utility> // for pair<>
-
-#include "model/Complex_typedefs.h"
-
-#include "Projector3D.h"
-#include "View_parameter.h"
-#include "Viewer.h"
-
-class Viewer;
-class Viewer_parameter;
-
-class Viewer_instructor : public QWidget {
- Q_OBJECT
-
- typedef Geometry_trait::Point_3 Point_3;
- typedef Complex::Point Point;
- typedef Complex::Vertex_handle Vertex_handle;
- typedef Complex::Edge_handle Edge_handle;
- typedef Complex::Simplex_handle Simplex_handle;
-
- Viewer* viewer_;
- View_parameter view_params_;
- const Complex& mesh_;
- std::unique_ptr<Projector3D> projector_;
-
- public:
- Viewer_instructor(QWidget* parent, Viewer* viewer, const Complex& mesh);
-
- void initialize_bounding_box();
-
- std::pair<Point, Point> compute_bounding_box_corners();
-
- void show_entire_scene();
-
- const qglviewer::Camera* camera() const;
-
- int width() const;
- int height() const;
-
- /**
- * to change display parameters
- */
- View_parameter& view_params();
-
- public:
- /**
- * gives instructions to the viewer
- */
- void give_instructions();
-
- void draw_edges();
- void draw_triangles();
- void draw_points();
-
- void draw_edge(const Point&, const Point&);
-
- void draw_point(const Point&);
-
- /**
- * set the right color of vertex/edge/triangle considering the view_params choice
- */
- void set_color_vertex(Vertex_handle vh);
- void set_color_edge(Edge_handle eh);
-
- void set_color_triangle(const Simplex_handle& triangle);
-
- private:
- /**
- * Projection to 3D needed for the viewer.
- */
- Point_3 proj(const Point& p) const;
-
- public slots:
- void sceneChanged();
- void change_draw_vertices();
- void change_draw_edges();
- void change_draw_triangles();
- void change_light();
-};
-
-#endif // VIEW_VIEWER_INSTRUCTOR_H_
+/* 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 VIEW_VIEWER_INSTRUCTOR_H_
+#define VIEW_VIEWER_INSTRUCTOR_H_
+
+// todo do a viewer instructor that have directely a pointer to a QGLviewer and buffer ot not triangles
+
+#include <QFileDialog>
+#include <QKeyEvent>
+#include <QGLViewer/camera.h>
+
+#include <memory>
+#include <utility> // for pair<>
+
+#include "model/Complex_typedefs.h"
+
+#include "Projector3D.h"
+#include "View_parameter.h"
+#include "Viewer.h"
+
+class Viewer;
+class Viewer_parameter;
+
+class Viewer_instructor : public QWidget {
+ Q_OBJECT
+
+ typedef Geometry_trait::Point_3 Point_3;
+ typedef Complex::Point Point;
+ typedef Complex::Vertex_handle Vertex_handle;
+ typedef Complex::Edge_handle Edge_handle;
+ typedef Complex::Simplex Simplex;
+
+ Viewer* viewer_;
+ View_parameter view_params_;
+ const Complex& mesh_;
+ std::unique_ptr<Projector3D> projector_;
+
+ public:
+ Viewer_instructor(QWidget* parent, Viewer* viewer, const Complex& mesh);
+
+ void initialize_bounding_box();
+
+ std::pair<Point, Point> compute_bounding_box_corners();
+
+ void show_entire_scene();
+
+ const qglviewer::Camera* camera() const;
+
+ int width() const;
+ int height() const;
+
+ /**
+ * to change display parameters
+ */
+ View_parameter& view_params();
+
+ public:
+ /**
+ * gives instructions to the viewer
+ */
+ void give_instructions();
+
+ void draw_edges();
+ void draw_triangles();
+ void draw_points();
+
+ void draw_edge(const Point&, const Point&);
+
+ void draw_point(const Point&);
+
+ /**
+ * set the right color of vertex/edge/triangle considering the view_params choice
+ */
+ void set_color_vertex(Vertex_handle vh);
+ void set_color_edge(Edge_handle eh);
+
+ void set_color_triangle(const Simplex& triangle);
+
+ private:
+ /**
+ * Projection to 3D needed for the viewer.
+ */
+ Point_3 proj(const Point& p) const;
+
+ public slots:
+ void sceneChanged();
+ void change_draw_vertices();
+ void change_draw_edges();
+ void change_draw_triangles();
+ void change_light();
+};
+
+#endif // VIEW_VIEWER_INSTRUCTOR_H_
diff --git a/src/Hasse_complex/include/gudhi/Hasse_complex.h b/src/Hasse_complex/include/gudhi/Hasse_complex.h
index 67079687..8b06b771 100644
--- a/src/Hasse_complex/include/gudhi/Hasse_complex.h
+++ b/src/Hasse_complex/include/gudhi/Hasse_complex.h
@@ -23,12 +23,18 @@
#ifndef HASSE_COMPLEX_H_
#define HASSE_COMPLEX_H_
+#include <gudhi/allocator.h>
+
#include <boost/iterator/counting_iterator.hpp>
#include <algorithm>
#include <utility> // for pair
#include <vector>
+#ifdef GUDHI_USE_TBB
+#include <tbb/parallel_for.h>
+#endif
+
namespace Gudhi {
template < class HasseCpx >
@@ -38,8 +44,7 @@ struct Hasse_simplex {
template< class Complex_ds >
Hasse_simplex(Complex_ds & cpx
, typename Complex_ds::Simplex_handle sh)
- : key_(cpx.key(sh))
- , filtration_(cpx.filtration(sh))
+ : filtration_(cpx.filtration(sh))
, boundary_() {
boundary_.reserve(cpx.dimension(sh) + 1);
for (auto b_sh : cpx.boundary_simplex_range(sh)) {
@@ -49,7 +54,7 @@ struct Hasse_simplex {
Hasse_simplex(typename HasseCpx::Simplex_key key
, typename HasseCpx::Filtration_value fil
- , std::vector<typename HasseCpx::Simplex_handle> boundary)
+ , std::vector<typename HasseCpx::Simplex_handle> const& boundary)
: key_(key)
, filtration_(fil)
, boundary_(boundary) { }
@@ -97,20 +102,24 @@ class Hasse_complex {
template < class Complex_ds >
Hasse_complex(Complex_ds & cpx)
- : complex_()
+ : complex_(cpx.num_simplices())
, vertices_()
, threshold_(cpx.filtration())
, num_vertices_()
, dim_max_(cpx.dimension()) {
- complex_.reserve(cpx.num_simplices());
- int idx = 0;
- for (auto cpx_sh : cpx.filtration_simplex_range()) {
- complex_.push_back(Hasse_simp(cpx, cpx_sh));
- if (dimension(idx) == 0) {
+ int size = complex_.size();
+#ifdef GUDHI_USE_TBB
+ tbb::parallel_for(0, size, [&](int idx){new (&complex_[idx]) Hasse_simp(cpx, cpx.simplex(idx));});
+ for (int idx=0; idx < size; ++idx)
+ if (complex_[idx].boundary_.empty())
+ vertices_.push_back(idx);
+#else
+ for (int idx=0; idx < size; ++idx) {
+ new (&complex_[idx]) Hasse_simp(cpx, cpx.simplex(idx));
+ if (complex_[idx].boundary_.empty())
vertices_.push_back(idx);
- }
- ++idx;
}
+#endif
}
Hasse_complex()
@@ -187,14 +196,15 @@ class Hasse_complex {
}
void initialize_filtration() {
+ // Setting the keys is done by pcoh, Simplex_tree doesn't do it either.
+#if 0
Simplex_key key = 0;
- for (auto & h_simp : complex_) {
- h_simp.key_ = key;
- ++key;
- }
+ for (auto & h_simp : complex_)
+ h_simp.key_ = key++;
+#endif
}
- std::vector< Hasse_simp > complex_;
+ std::vector< Hasse_simp, Gudhi::no_init_allocator<Hasse_simp> > complex_;
std::vector<Simplex_handle> vertices_;
Filtration_value threshold_;
size_t num_vertices_;
@@ -218,7 +228,7 @@ std::istream& operator>>(std::istream & is
// read all simplices in the file as a list of vertices
while (read_hasse_simplex(is, boundary, fil)) {
// insert every simplex in the simplex tree
- hcpx.complex_.push_back(Hasse_simplex< Hasse_complex<T1, T2, T3> >(key, fil, boundary));
+ hcpx.complex_.emplace_back(key, fil, boundary);
if (max_dim < hcpx.dimension(key)) {
max_dim = hcpx.dimension(key);
diff --git a/src/Persistent_cohomology/concept/FilteredComplex.h b/src/Persistent_cohomology/concept/FilteredComplex.h
index 1834903b..c19698df 100644
--- a/src/Persistent_cohomology/concept/FilteredComplex.h
+++ b/src/Persistent_cohomology/concept/FilteredComplex.h
@@ -43,7 +43,7 @@ struct FilteredComplex
* is model of IndexingTag. */
typedef unspecified Indexing_tag;
-/** Returns a Simplex_hanlde that is different from all simplex handles
+/** Returns a Simplex_handle that is different from all simplex handles
* of the simplices. */
Simplex_handle null_simplex();
/** \brief Returns the number of simplices in the complex.
@@ -61,13 +61,14 @@ struct FilteredComplex
/** \brief Returns a key that is different from the keys associated
* to the simplices. */
Simplex_key null_key ();
-/** \brief Returns the key associated to a simplex. */
+/** \brief Returns the key associated to a simplex.
+ *
+ * This is never called on null_simplex(). */
Simplex_key key ( Simplex_handle sh );
-/** \brief Returns the simplex associated to a key.
- *
- * If key is different from null_key(), there must be a unique
- * simplex having this key. */
- Simplex_handle simplex ( Simplex_key key );
+/** \brief Returns the simplex that has index idx in the filtration.
+ *
+ * This is never called on null_key(). */
+ Simplex_handle simplex ( Simplex_key idx );
/** \brief Assign a key to a simplex. */
void assign_key(Simplex_handle sh, Simplex_key key);
@@ -138,6 +139,6 @@ Filtration_simplex_range filtration_simplex_range();
* @todo use an enum? Just a bool?
*/
//int is_before_in_filtration(Simplex_handle s, Simplex_handle t);
-/*************************************************/
+/*************************************************/
};
diff --git a/src/Persistent_cohomology/doc/3DTorus_poch.png b/src/Persistent_cohomology/doc/3DTorus_poch.png
new file mode 100644
index 00000000..1c9d8328
--- /dev/null
+++ b/src/Persistent_cohomology/doc/3DTorus_poch.png
Binary files differ
diff --git a/src/Persistent_cohomology/doc/Intro_persistent_cohomology.h b/src/Persistent_cohomology/doc/Intro_persistent_cohomology.h
new file mode 100644
index 00000000..433cfd3e
--- /dev/null
+++ b/src/Persistent_cohomology/doc/Intro_persistent_cohomology.h
@@ -0,0 +1,206 @@
+/* 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
+ *
+ * Copyright (C) 2014 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 DOC_PERSISTENT_COHOMOLOGY_INTRO_PERSISTENT_COHOMOLOGY_H_
+#define DOC_PERSISTENT_COHOMOLOGY_INTRO_PERSISTENT_COHOMOLOGY_H_
+
+// needs namespace for Doxygen to link on classes
+namespace Gudhi {
+// needs namespace for Doxygen to link on classes
+namespace persistent_cohomology {
+
+/** \defgroup persistent_cohomology Persistent Cohomology
+
+ \author Clément Maria
+
+ Computation of persistent cohomology using the algorithm of
+ \cite DBLP:journals/dcg/SilvaMV11 and \cite DBLP:journals/corr/abs-1208-5018
+ and the Compressed Annotation Matrix
+ implementation of \cite DBLP:conf/esa/BoissonnatDM13
+
+ The theory of homology consists in attaching to a topological space a sequence of
+ (homology) groups,
+ capturing global topological features
+ like connected components, holes, cavities, etc. Persistent homology studies the evolution
+ -- birth, life and death -- of
+ these features when the topological space is changing. Consequently, the theory is essentially
+ composed of three elements:
+ topological spaces, their homology groups and an evolution scheme.
+
+ \section persistencetopolocalspaces Topological Spaces
+ Topological spaces are represented by simplicial complexes.
+ Let \f$V = \{1, \cdots ,|V|\}\f$ be a set of <EM>vertices</EM>.
+ A <EM>simplex</EM> \f$\sigma\f$ is a subset of vertices
+ \f$\sigma \subseteq V\f$. A <EM>simplicial complex</EM> \f$\mathbf{K}\f$
+ on \f$V\f$ is a collection of simplices \f$\{\sigma\}\f$,
+ \f$\sigma \subseteq V\f$, such that \f$\tau \subseteq \sigma \in \mathbf{K}
+ \Rightarrow \tau \in \mathbf{K}\f$. The dimension \f$n=|\sigma|-1\f$ of \f$\sigma\f$
+ is its number of elements minus 1. A <EM>filtration</EM> of a simplicial complex is
+ a function \f$f:\mathbf{K} \rightarrow \mathbb{R}\f$ satisfying \f$f(\tau)\leq
+ f(\sigma)\f$ whenever \f$\tau \subseteq \sigma\f$.
+
+ We define the concept FilteredComplex which enumerates the requirements for a class
+ to represent a filtered complex from which persistent homology may be computed.
+ We use the vocabulary of simplicial complexes, but the concept
+ is valid for any type of cell complex. The main requirements
+ are the definition of:
+ \li type <CODE>Indexing_tag</CODE>, which is a model of the concept
+ <CODE>IndexingTag</CODE>,
+ describing the nature of the indexing scheme,
+ \li type Simplex_handle to manipulate simplices,
+ \li method <CODE>int dimension(Simplex_handle)</CODE> returning
+ the dimension of a simplex,
+ \li type and method <CODE>Boundary_simplex_range
+ boundary_simplex_range(Simplex_handle)</CODE> that returns
+ a range giving access to the codimension 1 subsimplices of the
+ input simplex, as-well-as the coefficients \f$(-1)^i\f$ in the
+ definition of the operator \f$\partial\f$. The iterators have
+ value type <CODE>Simplex_handle</CODE>,
+ \li type and method
+ <CODE>Filtration_simplex_range filtration_simplex_range ()</CODE>
+ that returns a range giving
+ access to all the simplices of the complex read in the order
+ assigned by the indexing scheme,
+ \li type and method
+ <CODE>Filtration_value filtration (Simplex_handle)</CODE> that returns the value of
+ the filtration on the simplex represented by the handle.
+
+ \section persistencehomology Homology
+ For a ring \f$\mathcal{R}\f$, the group of <EM>n-chains</EM>,
+ denoted \f$\mathbf{C}_n(\mathbf{K},\mathcal{R})\f$, of \f$\mathbf{K}\f$ is the
+ group of formal sums of
+ n-simplices with \f$\mathcal{R}\f$ coefficients. The <EM>boundary operator</EM> is a
+ linear operator
+ \f$\partial_n: \mathbf{C}_n(\mathbf{K},\mathcal{R}) \rightarrow \mathbf{C}_{n-1}(\mathbf{K},\mathcal{R})\f$
+ such that \f$\partial_n \sigma = \partial_n [v_0, \cdots , v_n] =
+ \sum_{i=0}^n (-1)^{i}[v_0,\cdots ,\widehat{v_i}, \cdots,v_n]\f$,
+ where \f$\widehat{v_i}\f$ means \f$v_i\f$ is omitted from the list. The chain
+ groups form a sequence:
+
+ \f[\cdots \ \ \mathbf{C}_n(\mathbf{K},\mathcal{R}) \xrightarrow{\ \partial_n\ } \mathbf{C}_{n-1}(\mathbf{K},\mathcal{R})
+ \xrightarrow{\partial_{n-1}} \cdots \xrightarrow{\ \partial_2 \ }
+ \mathbf{C}_1(\mathbf{K},\mathcal{R}) \xrightarrow{\ \partial_1 \ } \mathbf{C}_0(\mathbf{K},\mathcal{R}) \f]
+
+ of finitely many groups \f$\mathbf{C}_n(\mathbf{K},\mathcal{R})\f$ and homomorphisms
+ \f$\partial_n\f$, indexed by the dimension \f$n \geq 0\f$.
+ The boundary operators satisfy the property \f$\partial_n \circ \partial_{n+1}=0\f$
+ for every \f$n > 0\f$
+ and we define the homology groups:
+
+ \f[\mathbf{H}_n(\mathbf{K},\mathcal{R}) = \ker \partial_n / \mathrm{im} \ \partial_{n+1}\f]
+
+ We refer to \cite Munkres-elementsalgtop1984 for an introduction to homology
+ theory and to \cite DBLP:books/daglib/0025666 for an introduction to persistent homology.
+
+ \section persistenceindexingscheme Indexing Scheme
+ "Changing" a simplicial complex consists in applying a simplicial map.
+ An <EM>indexing scheme</EM> is a directed graph together with a traversal
+ order, such that two
+ consecutive nodes in the graph are connected by an arrow (either forward or backward).
+ The nodes represent simplicial complexes and the directed edges simplicial maps.
+
+ From the computational point of view, there are two types of indexing schemes of
+ interest
+ in persistent homology: <EM>linear</EM> ones
+ \f$\bullet \longrightarrow \bullet \longrightarrow \cdots \longrightarrow \bullet
+ \longrightarrow \bullet\f$
+ in persistent homology \cite DBLP:journals/dcg/ZomorodianC05 ,
+ and <EM>zigzag</EM> ones
+ \f$\bullet \longrightarrow \bullet \longleftarrow \cdots
+ \longrightarrow \bullet
+ \longleftarrow \bullet \f$ in zigzag persistent
+ homology \cite DBLP:journals/focm/CarlssonS10.
+ These indexing schemes have a natural left-to-right traversal order, and we
+ describe them with ranges and iterators.
+ In the current release of the Gudhi library, only the linear case is implemented.
+
+ In the following, we consider the case where the indexing scheme is induced
+ by a filtration.
+ Ordering the simplices
+ by increasing filtration values (breaking ties so as a simplex appears after
+ its subsimplices of same filtration value) provides an indexing scheme.
+
+\section pcohexamples Examples
+
+We provide several example files: run these examples with -h for details on their use, and read the README file.
+
+\li <a href="_persistent_cohomology_2rips_persistence_8cpp-example.html">
+Persistent_cohomology/rips_persistence.cpp</a> computes the Rips complex of a point cloud and its persistence diagram.
+
+\li <a href="_persistent_cohomology_2rips_multifield_persistence_8cpp-example.html">
+Persistent_cohomology/rips_multifield_persistence.cpp</a> computes the Rips complex of a point cloud and its
+persistence diagram with a family of field coefficients.
+
+\li <a href="_persistent_cohomology_2performance_rips_persistence_8cpp-example.html">
+Persistent_cohomology/performance_rips_persistence.cpp</a> provides timings for the construction of the Rips complex
+on a set of points sampling a Klein bottle in \f$\mathbb{R}^5\f$ with a simplex tree, its conversion to a
+Hasse diagram and the computation of persistent homology and multi-field persistent homology for the
+different representations.
+
+\li <a href="_persistent_cohomology_2alpha_complex_3d_persistence_8cpp-example.html">
+Persistent_cohomology/alpha_complex_3d_persistence.cpp</a> computes the persistent homology with
+\f$\mathbb{Z}/2\mathbb{Z}\f$ coefficients of the alpha complex on points sampling from an OFF file.
+\code $> ./alpha_complex_3d_persistence ../../data/points/tore3D_300.off 2 0.45 \endcode
+\code Simplex_tree dim: 3
+2 0 0 inf
+2 1 0.0682162 1.0001
+2 1 0.0934117 1.00003
+2 2 0.56444 1.03938 \endcode
+
+\li <a href="_persistent_cohomology_2alpha_complex_persistence_8cpp-example.html">
+Persistent_cohomology/alpha_complex_persistence.cpp</a> computes the persistent homology with
+\f$\mathbb{Z}/p\mathbb{Z}\f$ coefficients of the alpha complex on points sampling from an OFF file.
+\code $> ./alpha_complex_persistence -r 32 -p 2 -m 0.45 ../../data/points/tore3D_300.off \endcode
+\code Alpha complex is of dimension 3 - 9273 simplices - 300 vertices.
+Simplex_tree dim: 3
+2 0 0 inf
+2 1 0.0682162 1.0001
+2 1 0.0934117 1.00003
+2 2 0.56444 1.03938 \endcode
+
+\li <a href="_persistent_cohomology_2periodic_alpha_complex_3d_persistence_8cpp-example.html">
+Persistent_cohomology/periodic_alpha_complex_3d_persistence.cpp</a> computes the persistent homology with
+\f$\mathbb{Z}/2\mathbb{Z}\f$ coefficients of the periodic alpha complex on points sampling from an OFF file.
+\code $> ./periodic_alpha_complex_3d_persistence ../../data/points/grid_10_10_10_in_0_1.off 3 1.0 \endcode
+\code Periodic Delaunay computed.
+Simplex_tree dim: 3
+3 0 0 inf
+3 1 0.0025 inf
+3 1 0.0025 inf
+3 1 0.0025 inf
+3 2 0.005 inf
+3 2 0.005 inf
+3 2 0.005 inf
+3 3 0.0075 inf \endcode
+
+\li <a href="_persistent_cohomology_2plain_homology_8cpp-example.html">
+Persistent_cohomology/plain_homology.cpp</a> computes the plain homology of a simple simplicial complex without
+filtration values.
+
+ \copyright GNU General Public License v3.
+ */
+
+} // namespace persistent_cohomology
+
+} // namespace Gudhi
+
+#endif // DOC_PERSISTENT_COHOMOLOGY_INTRO_PERSISTENT_COHOMOLOGY_H_
diff --git a/src/Persistent_cohomology/example/CMakeLists.txt b/src/Persistent_cohomology/example/CMakeLists.txt
index ea69352e..758bd6b1 100644
--- a/src/Persistent_cohomology/example/CMakeLists.txt
+++ b/src/Persistent_cohomology/example/CMakeLists.txt
@@ -1,44 +1,84 @@
cmake_minimum_required(VERSION 2.6)
-project(GUDHIExPersCohom)
+project(Persistent_cohomology_examples)
# problem with Visual Studio link on Boost program_options
add_definitions( -DBOOST_ALL_NO_LIB )
add_definitions( -DBOOST_ALL_DYN_LINK )
+add_executable(plain_homology plain_homology.cpp)
+target_link_libraries(plain_homology ${Boost_SYSTEM_LIBRARY})
+
add_executable(persistence_from_simple_simplex_tree persistence_from_simple_simplex_tree.cpp)
target_link_libraries(persistence_from_simple_simplex_tree ${Boost_SYSTEM_LIBRARY})
-add_test(persistence_from_simple_simplex_tree ${CMAKE_CURRENT_BINARY_DIR}/persistence_from_simple_simplex_tree 1 0)
add_executable(rips_persistence rips_persistence.cpp)
target_link_libraries(rips_persistence ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY})
-
-add_test(rips_persistence_3 ${CMAKE_CURRENT_BINARY_DIR}/rips_persistence ${CMAKE_SOURCE_DIR}/data/points/Kl.txt -r 0.25 -d 3 -p 3 -m 100)
-
+
+add_executable(rips_persistence_via_boundary_matrix rips_persistence_via_boundary_matrix.cpp)
+target_link_libraries(rips_persistence_via_boundary_matrix ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY})
+
add_executable(persistence_from_file persistence_from_file.cpp)
target_link_libraries(persistence_from_file ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY})
-add_test(persistence_from_file_3_2_0 ${CMAKE_CURRENT_BINARY_DIR}/persistence_from_file ${CMAKE_SOURCE_DIR}/data/points/bunny_5000.st -p 2 -m 0)
-add_test(persistence_from_file_3_3_100 ${CMAKE_CURRENT_BINARY_DIR}/persistence_from_file ${CMAKE_SOURCE_DIR}/data/points/bunny_5000.st -p 3 -m 100)
-
-if(GMPXX_FOUND AND GMP_FOUND)
- message("GMPXX_LIBRARIES = ${GMPXX_LIBRARIES}")
- message("GMP_LIBRARIES = ${GMP_LIBRARIES}")
-
- add_executable(rips_multifield_persistence rips_multifield_persistence.cpp )
- target_link_libraries(rips_multifield_persistence ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES})
- add_test(rips_multifield_persistence_2_71 ${CMAKE_CURRENT_BINARY_DIR}/rips_multifield_persistence ${CMAKE_SOURCE_DIR}/data/points/Kl.txt -r 0.25 -d 3 -p 2 -q 71 -m 100)
-
- add_executable ( performance_rips_persistence performance_rips_persistence.cpp )
- target_link_libraries(performance_rips_persistence ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES})
-
- if(CGAL_FOUND)
- if (CMAKE_BUILD_TYPE MATCHES Debug)
- # For programs to be more verbose
- add_definitions(-DDEBUG_TRACES)
- endif()
- add_executable(alpha_shapes_persistence alpha_shapes_persistence.cpp)
- target_link_libraries(alpha_shapes_persistence ${Boost_SYSTEM_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES} ${CGAL_LIBRARY})
- add_test(alpha_shapes_persistence_2_0_5 ${CMAKE_CURRENT_BINARY_DIR}/alpha_shapes_persistence ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 2 0.5)
- #add_test(alpha_shapes_persistence_3_3_100 ${CMAKE_CURRENT_BINARY_DIR}/alpha_shapes_persistence ${CMAKE_SOURCE_DIR}/data/points/bunny_5000.st -p 3 -m 100)
- endif()
-
+
+if (TBB_FOUND)
+ target_link_libraries(plain_homology ${TBB_LIBRARIES})
+ target_link_libraries(persistence_from_simple_simplex_tree ${TBB_LIBRARIES})
+ target_link_libraries(rips_persistence ${TBB_LIBRARIES})
+ target_link_libraries(rips_persistence_via_boundary_matrix ${TBB_LIBRARIES})
+ target_link_libraries(persistence_from_file ${TBB_LIBRARIES})
endif()
+
+add_test(plain_homology ${CMAKE_CURRENT_BINARY_DIR}/plain_homology)
+add_test(persistence_from_simple_simplex_tree ${CMAKE_CURRENT_BINARY_DIR}/persistence_from_simple_simplex_tree 1 0)
+add_test(rips_persistence_3 ${CMAKE_CURRENT_BINARY_DIR}/rips_persistence ${CMAKE_SOURCE_DIR}/data/points/Kl.txt -r 0.16 -d 3 -p 3 -m 100)
+add_test(rips_persistence_via_boundary_matrix_3 ${CMAKE_CURRENT_BINARY_DIR}/rips_persistence_via_boundary_matrix ${CMAKE_SOURCE_DIR}/data/points/Kl.txt -r 0.16 -d 3 -p 3 -m 100)
+add_test(persistence_from_file_3_2_0 ${CMAKE_CURRENT_BINARY_DIR}/persistence_from_file ${CMAKE_SOURCE_DIR}/data/filtered_simplicial_complex/bunny_5000_complex.fsc -p 2 -m 0)
+add_test(persistence_from_file_3_3_100 ${CMAKE_CURRENT_BINARY_DIR}/persistence_from_file ${CMAKE_SOURCE_DIR}/data/filtered_simplicial_complex/bunny_5000_complex.fsc -p 3 -m 100)
+
+if(GMP_FOUND)
+ if(GMPXX_FOUND)
+ add_executable(rips_multifield_persistence rips_multifield_persistence.cpp )
+ target_link_libraries(rips_multifield_persistence ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES})
+ add_executable ( performance_rips_persistence performance_rips_persistence.cpp )
+ target_link_libraries(performance_rips_persistence ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES})
+ if (TBB_FOUND)
+ target_link_libraries(rips_multifield_persistence ${TBB_LIBRARIES})
+ target_link_libraries(performance_rips_persistence ${TBB_LIBRARIES})
+ endif(TBB_FOUND)
+
+ add_test(rips_multifield_persistence_2_71 ${CMAKE_CURRENT_BINARY_DIR}/rips_multifield_persistence ${CMAKE_SOURCE_DIR}/data/points/Kl.txt -r 0.2 -d 3 -p 2 -q 71 -m 100)
+ endif(GMPXX_FOUND)
+endif(GMP_FOUND)
+
+if(CGAL_FOUND)
+ add_executable(alpha_complex_3d_persistence alpha_complex_3d_persistence.cpp)
+ target_link_libraries(alpha_complex_3d_persistence ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY})
+
+ if (TBB_FOUND)
+ target_link_libraries(alpha_complex_3d_persistence ${TBB_LIBRARIES})
+ endif(TBB_FOUND)
+ add_test(alpha_complex_3d_persistence_2_0_5 ${CMAKE_CURRENT_BINARY_DIR}/alpha_complex_3d_persistence ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off 2 0.45)
+
+
+ if (NOT CGAL_VERSION VERSION_LESS 4.7.0)
+ if (EIGEN3_FOUND)
+ add_executable (alpha_complex_persistence alpha_complex_persistence.cpp)
+ target_link_libraries(alpha_complex_persistence ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY})
+
+ add_executable(periodic_alpha_complex_3d_persistence periodic_alpha_complex_3d_persistence.cpp)
+ target_link_libraries(periodic_alpha_complex_3d_persistence ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY})
+
+ add_executable(custom_persistence_sort custom_persistence_sort.cpp)
+ target_link_libraries(custom_persistence_sort ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY})
+
+ if (TBB_FOUND)
+ target_link_libraries(alpha_complex_persistence ${TBB_LIBRARIES})
+ target_link_libraries(periodic_alpha_complex_3d_persistence ${TBB_LIBRARIES})
+ target_link_libraries(custom_persistence_sort ${TBB_LIBRARIES})
+ endif(TBB_FOUND)
+ add_test(alpha_complex_persistence_2_0_45 ${CMAKE_CURRENT_BINARY_DIR}/alpha_complex_persistence ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -m 0.45 -p 2)
+ add_test(periodic_alpha_complex_3d_persistence_2_0 ${CMAKE_CURRENT_BINARY_DIR}/periodic_alpha_complex_3d_persistence ${CMAKE_SOURCE_DIR}/data/points/grid_10_10_10_in_0_1.off ${CMAKE_SOURCE_DIR}/data/points/iso_cuboid_3_in_0_1.txt 2 0)
+ add_test(custom_persistence_sort ${CMAKE_CURRENT_BINARY_DIR}/custom_persistence_sort)
+ endif(EIGEN3_FOUND)
+ endif (NOT CGAL_VERSION VERSION_LESS 4.7.0)
+endif(CGAL_FOUND)
diff --git a/src/Persistent_cohomology/example/README b/src/Persistent_cohomology/example/README
index 8c71ccf5..7803e5ab 100644
--- a/src/Persistent_cohomology/example/README
+++ b/src/Persistent_cohomology/example/README
@@ -4,13 +4,13 @@ cd /path-to-example/
cmake .
make
-
-Example of use :
+***********************************************************************************************************************
+Example of use of RIPS:
Computation of the persistent homology with Z/2Z coefficients of the Rips complex on points
sampling a Klein bottle:
-./rips_persistence ../../../data/points/Kl.txt -r 0.25 -d 3 -p 2 -m 100
+./rips_persistence ../../data/points/Kl.txt -r 0.25 -d 3 -p 2 -m 100
output:
210 0 0 inf
@@ -29,7 +29,7 @@ where
with Z/3Z coefficients:
-./rips_persistence ../../../data/points/Kl.txt -r 0.25 -d 3 -p 3 -m 100
+./rips_persistence ../../data/points/Kl.txt -r 0.25 -d 3 -p 3 -m 100
output:
3 0 0 inf
@@ -37,7 +37,7 @@ output:
and the computation with Z/2Z and Z/3Z coefficients simultaneously:
-./rips_multifield_persistence ../../../data/points/Kl.txt -r 0.25 -d 3 -p 2 -q 3 -m 100
+./rips_multifield_persistence ../../data/points/Kl.txt -r 0.25 -d 3 -p 2 -q 3 -m 100
output:
6 0 0 inf
@@ -47,10 +47,106 @@ output:
and finally the computation with all Z/pZ for 2 <= p <= 71 (20 first prime numbers):
- ./rips_multifield_persistence ../../../data/points/Kl.txt -r 0.25 -d 3 -p 2 -q 71 -m 100
+ ./rips_multifield_persistence ../../data/points/Kl.txt -r 0.25 -d 3 -p 2 -q 71 -m 100
output:
557940830126698960967415390 0 0 inf
557940830126698960967415390 1 0.0702103 inf
2 1 0.0702103 inf
2 2 0.159992 inf
+
+***********************************************************************************************************************
+Example of use of ALPHA:
+
+For a more verbose mode, please run cmake with option "DEBUG_TRACES=TRUE" and recompile the programs.
+
+1) 3D special case
+------------------
+Computation of the persistent homology with Z/2Z coefficients of the alpha complex on points
+sampling a torus 3D:
+
+./alpha_complex_3d_persistence ../../data/points/tore3D_300.off 2 0.45
+
+output:
+Simplex_tree dim: 3
+2 0 0 inf
+2 1 0.0682162 1.0001
+2 1 0.0934117 1.00003
+2 2 0.56444 1.03938
+
+Here we retrieve expected Betti numbers on a tore 3D:
+Betti numbers[0] = 1
+Betti numbers[1] = 2
+Betti numbers[2] = 1
+
+N.B.: - alpha_complex_3d_persistence accepts only OFF files in 3D dimension.
+ - filtration values are alpha square values
+
+2) d-Dimension case
+-------------------
+Computation of the persistent homology with Z/2Z coefficients of the alpha complex on points
+sampling a torus 3D:
+
+./alpha_complex_persistence -r 32 -p 2 -m 0.45 ../../data/points/tore3D_300.off
+
+output:
+Alpha complex is of dimension 3 - 9273 simplices - 300 vertices.
+Simplex_tree dim: 3
+2 0 0 inf
+2 1 0.0682162 1.0001
+2 1 0.0934117 1.00003
+2 2 0.56444 1.03938
+
+Here we retrieve expected Betti numbers on a tore 3D:
+Betti numbers[0] = 1
+Betti numbers[1] = 2
+Betti numbers[2] = 1
+
+N.B.: - alpha_complex_persistence accepts OFF files in d-Dimension.
+ - filtration values are alpha square values
+
+3) 3D periodic special case
+---------------------------
+./periodic_alpha_complex_3d_persistence ../../data/points/grid_10_10_10_in_0_1.off 3 1.0
+
+output:
+Periodic Delaunay computed.
+Simplex_tree dim: 3
+3 0 0 inf
+3 1 0.0025 inf
+3 1 0.0025 inf
+3 1 0.0025 inf
+3 2 0.005 inf
+3 2 0.005 inf
+3 2 0.005 inf
+3 3 0.0075 inf
+
+Here we retrieve expected Betti numbers on a tore 3D:
+Betti numbers[0] = 1
+Betti numbers[1] = 3
+Betti numbers[2] = 3
+Betti numbers[3] = 1
+
+N.B.: - periodic_alpha_complex_3d_persistence accepts only OFF files in 3D dimension. In this example, the periodic cube
+is hard coded to { x = [0,1]; y = [0,1]; z = [0,1] }
+ - filtration values are alpha square values
+
+***********************************************************************************************************************
+Example of use of PLAIN HOMOLOGY:
+
+This example computes the plain homology of the following simplicial complex without filtration values:
+ /* Complex to build. */
+ /* 1 3 */
+ /* o---o */
+ /* /X\ / */
+ /* o---o o */
+ /* 2 0 4 */
+
+./plain_homology
+
+output:
+2 0 0 inf
+2 0 0 inf
+2 1 0 inf
+
+Here we retrieve the 2 entities {0,1,2,3} and {4} (Betti numbers[0] = 2) and the hole in {0,1,3} (Betti numbers[1] = 1)
diff --git a/src/Persistent_cohomology/example/alpha_shapes_persistence.cpp b/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp
index 6d5eebcf..48fbb91a 100644
--- a/src/Persistent_cohomology/example/alpha_shapes_persistence.cpp
+++ b/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp
@@ -20,9 +20,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <gudhi/graph_simplicial_complex.h>
#include <gudhi/Simplex_tree.h>
#include <gudhi/Persistent_cohomology.h>
+#include <gudhi/Points_3D_off_io.h>
#include <boost/variant.hpp>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
@@ -39,9 +39,6 @@
#include <list>
#include <vector>
-using namespace Gudhi;
-using namespace Gudhi::persistent_cohomology;
-
// Alpha_shape_3 templates type definitions
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef CGAL::Alpha_shape_vertex_base_3<Kernel> Vb;
@@ -66,10 +63,12 @@ typedef Alpha_shape_3::Edge Edge_3;
typedef std::list<Alpha_shape_3::Vertex_handle> Vertex_list;
// gudhi type definition
-typedef Simplex_tree<>::Vertex_handle Simplex_tree_vertex;
+typedef Gudhi::Simplex_tree<Gudhi::Simplex_tree_options_fast_persistence> ST;
+typedef ST::Vertex_handle Simplex_tree_vertex;
typedef std::map<Alpha_shape_3::Vertex_handle, Simplex_tree_vertex > Alpha_shape_simplex_tree_map;
typedef std::pair<Alpha_shape_3::Vertex_handle, Simplex_tree_vertex> Alpha_shape_simplex_tree_pair;
typedef std::vector< Simplex_tree_vertex > Simplex_tree_vector_vertex;
+typedef Gudhi::persistent_cohomology::Persistent_cohomology< ST, Gudhi::persistent_cohomology::Field_Zp > PCOH;
Vertex_list from(const Cell_handle& ch) {
Vertex_list the_list;
@@ -124,40 +123,33 @@ void usage(char * const progName) {
}
int main(int argc, char * const argv[]) {
- int coeff_field_characteristic = 0;
- int returnedScanValue = sscanf(argv[2], "%d", &coeff_field_characteristic);
- if ((returnedScanValue == EOF) || (coeff_field_characteristic <= 0)) {
- std::cerr << "Error: " << argv[2] << " is not correct\n";
+ // program args management
+ if (argc != 4) {
+ std::cerr << "Error: Number of arguments (" << argc << ") is not correct\n";
usage(argv[0]);
}
+ int coeff_field_characteristic = atoi(argv[2]);
+
Filtration_value min_persistence = 0.0;
- returnedScanValue = sscanf(argv[3], "%lf", &min_persistence);
+ int returnedScanValue = sscanf(argv[3], "%lf", &min_persistence);
if ((returnedScanValue == EOF) || (min_persistence < -1.0)) {
std::cerr << "Error: " << argv[3] << " is not correct\n";
usage(argv[0]);
}
- // program args management
- if (argc != 4) {
- std::cerr << "Error: Number of arguments (" << argc << ") is not correct\n";
+ // Read points from file
+ std::string offInputFile(argv[1]);
+ // Read the OFF file (input file name given as parameter) and triangulate points
+ Gudhi::Points_3D_off_reader<Point_3> off_reader(offInputFile);
+ // Check the read operation was correct
+ if (!off_reader.is_valid()) {
+ std::cerr << "Unable to read file " << offInputFile << std::endl;
usage(argv[0]);
}
- // Read points from file
- std::string filegraph = argv[1];
- std::list<Point_3> lp;
- std::ifstream is(filegraph.c_str());
- int n;
- is >> n;
-#ifdef DEBUG_TRACES
- std::cout << "Reading " << n << " points " << std::endl;
-#endif // DEBUG_TRACES
- Point_3 p;
- for (; n > 0; n--) {
- is >> p;
- lp.push_back(p);
- }
+ // Retrieve the triangulation
+ std::vector<Point_3> lp = off_reader.get_point_cloud();
// alpha shape construction from points. CGAL has a strange behavior in REGULARIZED mode.
Alpha_shape_3 as(lp.begin(), lp.end(), 0, Alpha_shape_3::GENERAL);
@@ -184,7 +176,7 @@ int main(int argc, char * const argv[]) {
// Loop on objects vector
Vertex_list vertex_list;
- Simplex_tree<> simplex_tree;
+ ST simplex_tree;
Alpha_shape_simplex_tree_map map_cgal_simplex_tree;
std::vector<Alpha_value_type>::iterator the_alpha_value_iterator = the_alpha_values.begin();
int dim_max = 0;
@@ -239,7 +231,7 @@ int main(int argc, char * const argv[]) {
}
}
// Construction of the simplex_tree
- Filtration_value filtr = std::sqrt(*the_alpha_value_iterator);
+ Filtration_value filtr = /*std::sqrt*/(*the_alpha_value_iterator);
#ifdef DEBUG_TRACES
std::cout << "filtration = " << filtr << std::endl;
#endif // DEBUG_TRACES
@@ -281,7 +273,7 @@ int main(int argc, char * const argv[]) {
std::cout << "Simplex_tree dim: " << simplex_tree.dimension() << std::endl;
// Compute the persistence diagram of the complex
- Persistent_cohomology< Simplex_tree<>, Field_Zp > pcoh(simplex_tree);
+ PCOH pcoh(simplex_tree);
// initializes the coefficient field for homology
pcoh.init_coefficients(coeff_field_characteristic);
diff --git a/src/Persistent_cohomology/example/alpha_complex_persistence.cpp b/src/Persistent_cohomology/example/alpha_complex_persistence.cpp
new file mode 100644
index 00000000..2412569a
--- /dev/null
+++ b/src/Persistent_cohomology/example/alpha_complex_persistence.cpp
@@ -0,0 +1,122 @@
+#include <boost/program_options.hpp>
+
+#include <CGAL/Epick_d.h>
+
+#include <gudhi/Alpha_complex.h>
+#include <gudhi/Persistent_cohomology.h>
+// to construct a simplex_tree from alpha complex
+#include <gudhi/Simplex_tree.h>
+
+#include <iostream>
+#include <string>
+#include <limits> // for numeric_limits
+
+void program_options(int argc, char * argv[]
+ , std::string & off_file_points
+ , std::string & output_file_diag
+ , Filtration_value & alpha_square_max_value
+ , int & coeff_field_characteristic
+ , Filtration_value & min_persistence);
+
+int main(int argc, char **argv) {
+ std::string off_file_points;
+ std::string output_file_diag;
+ Filtration_value alpha_square_max_value;
+ int coeff_field_characteristic;
+ Filtration_value min_persistence;
+
+ program_options(argc, argv, off_file_points, output_file_diag, alpha_square_max_value,
+ coeff_field_characteristic, min_persistence);
+
+ // ----------------------------------------------------------------------------
+ // Init of an alpha complex from an OFF file
+ // ----------------------------------------------------------------------------
+ using Kernel = CGAL::Epick_d< CGAL::Dynamic_dimension_tag >;
+ Gudhi::alpha_complex::Alpha_complex<Kernel> alpha_complex_from_file(off_file_points);
+
+ Gudhi::Simplex_tree<> simplex;
+ if (alpha_complex_from_file.create_complex(simplex, alpha_square_max_value)) {
+ // ----------------------------------------------------------------------------
+ // Display information about the alpha complex
+ // ----------------------------------------------------------------------------
+ std::cout << "Simplicial complex is of dimension " << simplex.dimension() <<
+ " - " << simplex.num_simplices() << " simplices - " <<
+ simplex.num_vertices() << " vertices." << std::endl;
+
+ // Sort the simplices in the order of the filtration
+ simplex.initialize_filtration();
+
+ std::cout << "Simplex_tree dim: " << simplex.dimension() << std::endl;
+ // Compute the persistence diagram of the complex
+ Gudhi::persistent_cohomology::Persistent_cohomology< Gudhi::Simplex_tree<>,
+ Gudhi::persistent_cohomology::Field_Zp > pcoh(simplex);
+ // initializes the coefficient field for homology
+ pcoh.init_coefficients(coeff_field_characteristic);
+
+ pcoh.compute_persistent_cohomology(min_persistence);
+
+ // Output the diagram in filediag
+ if (output_file_diag.empty()) {
+ pcoh.output_diagram();
+ } else {
+ std::cout << "Result in file: " << output_file_diag << std::endl;
+ std::ofstream out(output_file_diag);
+ pcoh.output_diagram(out);
+ out.close();
+ }
+ }
+
+ return 0;
+}
+
+void program_options(int argc, char * argv[]
+ , std::string & off_file_points
+ , std::string & output_file_diag
+ , Filtration_value & alpha_square_max_value
+ , int & coeff_field_characteristic
+ , Filtration_value & min_persistence) {
+ namespace po = boost::program_options;
+ po::options_description hidden("Hidden options");
+ hidden.add_options()
+ ("input-file", po::value<std::string>(&off_file_points),
+ "Name of file containing a point set. Format is one point per line: X1 ... Xd ");
+
+ po::options_description visible("Allowed options", 100);
+ visible.add_options()
+ ("help,h", "produce help message")
+ ("output-file,o", po::value<std::string>(&output_file_diag)->default_value(std::string()),
+ "Name of file in which the persistence diagram is written. Default print in std::cout")
+ ("max-alpha-square-value,r",
+ po::value<Filtration_value>(&alpha_square_max_value)->default_value(std::numeric_limits<Filtration_value>::infinity()),
+ "Maximal alpha square value for the Alpha complex construction.")
+ ("field-charac,p", po::value<int>(&coeff_field_characteristic)->default_value(11),
+ "Characteristic p of the coefficient field Z/pZ for computing homology.")
+ ("min-persistence,m", po::value<Filtration_value>(&min_persistence),
+ "Minimal lifetime of homology feature to be recorded. Default is 0. Enter a negative value to see zero length intervals");
+
+ po::positional_options_description pos;
+ pos.add("input-file", 1);
+
+ po::options_description all;
+ all.add(visible).add(hidden);
+
+ po::variables_map vm;
+ po::store(po::command_line_parser(argc, argv).
+ options(all).positional(pos).run(), vm);
+ po::notify(vm);
+
+ if (vm.count("help") || !vm.count("input-file")) {
+ std::cout << std::endl;
+ std::cout << "Compute the persistent homology with coefficient field Z/pZ \n";
+ std::cout << "of an Alpha complex defined on a set of input points.\n \n";
+ std::cout << "The output diagram contains one bar per line, written with the convention: \n";
+ std::cout << " p dim b d \n";
+ std::cout << "where dim is the dimension of the homological feature,\n";
+ std::cout << "b and d are respectively the birth and death of the feature and \n";
+ std::cout << "p is the characteristic of the field Z/pZ used for homology coefficients." << std::endl << std::endl;
+
+ std::cout << "Usage: " << argv[0] << " [options] input-file" << std::endl << std::endl;
+ std::cout << visible << std::endl;
+ std::abort();
+ }
+}
diff --git a/src/Persistent_cohomology/example/custom_persistence_sort.cpp b/src/Persistent_cohomology/example/custom_persistence_sort.cpp
new file mode 100644
index 00000000..64f2a4dc
--- /dev/null
+++ b/src/Persistent_cohomology/example/custom_persistence_sort.cpp
@@ -0,0 +1,137 @@
+/* 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) 2014 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/>.
+ */
+
+#include <CGAL/Epick_d.h>
+#include <CGAL/point_generators_d.h>
+#include <CGAL/algorithm.h>
+#include <CGAL/assertions.h>
+
+#include <gudhi/Alpha_complex.h>
+#include <gudhi/Persistent_cohomology.h>
+// to construct a simplex_tree from alpha complex
+#include <gudhi/Simplex_tree.h>
+
+#include <iostream>
+#include <iterator>
+#include <vector>
+#include <fstream> // for std::ofstream
+#include <algorithm> // for std::sort
+
+
+using Kernel = CGAL::Epick_d< CGAL::Dimension_tag<3> >;
+using Point = Kernel::Point_d;
+using Alpha_complex = Gudhi::alpha_complex::Alpha_complex<Kernel>;
+using Simplex_tree = Gudhi::Simplex_tree<>;
+using Persistent_cohomology = Gudhi::persistent_cohomology::Persistent_cohomology< Simplex_tree,
+ Gudhi::persistent_cohomology::Field_Zp >;
+
+std::vector<Point> random_points() {
+ // Instanciate a random point generator
+ CGAL::Random rng(0);
+
+ // Generate "points_number" random points in a vector
+ std::vector<Point> points;
+
+ // Generates 1000 random 3D points on a sphere of radius 4.0
+ CGAL::Random_points_on_sphere_d<Point> rand_outside(3, 4.0, rng);
+ CGAL::cpp11::copy_n(rand_outside, 1000, std::back_inserter(points));
+ // Generates 2000 random 3D points in a sphere of radius 3.0
+ CGAL::Random_points_in_ball_d<Point> rand_inside(3, 3.0, rng);
+ CGAL::cpp11::copy_n(rand_inside, 2000, std::back_inserter(points));
+
+ return points;
+}
+
+/*
+ * Compare two intervals by dimension, then by length.
+ */
+struct cmp_intervals_by_dim_then_length {
+ explicit cmp_intervals_by_dim_then_length(Simplex_tree * sc)
+ : sc_(sc) { }
+
+ template<typename Persistent_interval>
+ bool operator()(const Persistent_interval & p1, const Persistent_interval & p2) {
+ if (sc_->dimension(get < 0 > (p1)) == sc_->dimension(get < 0 > (p2)))
+ return (sc_->filtration(get < 1 > (p1)) - sc_->filtration(get < 0 > (p1))
+ > sc_->filtration(get < 1 > (p2)) - sc_->filtration(get < 0 > (p2)));
+ else
+ return (sc_->dimension(get < 0 > (p1)) > sc_->dimension(get < 0 > (p2)));
+ }
+ Simplex_tree* sc_;
+};
+
+int main(int argc, char **argv) {
+ std::vector<Point> points = random_points();
+
+ std::cout << "Points size=" << points.size() << std::endl;
+ // Alpha complex persistence computation from generated points
+ Alpha_complex alpha_complex_from_points(points);
+ std::cout << "alpha_complex_from_points" << std::endl;
+
+ Simplex_tree simplex;
+ std::cout << "simplex" << std::endl;
+ if (alpha_complex_from_points.create_complex(simplex, 0.6)) {
+ std::cout << "simplex" << std::endl;
+ // ----------------------------------------------------------------------------
+ // Display information about the alpha complex
+ // ----------------------------------------------------------------------------
+ std::cout << "Simplicial complex is of dimension " << simplex.dimension() <<
+ " - " << simplex.num_simplices() << " simplices - " <<
+ simplex.num_vertices() << " vertices." << std::endl;
+
+ // Sort the simplices in the order of the filtration
+ simplex.initialize_filtration();
+
+ std::cout << "Simplex_tree dim: " << simplex.dimension() << std::endl;
+
+ Persistent_cohomology pcoh(simplex);
+
+ // initializes the coefficient field for homology - Z/3Z
+ pcoh.init_coefficients(3);
+ pcoh.compute_persistent_cohomology(0.2);
+
+ // Custom sort and output persistence
+ cmp_intervals_by_dim_then_length cmp(&simplex);
+ auto persistent_pairs = pcoh.get_persistent_pairs();
+ std::sort(std::begin(persistent_pairs), std::end(persistent_pairs), cmp);
+ for (auto pair : persistent_pairs) {
+ std::cout << simplex.dimension(get<0>(pair)) << " "
+ << simplex.filtration(get<0>(pair)) << " "
+ << simplex.filtration(get<1>(pair)) << std::endl;
+ }
+
+ // Persistent Betti numbers
+ std::cout << "The persistent Betti numbers in interval [0.40, 0.41] are : ";
+ for (int dim = 0; dim < simplex.dimension(); dim++)
+ std::cout << "b" << dim << " = " << pcoh.persistent_betti_number(dim, 0.40, 0.41) << " ; ";
+ std::cout << std::endl;
+
+ // Betti numbers
+ std::vector<int> betti_numbers = pcoh.betti_numbers();
+ std::cout << "The Betti numbers are : ";
+ for (std::size_t i = 0; i < betti_numbers.size(); i++)
+ std::cout << "b" << i << " = " << betti_numbers[i] << " ; ";
+ std::cout << std::endl;
+ }
+ return 0;
+}
+
diff --git a/src/Persistent_cohomology/example/performance_rips_persistence.cpp b/src/Persistent_cohomology/example/performance_rips_persistence.cpp
index 0e912d57..b4d282ac 100644
--- a/src/Persistent_cohomology/example/performance_rips_persistence.cpp
+++ b/src/Persistent_cohomology/example/performance_rips_persistence.cpp
@@ -63,10 +63,11 @@ void timing_persistence(FilteredComplex & cpx
*/
int main(int argc, char * argv[]) {
std::chrono::time_point<std::chrono::system_clock> start, end;
- int enlapsed_sec;
+ int elapsed_sec;
+ {
- std::string filepoints = "../examples/Kl.txt";
- Filtration_value threshold = 0.3;
+ std::string filepoints = "../../../data/points/Kl.txt";
+ Filtration_value threshold = 0.27;
int dim_max = 3;
int p = 2;
int q = 1223;
@@ -81,11 +82,11 @@ int main(int argc, char * argv[]) {
Graph_t prox_graph = compute_proximity_graph(points, threshold
, euclidean_distance<Point_t>);
end = std::chrono::system_clock::now();
- enlapsed_sec = std::chrono::duration_cast<std::chrono::seconds>(end - start).count();
- std::cout << "Compute Rips graph in " << enlapsed_sec << " sec.\n";
+ elapsed_sec = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
+ std::cout << "Compute Rips graph in " << elapsed_sec << " ms.\n";
// Construct the Rips complex in a Simplex Tree
- Simplex_tree<> st;
+ Simplex_tree<Simplex_tree_options_fast_persistence> st;
start = std::chrono::system_clock::now();
// insert the proximity graph in the simplex tree
@@ -94,8 +95,8 @@ int main(int argc, char * argv[]) {
st.expansion(dim_max);
end = std::chrono::system_clock::now();
- enlapsed_sec = std::chrono::duration_cast<std::chrono::seconds>(end - start).count();
- std::cout << "Compute Rips complex in " << enlapsed_sec << " sec.\n";
+ elapsed_sec = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
+ std::cout << "Compute Rips complex in " << elapsed_sec << " ms.\n";
std::cout << " - dimension = " << st.dimension() << std::endl;
std::cout << " - number of simplices = " << st.num_simplices() << std::endl;
@@ -103,15 +104,26 @@ int main(int argc, char * argv[]) {
start = std::chrono::system_clock::now();
st.initialize_filtration();
end = std::chrono::system_clock::now();
- enlapsed_sec = std::chrono::duration_cast<std::chrono::seconds>(end - start).count();
- std::cout << "Order the simplices of the filtration in " << enlapsed_sec << " sec.\n";
+ elapsed_sec = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
+ std::cout << "Order the simplices of the filtration in " << elapsed_sec << " ms.\n";
+
+ // Copy the keys inside the simplices
+ start = std::chrono::system_clock::now();
+ {
+ int count = 0;
+ for (auto sh : st.filtration_simplex_range())
+ st.assign_key(sh, count++);
+ }
+ end = std::chrono::system_clock::now();
+ elapsed_sec = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
+ std::cout << "Copied the keys inside the simplices in " << elapsed_sec << " ms.\n";
// Convert the simplex tree into a hasse diagram
start = std::chrono::system_clock::now();
Hasse_complex<> hcpx(st);
end = std::chrono::system_clock::now();
- enlapsed_sec = std::chrono::duration_cast<std::chrono::seconds>(end - start).count();
- std::cout << "Convert the simplex tree into a Hasse diagram in " << enlapsed_sec << " sec.\n";
+ elapsed_sec = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
+ std::cout << "Convert the simplex tree into a Hasse diagram in " << elapsed_sec << " ms.\n";
std::cout << "Timings when using a simplex tree: \n";
@@ -124,6 +136,11 @@ int main(int argc, char * argv[]) {
timing_persistence(hcpx, q);
timing_persistence(hcpx, p, q);
+ start = std::chrono::system_clock::now();
+ }
+ end = std::chrono::system_clock::now();
+ elapsed_sec = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
+ std::cout << "Running the complex destructors in " << elapsed_sec << " ms.\n";
return 0;
}
@@ -132,19 +149,32 @@ void
timing_persistence(FilteredComplex & cpx
, int p) {
std::chrono::time_point<std::chrono::system_clock> start, end;
- int enlapsed_sec;
-
+ int elapsed_sec;
+ {
+ start = std::chrono::system_clock::now();
Persistent_cohomology< FilteredComplex, Field_Zp > pcoh(cpx);
+ end = std::chrono::system_clock::now();
+ elapsed_sec = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
+ std::cout << " Initialize pcoh in " << elapsed_sec << " ms.\n";
// initializes the coefficient field for homology
+ start = std::chrono::system_clock::now();
pcoh.init_coefficients(p);
+ end = std::chrono::system_clock::now();
+ elapsed_sec = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
+ std::cout << " Initialize the coefficient field in " << elapsed_sec << " ms.\n";
start = std::chrono::system_clock::now();
pcoh.compute_persistent_cohomology(INFINITY);
end = std::chrono::system_clock::now();
- enlapsed_sec = std::chrono::duration_cast<std::chrono::seconds>(end - start).count();
- std::cout << " Compute persistent homology in Z/" << p << "Z in " << enlapsed_sec << " sec.\n";
+ elapsed_sec = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
+ std::cout << " Compute persistent homology in Z/" << p << "Z in " << elapsed_sec << " ms.\n";
+ start = std::chrono::system_clock::now();
+ }
+ end = std::chrono::system_clock::now();
+ elapsed_sec = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
+ std::cout << " Run the persistence destructors in " << elapsed_sec << " ms.\n";
}
template< typename FilteredComplex>
@@ -153,11 +183,19 @@ timing_persistence(FilteredComplex & cpx
, int p
, int q) {
std::chrono::time_point<std::chrono::system_clock> start, end;
- int enlapsed_sec;
-
+ int elapsed_sec;
+ {
+ start = std::chrono::system_clock::now();
Persistent_cohomology< FilteredComplex, Multi_field > pcoh(cpx);
+ end = std::chrono::system_clock::now();
+ elapsed_sec = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
+ std::cout << " Initialize pcoh in " << elapsed_sec << " ms.\n";
// initializes the coefficient field for homology
+ start = std::chrono::system_clock::now();
pcoh.init_coefficients(p, q);
+ end = std::chrono::system_clock::now();
+ elapsed_sec = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
+ std::cout << " Initialize the coefficient field in " << elapsed_sec << " ms.\n";
// compute persistent homology, disgarding persistent features of life shorter than min_persistence
start = std::chrono::system_clock::now();
@@ -165,7 +203,12 @@ timing_persistence(FilteredComplex & cpx
pcoh.compute_persistent_cohomology(INFINITY);
end = std::chrono::system_clock::now();
- enlapsed_sec = std::chrono::duration_cast<std::chrono::seconds>(end - start).count();
+ elapsed_sec = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
std::cout << " Compute multi-field persistent homology in all coefficient fields Z/pZ "
- << "with p in [" << p << ";" << q << "] in " << enlapsed_sec << " sec.\n";
+ << "with p in [" << p << ";" << q << "] in " << elapsed_sec << " ms.\n";
+ start = std::chrono::system_clock::now();
+ }
+ end = std::chrono::system_clock::now();
+ elapsed_sec = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
+ std::cout << " Run the persistence destructors in " << elapsed_sec << " ms.\n";
}
diff --git a/src/Persistent_cohomology/example/periodic_alpha_complex_3d_persistence.cpp b/src/Persistent_cohomology/example/periodic_alpha_complex_3d_persistence.cpp
new file mode 100644
index 00000000..a199fea1
--- /dev/null
+++ b/src/Persistent_cohomology/example/periodic_alpha_complex_3d_persistence.cpp
@@ -0,0 +1,313 @@
+/* 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) 2014 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/>.
+ */
+
+#include <gudhi/Simplex_tree.h>
+#include <gudhi/Persistent_cohomology.h>
+#include <gudhi/Points_3D_off_io.h>
+#include <boost/variant.hpp>
+
+#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
+#include <CGAL/Periodic_3_Delaunay_triangulation_traits_3.h>
+#include <CGAL/Periodic_3_Delaunay_triangulation_3.h>
+#include <CGAL/Alpha_shape_3.h>
+#include <CGAL/iterator.h>
+
+#include <fstream>
+#include <cmath>
+#include <string>
+#include <tuple>
+#include <map>
+#include <utility>
+#include <list>
+#include <vector>
+
+// Traits
+using K = CGAL::Exact_predicates_inexact_constructions_kernel;
+using PK = CGAL::Periodic_3_Delaunay_triangulation_traits_3<K>;
+// Vertex type
+using DsVb = CGAL::Periodic_3_triangulation_ds_vertex_base_3<>;
+using Vb = CGAL::Triangulation_vertex_base_3<PK, DsVb>;
+using AsVb = CGAL::Alpha_shape_vertex_base_3<PK, Vb>;
+// Cell type
+using DsCb = CGAL::Periodic_3_triangulation_ds_cell_base_3<>;
+using Cb = CGAL::Triangulation_cell_base_3<PK, DsCb>;
+using AsCb = CGAL::Alpha_shape_cell_base_3<PK, Cb>;
+using Tds = CGAL::Triangulation_data_structure_3<AsVb, AsCb>;
+using P3DT3 = CGAL::Periodic_3_Delaunay_triangulation_3<PK, Tds>;
+using Alpha_shape_3 = CGAL::Alpha_shape_3<P3DT3>;
+using Point_3 = PK::Point_3;
+
+// filtration with alpha values needed type definition
+using Alpha_value_type = Alpha_shape_3::FT;
+using Object = CGAL::Object;
+using Dispatch = CGAL::Dispatch_output_iterator<
+ CGAL::cpp11::tuple<Object, Alpha_value_type>,
+ CGAL::cpp11::tuple<std::back_insert_iterator< std::vector<Object> >,
+ std::back_insert_iterator< std::vector<Alpha_value_type> > > >;
+using Cell_handle = Alpha_shape_3::Cell_handle;
+using Facet = Alpha_shape_3::Facet;
+using Edge_3 = Alpha_shape_3::Edge;
+using Vertex_list = std::list<Alpha_shape_3::Vertex_handle>;
+
+// gudhi type definition
+using ST = Gudhi::Simplex_tree<Gudhi::Simplex_tree_options_fast_persistence>;
+using Simplex_tree_vertex = ST::Vertex_handle;
+using Alpha_shape_simplex_tree_map = std::map<Alpha_shape_3::Vertex_handle, Simplex_tree_vertex >;
+using Alpha_shape_simplex_tree_pair = std::pair<Alpha_shape_3::Vertex_handle, Simplex_tree_vertex>;
+using Simplex_tree_vector_vertex = std::vector< Simplex_tree_vertex >;
+using Persistent_cohomology = Gudhi::persistent_cohomology::Persistent_cohomology<
+ ST, Gudhi::persistent_cohomology::Field_Zp >;
+
+Vertex_list from(const Cell_handle& ch) {
+ Vertex_list the_list;
+ for (auto i = 0; i < 4; i++) {
+#ifdef DEBUG_TRACES
+ std::cout << "from cell[" << i << "]=" << ch->vertex(i)->point() << std::endl;
+#endif // DEBUG_TRACES
+ the_list.push_back(ch->vertex(i));
+ }
+ return the_list;
+}
+
+Vertex_list from(const Facet& fct) {
+ Vertex_list the_list;
+ for (auto i = 0; i < 4; i++) {
+ if (fct.second != i) {
+#ifdef DEBUG_TRACES
+ std::cout << "from facet=[" << i << "]" << fct.first->vertex(i)->point() << std::endl;
+#endif // DEBUG_TRACES
+ the_list.push_back(fct.first->vertex(i));
+ }
+ }
+ return the_list;
+}
+
+Vertex_list from(const Edge_3& edg) {
+ Vertex_list the_list;
+ for (auto i = 0; i < 4; i++) {
+ if ((edg.second == i) || (edg.third == i)) {
+#ifdef DEBUG_TRACES
+ std::cout << "from edge[" << i << "]=" << edg.first->vertex(i)->point() << std::endl;
+#endif // DEBUG_TRACES
+ the_list.push_back(edg.first->vertex(i));
+ }
+ }
+ return the_list;
+}
+
+Vertex_list from(const Alpha_shape_3::Vertex_handle& vh) {
+ Vertex_list the_list;
+#ifdef DEBUG_TRACES
+ std::cout << "from vertex=" << vh->point() << std::endl;
+#endif // DEBUG_TRACES
+ the_list.push_back(vh);
+ return the_list;
+}
+
+void usage(char * const progName) {
+ std::cerr << "Usage: " << progName <<
+ " path_to_file_graph path_to_iso_cuboid_3_file coeff_field_characteristic[integer > 0] min_persistence[float >= -1.0]\n";
+ exit(-1);
+}
+
+int main(int argc, char * const argv[]) {
+ // program args management
+ if (argc != 5) {
+ std::cerr << "Error: Number of arguments (" << argc << ") is not correct\n";
+ usage(argv[0]);
+ }
+
+ int coeff_field_characteristic = 0;
+ int returnedScanValue = sscanf(argv[3], "%d", &coeff_field_characteristic);
+ if ((returnedScanValue == EOF) || (coeff_field_characteristic <= 0)) {
+ std::cerr << "Error: " << argv[3] << " is not correct\n";
+ usage(argv[0]);
+ }
+
+ Filtration_value min_persistence = 0.0;
+ returnedScanValue = sscanf(argv[4], "%lf", &min_persistence);
+ if ((returnedScanValue == EOF) || (min_persistence < -1.0)) {
+ std::cerr << "Error: " << argv[4] << " is not correct\n";
+ usage(argv[0]);
+ }
+
+ // Read points from file
+ std::string offInputFile(argv[1]);
+ // Read the OFF file (input file name given as parameter) and triangulate points
+ Gudhi::Points_3D_off_reader<Point_3> off_reader(offInputFile);
+ // Check the read operation was correct
+ if (!off_reader.is_valid()) {
+ std::cerr << "Unable to read file " << offInputFile << std::endl;
+ usage(argv[0]);
+ }
+
+ // Read iso_cuboid_3 information from file
+ std::ifstream iso_cuboid_str(argv[2]);
+ double x_min, y_min, z_min, x_max, y_max, z_max;
+ if (iso_cuboid_str.good()) {
+ iso_cuboid_str >> x_min >> y_min >> z_min >> x_max >> y_max >> z_max;
+ } else {
+ std::cerr << "Unable to read file " << argv[2] << std::endl;
+ usage(argv[0]);
+ }
+
+ // Retrieve the triangulation
+ std::vector<Point_3> lp = off_reader.get_point_cloud();
+
+ // Define the periodic cube
+ P3DT3 pdt(PK::Iso_cuboid_3(x_min, y_min, z_min, x_max, y_max, z_max));
+ // Heuristic for inserting large point sets (if pts is reasonably large)
+ pdt.insert(lp.begin(), lp.end(), true);
+ // As pdt won't be modified anymore switch to 1-sheeted cover if possible
+ if (pdt.is_triangulation_in_1_sheet()) pdt.convert_to_1_sheeted_covering();
+ std::cout << "Periodic Delaunay computed." << std::endl;
+
+ // alpha shape construction from points. CGAL has a strange behavior in REGULARIZED mode. This is the default mode
+ // Maybe need to set it to GENERAL mode
+ Alpha_shape_3 as(pdt, 0, Alpha_shape_3::GENERAL);
+
+ // filtration with alpha values from alpha shape
+ std::vector<Object> the_objects;
+ std::vector<Alpha_value_type> the_alpha_values;
+
+ Dispatch disp = CGAL::dispatch_output<Object, Alpha_value_type>(std::back_inserter(the_objects),
+ std::back_inserter(the_alpha_values));
+
+ as.filtration_with_alpha_values(disp);
+#ifdef DEBUG_TRACES
+ std::cout << "filtration_with_alpha_values returns : " << the_objects.size() << " objects" << std::endl;
+#endif // DEBUG_TRACES
+
+ Alpha_shape_3::size_type count_vertices = 0;
+ Alpha_shape_3::size_type count_edges = 0;
+ Alpha_shape_3::size_type count_facets = 0;
+ Alpha_shape_3::size_type count_cells = 0;
+
+ // Loop on objects vector
+ Vertex_list vertex_list;
+ ST simplex_tree;
+ Alpha_shape_simplex_tree_map map_cgal_simplex_tree;
+ std::vector<Alpha_value_type>::iterator the_alpha_value_iterator = the_alpha_values.begin();
+ int dim_max = 0;
+ Filtration_value filtration_max = 0.0;
+ for (auto object_iterator : the_objects) {
+ // Retrieve Alpha shape vertex list from object
+ if (const Cell_handle * cell = CGAL::object_cast<Cell_handle>(&object_iterator)) {
+ vertex_list = from(*cell);
+ count_cells++;
+ if (dim_max < 3) {
+ // Cell is of dim 3
+ dim_max = 3;
+ }
+ } else if (const Facet * facet = CGAL::object_cast<Facet>(&object_iterator)) {
+ vertex_list = from(*facet);
+ count_facets++;
+ if (dim_max < 2) {
+ // Facet is of dim 2
+ dim_max = 2;
+ }
+ } else if (const Edge_3 * edge = CGAL::object_cast<Edge_3>(&object_iterator)) {
+ vertex_list = from(*edge);
+ count_edges++;
+ if (dim_max < 1) {
+ // Edge_3 is of dim 1
+ dim_max = 1;
+ }
+ } else if (const Alpha_shape_3::Vertex_handle * vertex =
+ CGAL::object_cast<Alpha_shape_3::Vertex_handle>(&object_iterator)) {
+ count_vertices++;
+ vertex_list = from(*vertex);
+ }
+ // Construction of the vector of simplex_tree vertex from list of alpha_shapes vertex
+ Simplex_tree_vector_vertex the_simplex_tree;
+ for (auto the_alpha_shape_vertex : vertex_list) {
+ Alpha_shape_simplex_tree_map::iterator the_map_iterator = map_cgal_simplex_tree.find(the_alpha_shape_vertex);
+ if (the_map_iterator == map_cgal_simplex_tree.end()) {
+ // alpha shape not found
+ Simplex_tree_vertex vertex = map_cgal_simplex_tree.size();
+#ifdef DEBUG_TRACES
+ std::cout << "vertex [" << the_alpha_shape_vertex->point() << "] not found - insert " << vertex << std::endl;
+#endif // DEBUG_TRACES
+ the_simplex_tree.push_back(vertex);
+ map_cgal_simplex_tree.insert(Alpha_shape_simplex_tree_pair(the_alpha_shape_vertex, vertex));
+ } else {
+ // alpha shape found
+ Simplex_tree_vertex vertex = the_map_iterator->second;
+#ifdef DEBUG_TRACES
+ std::cout << "vertex [" << the_alpha_shape_vertex->point() << "] found in " << vertex << std::endl;
+#endif // DEBUG_TRACES
+ the_simplex_tree.push_back(vertex);
+ }
+ }
+ // Construction of the simplex_tree
+ Filtration_value filtr = /*std::sqrt*/(*the_alpha_value_iterator);
+#ifdef DEBUG_TRACES
+ std::cout << "filtration = " << filtr << std::endl;
+#endif // DEBUG_TRACES
+ if (filtr > filtration_max) {
+ filtration_max = filtr;
+ }
+ simplex_tree.insert_simplex(the_simplex_tree, filtr);
+ if (the_alpha_value_iterator != the_alpha_values.end())
+ ++the_alpha_value_iterator;
+ else
+ std::cout << "This shall not happen" << std::endl;
+ }
+ simplex_tree.set_filtration(filtration_max);
+ simplex_tree.set_dimension(dim_max);
+
+#ifdef DEBUG_TRACES
+ std::cout << "vertices \t\t" << count_vertices << std::endl;
+ std::cout << "edges \t\t" << count_edges << std::endl;
+ std::cout << "facets \t\t" << count_facets << std::endl;
+ std::cout << "cells \t\t" << count_cells << std::endl;
+
+
+ std::cout << "Information of the Simplex Tree: " << std::endl;
+ std::cout << " Number of vertices = " << simplex_tree.num_vertices() << " ";
+ std::cout << " Number of simplices = " << simplex_tree.num_simplices() << std::endl << std::endl;
+ std::cout << " Dimension = " << simplex_tree.dimension() << " ";
+ std::cout << " filtration = " << simplex_tree.filtration() << std::endl << std::endl;
+#endif // DEBUG_TRACES
+
+#ifdef DEBUG_TRACES
+ std::cout << "Iterator on vertices: " << std::endl;
+ for (auto vertex : simplex_tree.complex_vertex_range()) {
+ std::cout << vertex << " ";
+ }
+#endif // DEBUG_TRACES
+
+ // Sort the simplices in the order of the filtration
+ simplex_tree.initialize_filtration();
+
+ std::cout << "Simplex_tree dim: " << simplex_tree.dimension() << std::endl;
+ // Compute the persistence diagram of the complex
+ Persistent_cohomology pcoh(simplex_tree, true);
+ // initializes the coefficient field for homology
+ pcoh.init_coefficients(coeff_field_characteristic);
+
+ pcoh.compute_persistent_cohomology(min_persistence);
+
+ pcoh.output_diagram();
+
+ return 0;
+}
diff --git a/src/Persistent_cohomology/example/persistence_from_file.cpp b/src/Persistent_cohomology/example/persistence_from_file.cpp
index 8eb8d0f3..67235467 100644
--- a/src/Persistent_cohomology/example/persistence_from_file.cpp
+++ b/src/Persistent_cohomology/example/persistence_from_file.cpp
@@ -54,7 +54,7 @@ int main(int argc, char * argv[]) {
<< std::endl;
std::cout << " - p=" << p << " - min_persistence=" << min_persistence << std::endl;
- // Construct the Rips complex in a Simplex Tree
+ // Read the list of simplices from a file.
Simplex_tree<> simplex_tree;
std::ifstream simplex_tree_stream(simplex_tree_file);
diff --git a/src/Persistent_cohomology/example/plain_homology.cpp b/src/Persistent_cohomology/example/plain_homology.cpp
new file mode 100644
index 00000000..ae82c817
--- /dev/null
+++ b/src/Persistent_cohomology/example/plain_homology.cpp
@@ -0,0 +1,95 @@
+/* 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) 2015 INRIA Saclay - Ile-de-France (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/>.
+ */
+
+#include <gudhi/Simplex_tree.h>
+#include <gudhi/Persistent_cohomology.h>
+
+#include <iostream>
+#include <vector>
+#include <cstdint> // for std::uint8_t
+
+using namespace Gudhi;
+
+/* We could perfectly well use the default Simplex_tree<> (which uses
+ * Simplex_tree_options_full_featured), the following simply demonstrates
+ * how to save on storage by not storing a filtration value. */
+
+struct MyOptions : Simplex_tree_options_full_featured {
+ // Implicitly use 0 as filtration value for all simplices
+ static const bool store_filtration = false;
+ // The persistence algorithm needs this
+ static const bool store_key = true;
+ // I have few vertices
+ typedef short Vertex_handle;
+ // Maximum number of simplices to compute persistence is 2^8 - 1 = 255. One is reserved for null_key
+ typedef std::uint8_t Simplex_key;
+};
+typedef Simplex_tree<MyOptions> ST;
+
+int main() {
+ ST st;
+
+ /* Complex to build. */
+ /* 1 3 */
+ /* o---o */
+ /* /X\ / */
+ /* o---o o */
+ /* 2 0 4 */
+
+ const short triangle012[] = {0, 1, 2};
+ const short edge03[] = {0, 3};
+ const short edge13[] = {1, 3};
+ const short vertex4[] = {4};
+ st.insert_simplex_and_subfaces(triangle012);
+ st.insert_simplex_and_subfaces(edge03);
+ st.insert_simplex(edge13);
+ st.insert_simplex(vertex4);
+ // FIXME: Remove this line
+ st.set_dimension(2);
+
+ // Sort the simplices in the order of the filtration
+ st.initialize_filtration();
+
+ // Class for homology computation
+ persistent_cohomology::Persistent_cohomology<ST, persistent_cohomology::Field_Zp> pcoh(st);
+
+ // Initialize the coefficient field Z/2Z for homology
+ pcoh.init_coefficients(2);
+
+ // Compute the persistence diagram of the complex
+ pcoh.compute_persistent_cohomology();
+
+ // Print the result. The format is, on each line: 2 dim 0 inf
+ // where 2 represents the field, dim the dimension of the feature.
+ // 2 0 0 inf
+ // 2 0 0 inf
+ // 2 1 0 inf
+ // means that in Z/2Z-homology, the Betti numbers are b0=2 and b1=1.
+ pcoh.output_diagram();
+
+ // Print the Betti numbers are b0=2 and b1=1.
+ std::cout << std::endl;
+ std::cout << "The Betti numbers are : ";
+ for (int i = 0; i < st.dimension(); i++)
+ std::cout << "b" << i << " = " << pcoh.betti_number(i) << " ; ";
+ std::cout << std::endl;
+}
diff --git a/src/Persistent_cohomology/example/rips_multifield_persistence.cpp b/src/Persistent_cohomology/example/rips_multifield_persistence.cpp
index 5277bf7a..c5cd775d 100644
--- a/src/Persistent_cohomology/example/rips_multifield_persistence.cpp
+++ b/src/Persistent_cohomology/example/rips_multifield_persistence.cpp
@@ -68,7 +68,8 @@ int main(int argc, char * argv[]) {
, euclidean_distance<Point_t>);
// Construct the Rips complex in a Simplex Tree
- Simplex_tree<> st;
+ typedef Simplex_tree<Simplex_tree_options_fast_persistence> ST;
+ ST st;
// insert the proximity graph in the simplex tree
st.insert_graph(prox_graph);
// expand the graph until dimension dim_max
@@ -78,7 +79,7 @@ int main(int argc, char * argv[]) {
st.initialize_filtration();
// Compute the persistence diagram of the complex
- Persistent_cohomology< Simplex_tree<>, Multi_field > pcoh(st);
+ Persistent_cohomology<ST, Multi_field > pcoh(st);
// initializes the coefficient field for homology
pcoh.init_coefficients(min_p, max_p);
// compute persistent homology, disgarding persistent features of life shorter than min_persistence
diff --git a/src/Persistent_cohomology/example/rips_persistence.cpp b/src/Persistent_cohomology/example/rips_persistence.cpp
index 9b1ef42f..cab49395 100644
--- a/src/Persistent_cohomology/example/rips_persistence.cpp
+++ b/src/Persistent_cohomology/example/rips_persistence.cpp
@@ -30,6 +30,7 @@
#include <string>
#include <vector>
+#include <limits> // infinity
using namespace Gudhi;
using namespace Gudhi::persistent_cohomology;
@@ -65,7 +66,8 @@ int main(int argc, char * argv[]) {
, euclidean_distance<Point_t>);
// Construct the Rips complex in a Simplex Tree
- Simplex_tree<> st;
+ typedef Simplex_tree<Simplex_tree_options_fast_persistence> ST;
+ ST st;
// insert the proximity graph in the simplex tree
st.insert_graph(prox_graph);
// expand the graph until dimension dim_max
@@ -78,7 +80,7 @@ int main(int argc, char * argv[]) {
st.initialize_filtration();
// Compute the persistence diagram of the complex
- persistent_cohomology::Persistent_cohomology< Simplex_tree<>, Field_Zp > pcoh(st);
+ persistent_cohomology::Persistent_cohomology<ST, Field_Zp > pcoh(st);
// initializes the coefficient field for homology
pcoh.init_coefficients(p);
@@ -114,7 +116,7 @@ void program_options(int argc, char * argv[]
("help,h", "produce help message")
("output-file,o", po::value<std::string>(&filediag)->default_value(std::string()),
"Name of file in which the persistence diagram is written. Default print in std::cout")
- ("max-edge-length,r", po::value<Filtration_value>(&threshold)->default_value(0),
+ ("max-edge-length,r", po::value<Filtration_value>(&threshold)->default_value(std::numeric_limits<Filtration_value>::infinity()),
"Maximal length of an edge for the Rips complex construction.")
("cpx-dimension,d", po::value<int>(&dim_max)->default_value(1),
"Maximal dimension of the Rips complex we want to compute.")
diff --git a/src/Persistent_cohomology/example/rips_persistence_via_boundary_matrix.cpp b/src/Persistent_cohomology/example/rips_persistence_via_boundary_matrix.cpp
new file mode 100644
index 00000000..4c6656f5
--- /dev/null
+++ b/src/Persistent_cohomology/example/rips_persistence_via_boundary_matrix.cpp
@@ -0,0 +1,180 @@
+/* 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, Marc Glisse
+ *
+ * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France),
+ * 2015 INRIA Saclay Île de 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/>.
+ */
+
+#include <gudhi/reader_utils.h>
+#include <gudhi/graph_simplicial_complex.h>
+#include <gudhi/distance_functions.h>
+#include <gudhi/Simplex_tree.h>
+#include <gudhi/Persistent_cohomology.h>
+#include <gudhi/Hasse_complex.h>
+
+#include <boost/program_options.hpp>
+
+#ifdef GUDHI_USE_TBB
+#include <tbb/task_scheduler_init.h>
+#endif
+
+#include <string>
+#include <vector>
+
+////////////////////////////////////////////////////////////////
+// //
+// WARNING: persistence computation itself is not parallel, //
+// and this uses more memory than rips_persistence. //
+// //
+////////////////////////////////////////////////////////////////
+
+using namespace Gudhi;
+using namespace Gudhi::persistent_cohomology;
+
+typedef int Vertex_handle;
+typedef double Filtration_value;
+
+void program_options(int argc, char * argv[]
+ , std::string & filepoints
+ , std::string & filediag
+ , Filtration_value & threshold
+ , int & dim_max
+ , int & p
+ , Filtration_value & min_persistence);
+
+int main(int argc, char * argv[]) {
+ std::string filepoints;
+ std::string filediag;
+ Filtration_value threshold;
+ int dim_max;
+ int p;
+ Filtration_value min_persistence;
+
+ program_options(argc, argv, filepoints, filediag, threshold, dim_max, p, min_persistence);
+
+ // Extract the points from the file filepoints
+ typedef std::vector<double> Point_t;
+ std::vector< Point_t > points;
+ read_points(filepoints, points);
+
+ // Compute the proximity graph of the points
+ Graph_t prox_graph = compute_proximity_graph(points, threshold
+ , euclidean_distance<Point_t>);
+
+ // Construct the Rips complex in a Simplex Tree
+ Simplex_tree<>& st = *new Simplex_tree<>;
+ // insert the proximity graph in the simplex tree
+ st.insert_graph(prox_graph);
+ // expand the graph until dimension dim_max
+ st.expansion(dim_max);
+
+ std::cout << "The complex contains " << st.num_simplices() << " simplices \n";
+ std::cout << " and has dimension " << st.dimension() << " \n";
+
+#ifdef GUDHI_USE_TBB
+ // Unnecessary, but clarifies which operations are parallel.
+ tbb::task_scheduler_init ts;
+#endif
+
+ // Sort the simplices in the order of the filtration
+ st.initialize_filtration();
+ int count = 0;
+ for (auto sh : st.filtration_simplex_range())
+ st.assign_key(sh, count++);
+
+ // Convert to a more convenient representation.
+ Hasse_complex<> hcpx(st);
+
+#ifdef GUDHI_USE_TBB
+ ts.terminate();
+#endif
+
+ // Free some space.
+ delete &st;
+
+ // Compute the persistence diagram of the complex
+ persistent_cohomology::Persistent_cohomology< Hasse_complex<>, Field_Zp > pcoh(hcpx);
+ // initializes the coefficient field for homology
+ pcoh.init_coefficients(p);
+
+ pcoh.compute_persistent_cohomology(min_persistence);
+
+ // Output the diagram in filediag
+ if (filediag.empty()) {
+ pcoh.output_diagram();
+ } else {
+ std::ofstream out(filediag);
+ pcoh.output_diagram(out);
+ out.close();
+ }
+}
+
+void program_options(int argc, char * argv[]
+ , std::string & filepoints
+ , std::string & filediag
+ , Filtration_value & threshold
+ , int & dim_max
+ , int & p
+ , Filtration_value & min_persistence) {
+ namespace po = boost::program_options;
+ po::options_description hidden("Hidden options");
+ hidden.add_options()
+ ("input-file", po::value<std::string>(&filepoints),
+ "Name of file containing a point set. Format is one point per line: X1 ... Xd ");
+
+ po::options_description visible("Allowed options", 100);
+ visible.add_options()
+ ("help,h", "produce help message")
+ ("output-file,o", po::value<std::string>(&filediag)->default_value(std::string()),
+ "Name of file in which the persistence diagram is written. Default print in std::cout")
+ ("max-edge-length,r", po::value<Filtration_value>(&threshold)->default_value(0),
+ "Maximal length of an edge for the Rips complex construction.")
+ ("cpx-dimension,d", po::value<int>(&dim_max)->default_value(1),
+ "Maximal dimension of the Rips complex we want to compute.")
+ ("field-charac,p", po::value<int>(&p)->default_value(11),
+ "Characteristic p of the coefficient field Z/pZ for computing homology.")
+ ("min-persistence,m", po::value<Filtration_value>(&min_persistence),
+ "Minimal lifetime of homology feature to be recorded. Default is 0. Enter a negative value to see zero length intervals");
+
+ po::positional_options_description pos;
+ pos.add("input-file", 1);
+
+ po::options_description all;
+ all.add(visible).add(hidden);
+
+ po::variables_map vm;
+ po::store(po::command_line_parser(argc, argv).
+ options(all).positional(pos).run(), vm);
+ po::notify(vm);
+
+ if (vm.count("help") || !vm.count("input-file")) {
+ std::cout << std::endl;
+ std::cout << "Compute the persistent homology with coefficient field Z/pZ \n";
+ std::cout << "of a Rips complex defined on a set of input points.\n \n";
+ std::cout << "The output diagram contains one bar per line, written with the convention: \n";
+ std::cout << " p dim b d \n";
+ std::cout << "where dim is the dimension of the homological feature,\n";
+ std::cout << "b and d are respectively the birth and death of the feature and \n";
+ std::cout << "p is the characteristic of the field Z/pZ used for homology coefficients." << std::endl << std::endl;
+
+ std::cout << "Usage: " << argv[0] << " [options] input-file" << std::endl << std::endl;
+ std::cout << visible << std::endl;
+ std::abort();
+ }
+}
diff --git a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h
index d096792f..b31df6a4 100644
--- a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h
+++ b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h
@@ -27,7 +27,6 @@
#include <gudhi/Persistent_cohomology/Field_Zp.h>
#include <gudhi/Simple_object_pool.h>
-#include <boost/tuple/tuple.hpp>
#include <boost/intrusive/set.hpp>
#include <boost/pending/disjoint_sets.hpp>
#include <boost/intrusive/list.hpp>
@@ -42,154 +41,16 @@
#include <tuple>
#include <algorithm>
#include <string>
+#include <stdexcept> // for std::out_of_range
namespace Gudhi {
namespace persistent_cohomology {
-/** \defgroup persistent_cohomology Persistent Cohomology
- *
-
- Computation of persistent cohomology using the algorithm of
- \cite DBLP:journals/dcg/SilvaMV11 and \cite DBLP:journals/corr/abs-1208-5018
- and the Compressed Annotation Matrix
- implementation of \cite DBLP:conf/esa/BoissonnatDM13
-
- The theory of homology consists in attaching to a topological space a sequence of
- (homology) groups,
- capturing global topological features
- like connected components, holes, cavities, etc. Persistent homology studies the evolution
- -- birth, life and death -- of
- these features when the topological space is changing. Consequently, the theory is essentially
- composed of three elements:
- topological spaces, their homology groups and an evolution scheme.
-
- The theory of homology consists in attaching to a topological space a sequence of
- (homology) groups,
- capturing global topological features
- like connected components, holes, cavities, etc. Persistent homology studies the evolution
- -- birth, life and death -- of
- these features when the topological space is changing. Consequently, the theory is essentially
- composed of three elements:
- topological spaces, their homology groups and an evolution scheme.
-
- <DT>Topological Spaces:</DT>
- Topological spaces are represented by simplicial complexes.
- Let \f$V = \{1, \cdots ,|V|\}\f$ be a set of <EM>vertices</EM>.
- A <EM>simplex</EM> \f$\sigma\f$ is a subset of vertices
- \f$\sigma \subseteq V\f$. A <EM>simplicial complex</EM> \f$\mathbf{K}\f$
- on \f$V\f$ is a collection of simplices \f$\{\sigma\}\f$,
- \f$\sigma \subseteq V\f$, such that \f$\tau \subseteq \sigma \in \mathbf{K}
- \Rightarrow \tau \in \mathbf{K}\f$. The dimension \f$n=|\sigma|-1\f$ of \f$\sigma\f$
- is its number of elements minus 1. A <EM>filtration</EM> of a simplicial complex is
- a function \f$f:\mathbf{K} \rightarrow \mathbb{R}\f$ satisfying \f$f(\tau)\leq
- f(\sigma)\f$ whenever \f$\tau \subseteq \sigma\f$.
-
- We define the concept FilteredComplex which enumerates the requirements for a class
- to represent a filtered complex from which persistent homology may be computed.
- We use the vocabulary of simplicial complexes, but the concept
- is valid for any type of cell complex. The main requirements
- are the definition of:
- \li type <CODE>Indexing_tag</CODE>, which is a model of the concept
- <CODE>IndexingTag</CODE>,
- describing the nature of the indexing scheme,
- \li type Simplex_handle to manipulate simplices,
- \li method <CODE>int dimension(Simplex_handle)</CODE> returning
- the dimension of a simplex,
- \li type and method <CODE>Boundary_simplex_range
- boundary_simplex_range(Simplex_handle)</CODE> that returns
- a range giving access to the codimension 1 subsimplices of the
- input simplex, as-well-as the coefficients \f$(-1)^i\f$ in the
- definition of the operator \f$\partial\f$. The iterators have
- value type <CODE>Simplex_handle</CODE>,
- \li type and method
- <CODE>Filtration_simplex_range filtration_simplex_range ()</CODE>
- that returns a range giving
- access to all the simplices of the complex read in the order
- assigned by the indexing scheme,
- \li type and method
- <CODE>Filtration_value filtration (Simplex_handle)</CODE> that returns the value of
- the filtration on the simplex represented by the handle.
-
- <DT>Homology:</DT>
- For a ring \f$\mathcal{R}\f$, the group of <EM>n-chains</EM>,
- denoted \f$\mathbf{C}_n(\mathbf{K},\mathcal{R})\f$, of \f$\mathbf{K}\f$ is the
- group of formal sums of
- n-simplices with \f$\mathcal{R}\f$ coefficients. The <EM>boundary operator</EM> is a
- linear operator
- \f$\partial_n: \mathbf{C}_n(\mathbf{K},\mathcal{R}) \rightarrow \mathbf{C}_{n-1}(\mathbf{K},\mathcal{R})\f$
- such that \f$\partial_n \sigma = \partial_n [v_0, \cdots , v_n] =
- \sum_{i=0}^n (-1)^{i}[v_0,\cdots ,\widehat{v_i}, \cdots,v_n]\f$,
- where \f$\widehat{v_i}\f$ means \f$v_i\f$ is omitted from the list. The chain
- groups form a sequence:
-
- \f[\cdots \ \ \mathbf{C}_n(\mathbf{K},\mathcal{R}) \xrightarrow{\ \partial_n\ } \mathbf{C}_{n-1}(\mathbf{K},\mathcal{R})
- \xrightarrow{\partial_{n-1}} \cdots \xrightarrow{\ \partial_2 \ }
- \mathbf{C}_1(\mathbf{K},\mathcal{R}) \xrightarrow{\ \partial_1 \ } \mathbf{C}_0(\mathbf{K},\mathcal{R}) \f]
-
- of finitely many groups \f$\mathbf{C}_n(\mathbf{K},\mathcal{R})\f$ and homomorphisms
- \f$\partial_n\f$, indexed by the dimension \f$n \geq 0\f$.
- The boundary operators satisfy the property \f$\partial_n \circ \partial_{n+1}=0\f$
- for every \f$n > 0\f$
- and we define the homology groups:
-
- \f[\mathbf{H}_n(\mathbf{K},\mathcal{R}) = \ker \partial_n / \mathrm{im} \ \partial_{n+1}\f]
-
- We refer to \cite Munkres-elementsalgtop1984 for an introduction to homology
- theory and to \cite DBLP:books/daglib/0025666 for an introduction to persistent homology.
-
- <DT>Indexing Scheme:</DT>
- "Changing" a simplicial complex consists in applying a simplicial map.
- An <EM>indexing scheme</EM> is a directed graph together with a traversal
- order, such that two
- consecutive nodes in the graph are connected by an arrow (either forward or backward).
- The nodes represent simplicial complexes and the directed edges simplicial maps.
-
- From the computational point of view, there are two types of indexing schemes of
- interest
- in persistent homology: <EM>linear</EM> ones
- \f$\bullet \longrightarrow \bullet \longrightarrow \cdots \longrightarrow \bullet
- \longrightarrow \bullet\f$
- in persistent homology \cite DBLP:journals/dcg/ZomorodianC05 ,
- and <EM>zigzag</EM> ones
- \f$\bullet \longrightarrow \bullet \longleftarrow \cdots
- \longrightarrow \bullet
- \longleftarrow \bullet \f$ in zigzag persistent
- homology \cite DBLP:journals/focm/CarlssonS10.
- These indexing schemes have a natural left-to-right traversal order, and we
- describe them with ranges and iterators.
- In the current release of the Gudhi library, only the linear case is implemented.
-
- In the following, we consider the case where the indexing scheme is induced
- by a filtration.
- Ordering the simplices
- by increasing filtration values (breaking ties so as a simplex appears after
- its subsimplices of same filtration value) provides an indexing scheme.
-
-\section Examples
- We provide several example files: run these examples with -h for details on their use, and read the README file.
-
-\li <CODE>rips_persistence.cpp</CODE> computes the Rips complex of a point cloud and its persistence diagram.
-
-\li <CODE>rips_multifield_persistence.cpp</CODE> computes the Rips complex of a point cloud and its persistence diagram
-with a family of field coefficients.
-
-\li <CODE>performance_rips_persistence.cpp</CODE> provides timings for the construction of the Rips complex on a set of
-points sampling a Klein bottle in \f$\mathbb{R}^5\f$ with a simplex tree, its conversion to a
-Hasse diagram and the computation of persistent homology and multi-field persistent homology for the
-different representations.
-
-
-
- \author Clément Maria
- \version 1.0
- \date 2014
- \copyright GNU General Public License v3.
- @{
- */
-
/** \brief Computes the persistent cohomology of a filtered complex.
*
+ * \ingroup persistent_cohomology
+ *
* The computation is implemented with a Compressed Annotation Matrix
* (CAM)\cite DBLP:conf/esa/BoissonnatDM13,
* and is adapted to the computation of Multi-Field Persistent Homology (MF)
@@ -198,8 +59,8 @@ different representations.
* \implements PersistentHomology
*
*/
-// Memory allocation policy: classic, use a mempool, etc.*/
-template<class FilteredComplex, class CoefficientField> // to do mem allocation policy: classic, mempool, etc.
+// TODO(CM): Memory allocation policy: classic, use a mempool, etc.
+template<class FilteredComplex, class CoefficientField>
class Persistent_cohomology {
public:
typedef FilteredComplex Complex_ds;
@@ -208,7 +69,7 @@ class Persistent_cohomology {
typedef typename Complex_ds::Simplex_handle Simplex_handle;
typedef typename Complex_ds::Filtration_value Filtration_value;
typedef typename CoefficientField::Element Arith_element;
-// Compressed Annotation Matrix types:
+ // Compressed Annotation Matrix types:
// Column type
typedef Persistent_cohomology_column<Simplex_key, Arith_element> Column; // contains 1 set_hook
// Cell type
@@ -220,15 +81,16 @@ class Persistent_cohomology {
typedef boost::intrusive::set<Column,
boost::intrusive::constant_time_size<false> > Cam;
-// Sparse column type for the annotation of the boundary of an element.
+ // Sparse column type for the annotation of the boundary of an element.
typedef std::vector<std::pair<Simplex_key, Arith_element> > A_ds_type;
-// Persistent interval type. The Arith_element field is used for the multi-field framework.
- typedef boost::tuple<Simplex_handle, Simplex_handle, Arith_element> Persistent_interval;
+ // Persistent interval type. The Arith_element field is used for the multi-field framework.
+ typedef std::tuple<Simplex_handle, Simplex_handle, Arith_element> Persistent_interval;
/** \brief Initializes the Persistent_cohomology class.
*
* @param[in] cpx Complex for which the persistent homology is computed.
- cpx is a model of FilteredComplex
+ * cpx is a model of FilteredComplex
+ * @exception std::out_of_range In case the number of simplices is more than Simplex_key type numeric limit.
*/
explicit Persistent_cohomology(Complex_ds& cpx)
: cpx_(&cpx),
@@ -246,6 +108,10 @@ class Persistent_cohomology {
interval_length_policy(&cpx, 0),
column_pool_(), // memory pools for the CAM
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.");
+ }
Simplex_key idx_fil = 0;
for (auto sh : cpx_->filtration_simplex_range()) {
cpx_->assign_key(sh, idx_fil);
@@ -257,7 +123,7 @@ class Persistent_cohomology {
/** \brief Initializes the Persistent_cohomology class.
*
* @param[in] cpx Complex for which the persistent homology is compiuted.
- cpx is a model of FilteredComplex
+ * cpx is a model of FilteredComplex
*
* @param[in] persistence_dim_max if true, the persistent homology for the maximal dimension in the
* complex is computed. If false, it is ignored. Default is false.
@@ -346,7 +212,7 @@ class Persistent_cohomology {
persistent_pairs_.emplace_back(
cpx_->simplex(zero_idx.second), cpx_->null_simplex(), coeff_field_.characteristic());
}
-// Compute infinite interval of dimension > 0
+ // Compute infinite interval of dimension > 0
for (auto cocycle : transverse_idx_) {
persistent_pairs_.emplace_back(
cpx_->simplex(cocycle.first), cpx_->null_simplex(), cocycle.second.characteristics_);
@@ -431,9 +297,12 @@ class Persistent_cohomology {
std::map<Simplex_key, Arith_element> & map_a_ds, Simplex_handle sigma,
int dim_sigma) {
// traverses the boundary of sigma, keeps track of the annotation vectors,
- // with multiplicity, in a map.
- std::map<Column *, int> annotations_in_boundary;
- std::pair<typename std::map<Column *, int>::iterator, bool> result_insert_bound;
+ // 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;
+ annotations_in_boundary.clear();
int sign = 1 - 2 * (dim_sigma % 2); // \in {-1,1} provides the sign in the
// alternate sum in the boundary.
Simplex_key key;
@@ -445,22 +314,29 @@ class Persistent_cohomology {
// Find its annotation vector
curr_col = ds_repr_[dsets_.find_set(key)];
if (curr_col != NULL) { // and insert it in annotations_in_boundary with multyiplicative factor "sign".
- result_insert_bound = annotations_in_boundary.insert(std::pair<Column *, int>(curr_col, sign));
- if (!(result_insert_bound.second)) {
- result_insert_bound.first->second += sign;
- }
+ annotations_in_boundary.emplace_back(curr_col, sign);
}
}
sign = -sign;
}
+ // Place identical annotations consecutively so we can easily sum their multiplicities.
+ std::sort(annotations_in_boundary.begin(), annotations_in_boundary.end(),
+ [](annotation_t const& a, annotation_t const& b) { return a.first < b.first; });
+
// Sum the annotations with multiplicity, using a map<key,coeff>
// to represent a sparse vector.
std::pair<typename std::map<Simplex_key, Arith_element>::iterator, bool> result_insert_a_ds;
- for (auto ann_ref : annotations_in_boundary) {
- if (ann_ref.second != coeff_field_.additive_identity()) { // For all columns in the boundary,
- for (auto cell_ref : ann_ref.first->col_) { // insert every cell in map_a_ds with multiplicity
- Arith_element w_y = coeff_field_.times(cell_ref.coefficient_, ann_ref.second); // coefficient * multiplicity
+ for (auto ann_it = annotations_in_boundary.begin(); ann_it != annotations_in_boundary.end(); /**/) {
+ Column* col = ann_it->first;
+ int mult = ann_it->second;
+ while (++ann_it != annotations_in_boundary.end() && ann_it->first == col) {
+ mult += ann_it->second;
+ }
+ // The following test is just a heuristic, it is not required, and it is fine that is misses p == 0.
+ if (mult != coeff_field_.additive_identity()) { // For all columns in the boundary,
+ for (auto cell_ref : col->col_) { // insert every cell in map_a_ds with multiplicity
+ Arith_element w_y = coeff_field_.times(cell_ref.coefficient_, mult); // coefficient * multiplicity
if (w_y != coeff_field_.additive_identity()) { // if != 0
result_insert_a_ds = map_a_ds.insert(std::pair<Simplex_key, Arith_element>(cell_ref.key_, w_y));
@@ -696,7 +572,6 @@ class Persistent_cohomology {
* feature exists in homology with Z/piZ coefficients.
*/
void output_diagram(std::ostream& ostream = std::cout) {
-
cmp_intervals_by_length cmp(cpx_);
std::sort(std::begin(persistent_pairs_), std::end(persistent_pairs_), cmp);
bool has_infinity = std::numeric_limits<Filtration_value>::has_infinity;
@@ -724,12 +599,105 @@ class Persistent_cohomology {
}
}
+ /** @brief Returns Betti numbers.
+ * @return A vector of Betti numbers.
+ */
+ std::vector<int> betti_numbers() const {
+ // Init Betti numbers vector with zeros until Simplicial complex dimension
+ std::vector<int> betti_numbers(cpx_->dimension(), 0);
+
+ for (auto pair : persistent_pairs_) {
+ // Count never ended persistence intervals
+ if (cpx_->null_simplex() == get<1>(pair)) {
+ // Increment corresponding betti number
+ betti_numbers[cpx_->dimension(get<0>(pair))] += 1;
+ }
+ }
+ return betti_numbers;
+ }
+
+ /** @brief Returns the Betti number of the dimension passed by parameter.
+ * @param[in] dimension The Betti number dimension to get.
+ * @return Betti number of the given dimension
+ *
+ */
+ int betti_number(int dimension) const {
+ int betti_number = 0;
+
+ for (auto pair : persistent_pairs_) {
+ // Count never ended persistence intervals
+ if (cpx_->null_simplex() == get<1>(pair)) {
+ if (cpx_->dimension(get<0>(pair)) == dimension) {
+ // Increment betti number found
+ ++betti_number;
+ }
+ }
+ }
+ return betti_number;
+ }
+
+ /** @brief Returns the persistent Betti numbers.
+ * @param[in] from The persistence birth limit to be added in the number \f$(persistent birth \leq from)\f$.
+ * @param[in] to The persistence death limit to be added in the number \f$(persistent death > to)\f$.
+ * @return A vector of persistent Betti numbers.
+ */
+ 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);
+
+ 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
+ // still work if we change the complex filtration function to reject null simplices.
+ if (cpx_->filtration(get<0>(pair)) <= from &&
+ (get<1>(pair) == cpx_->null_simplex() || cpx_->filtration(get<1>(pair)) > to)) {
+ // Increment corresponding betti number
+ betti_numbers[cpx_->dimension(get<0>(pair))] += 1;
+ }
+ }
+ return betti_numbers;
+ }
+
+ /** @brief Returns the persistent Betti number of the dimension passed by parameter.
+ * @param[in] dimension The Betti number dimension to get.
+ * @param[in] from The persistence birth limit to be added in the number \f$(persistent birth \leq from)\f$.
+ * @param[in] to The persistence death limit to be added in the number \f$(persistent death > to)\f$.
+ * @return Persistent Betti number of the given dimension
+ */
+ int persistent_betti_number(int dimension, Filtration_value from, Filtration_value to) const {
+ int betti_number = 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
+ // still work if we change the complex filtration function to reject null simplices.
+ if (cpx_->filtration(get<0>(pair)) <= from &&
+ (get<1>(pair) == cpx_->null_simplex() || cpx_->filtration(get<1>(pair)) > to)) {
+ if (cpx_->dimension(get<0>(pair)) == dimension) {
+ // Increment betti number found
+ ++betti_number;
+ }
+ }
+ }
+ return betti_number;
+ }
+
+ /** @brief Returns the persistent pairs.
+ * @return Persistent pairs
+ *
+ */
+ const std::vector<Persistent_interval>& get_persistent_pairs() const {
+ return persistent_pairs_;
+ }
+
private:
/*
* Structure representing a cocycle.
*/
struct cocycle {
- cocycle() {
+ cocycle()
+ : row_(nullptr),
+ characteristics_() {
}
cocycle(Arith_element characteristics, Hcell * row)
: row_(row),
@@ -770,8 +738,6 @@ class Persistent_cohomology {
Simple_object_pool<Cell> cell_pool_;
};
-/** @} */ // end defgroup persistent_cohomology
-
} // namespace persistent_cohomology
} // namespace Gudhi
diff --git a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Multi_field.h b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Multi_field.h
index 0591fc95..38bc08d1 100644
--- a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Multi_field.h
+++ b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Multi_field.h
@@ -81,8 +81,7 @@ class Multi_field {
// set m to primorial(bound_prime)
prod_characteristics_ = 1;
for (auto p : primes_) {
- mpz_mul_ui(prod_characteristics_.get_mpz_t(),
- prod_characteristics_.get_mpz_t(), p);
+ prod_characteristics_ *= p;
}
// Uvect_
diff --git a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Persistent_cohomology_column.h b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Persistent_cohomology_column.h
index 612658e6..5deb2d88 100644
--- a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Persistent_cohomology_column.h
+++ b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Persistent_cohomology_column.h
@@ -23,7 +23,6 @@
#ifndef PERSISTENT_COHOMOLOGY_PERSISTENT_COHOMOLOGY_COLUMN_H_
#define PERSISTENT_COHOMOLOGY_PERSISTENT_COHOMOLOGY_COLUMN_H_
-#include <boost/tuple/tuple.hpp>
#include <boost/intrusive/set.hpp>
#include <boost/intrusive/list.hpp>
diff --git a/src/Persistent_cohomology/test/CMakeLists.txt b/src/Persistent_cohomology/test/CMakeLists.txt
index ed63a6ac..a21f39c4 100644
--- a/src/Persistent_cohomology/test/CMakeLists.txt
+++ b/src/Persistent_cohomology/test/CMakeLists.txt
@@ -1,21 +1,23 @@
cmake_minimum_required(VERSION 2.6)
-project(GUDHIPersistentCohomologyUT)
+project(Persistent_cohomology_tests)
if (GCOVR_PATH)
# for gcovr to make coverage reports - Corbera Jenkins plugin
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
- set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fprofile-arcs -ftest-coverage")
- set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fprofile-arcs -ftest-coverage")
-endif()
+endif(GCOVR_PATH)
if (GPROF_PATH)
# for gprof to make coverage reports - Jenkins
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg")
- set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pg")
- set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pg")
-endif()
+endif(GPROF_PATH)
add_executable ( PersistentCohomologyUT persistent_cohomology_unit_test.cpp )
target_link_libraries(PersistentCohomologyUT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+add_executable ( BettiNumbersUT betti_numbers_unit_test.cpp )
+target_link_libraries(BettiNumbersUT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+if (TBB_FOUND)
+ target_link_libraries(PersistentCohomologyUT ${TBB_LIBRARIES})
+ target_link_libraries(BettiNumbersUT ${TBB_LIBRARIES})
+endif(TBB_FOUND)
# Unitary tests
add_test(NAME PersistentCohomologyUT
@@ -24,9 +26,17 @@ add_test(NAME PersistentCohomologyUT
# XML format for Jenkins xUnit plugin
--log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/PersistentCohomologyUT.xml --log_level=test_suite --report_level=no)
+add_test(NAME BettiNumbersUT
+ COMMAND ${CMAKE_CURRENT_BINARY_DIR}/BettiNumbersUT
+ # XML format for Jenkins xUnit plugin
+ --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/BettiNumbersUT.xml --log_level=test_suite --report_level=no)
+
if(GMPXX_FOUND AND GMP_FOUND)
add_executable ( PersistentCohomologyMultiFieldUT persistent_cohomology_unit_test_multi_field.cpp )
target_link_libraries(PersistentCohomologyMultiFieldUT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES})
+ if (TBB_FOUND)
+ target_link_libraries(PersistentCohomologyMultiFieldUT ${TBB_LIBRARIES})
+ endif(TBB_FOUND)
# Unitary tests
add_test(NAME PersistentCohomologyMultiFieldUT
@@ -35,5 +45,5 @@ if(GMPXX_FOUND AND GMP_FOUND)
# XML format for Jenkins xUnit plugin
--log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/PersistentCohomologyMultiFieldUT.xml --log_level=test_suite --report_level=no)
-endif()
+endif(GMPXX_FOUND AND GMP_FOUND)
diff --git a/src/Persistent_cohomology/test/betti_numbers_unit_test.cpp b/src/Persistent_cohomology/test/betti_numbers_unit_test.cpp
new file mode 100644
index 00000000..40221005
--- /dev/null
+++ b/src/Persistent_cohomology/test/betti_numbers_unit_test.cpp
@@ -0,0 +1,234 @@
+#include <iostream>
+#include <string>
+#include <algorithm>
+#include <utility> // std::pair, std::make_pair
+#include <cmath> // float comparison
+#include <limits>
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE "betti_numbers"
+#include <boost/test/unit_test.hpp>
+
+#include "gudhi/Simplex_tree.h"
+#include "gudhi/Persistent_cohomology.h"
+
+struct MiniSTOptions : Gudhi::Simplex_tree_options_full_featured {
+ // Implicitly use 0 as filtration value for all simplices
+ static const bool store_filtration = false;
+ // The persistence algorithm needs this
+ static const bool store_key = true;
+ // I have few vertices
+ typedef short Vertex_handle;
+};
+
+using Mini_simplex_tree = Gudhi::Simplex_tree<MiniSTOptions>;
+using Mini_st_persistence =
+ Gudhi::persistent_cohomology::Persistent_cohomology<Mini_simplex_tree, Gudhi::persistent_cohomology::Field_Zp>;
+
+/*
+ * Compare two intervals by dimension, then by length.
+ */
+template<class Simplicial_complex>
+struct cmp_intervals_by_dim_then_length {
+ explicit cmp_intervals_by_dim_then_length(Simplicial_complex * sc)
+ : sc_(sc) { }
+
+ template<typename Persistent_interval>
+ bool operator()(const Persistent_interval & p1, const Persistent_interval & p2) {
+ if (sc_->dimension(get < 0 > (p1)) == sc_->dimension(get < 0 > (p2)))
+ return (sc_->filtration(get < 1 > (p1)) - sc_->filtration(get < 0 > (p1))
+ > sc_->filtration(get < 1 > (p2)) - sc_->filtration(get < 0 > (p2)));
+ else
+ return (sc_->dimension(get < 0 > (p1)) > sc_->dimension(get < 0 > (p2)));
+ }
+ Simplicial_complex* sc_;
+};
+
+BOOST_AUTO_TEST_CASE( plain_homology_betti_numbers )
+{
+ Mini_simplex_tree st;
+
+ /* Complex to build. */
+ /* 1 4 */
+ /* o---o */
+ /* /3\ / */
+ /* o---o o */
+ /* 2 0 5 */
+ const short tetra0123[] = {0, 1, 2, 3};
+ const short edge04[] = {0, 4};
+ const short edge14[] = {1, 4};
+ const short vertex5[] = {5};
+ st.insert_simplex_and_subfaces(tetra0123);
+ st.insert_simplex_and_subfaces(edge04);
+ st.insert_simplex(edge14);
+ st.insert_simplex(vertex5);
+ // FIXME: Remove this line
+ st.set_dimension(3);
+
+ // Sort the simplices in the order of the filtration
+ st.initialize_filtration();
+
+ // Class for homology computation
+ Mini_st_persistence pcoh(st);
+
+ // Initialize the coefficient field Z/3Z for homology
+ pcoh.init_coefficients(3);
+
+ // Compute the persistence diagram of the complex
+ pcoh.compute_persistent_cohomology();
+
+ // Print the result. The format is, on each line: 2 dim 0 inf
+ // where 2 represents the field, dim the dimension of the feature.
+ // 2 0 0 inf
+ // 2 0 0 inf
+ // 2 1 0 inf
+ // means that in Z/2Z-homology, the Betti numbers are b0=2 and b1=1.
+
+ BOOST_CHECK(pcoh.betti_number(0) == 2);
+ BOOST_CHECK(pcoh.betti_number(1) == 1);
+ BOOST_CHECK(pcoh.betti_number(2) == 0);
+
+ std::vector<int> bns = pcoh.betti_numbers();
+ BOOST_CHECK(bns.size() == 3);
+ BOOST_CHECK(bns[0] == 2);
+ BOOST_CHECK(bns[1] == 1);
+ BOOST_CHECK(bns[2] == 0);
+
+ // Custom sort and output persistence
+ cmp_intervals_by_dim_then_length<Mini_simplex_tree> cmp(&st);
+ auto persistent_pairs = pcoh.get_persistent_pairs();
+
+ std::sort(std::begin(persistent_pairs), std::end(persistent_pairs), cmp);
+
+ BOOST_CHECK(persistent_pairs.size() == 3);
+ // persistent_pairs[0] = 2 1 0 inf
+ BOOST_CHECK(st.dimension(get<0>(persistent_pairs[0])) == 1);
+ BOOST_CHECK(st.filtration(get<0>(persistent_pairs[0])) == 0);
+ BOOST_CHECK(get<1>(persistent_pairs[0]) == st.null_simplex());
+
+ // persistent_pairs[1] = 2 0 0 inf
+ BOOST_CHECK(st.dimension(get<0>(persistent_pairs[1])) == 0);
+ BOOST_CHECK(st.filtration(get<0>(persistent_pairs[1])) == 0);
+ BOOST_CHECK(get<1>(persistent_pairs[1]) == st.null_simplex());
+
+ // persistent_pairs[2] = 2 0 0 inf
+ BOOST_CHECK(st.dimension(get<0>(persistent_pairs[2])) == 0);
+ BOOST_CHECK(st.filtration(get<0>(persistent_pairs[2])) == 0);
+ BOOST_CHECK(get<1>(persistent_pairs[2]) == st.null_simplex());
+}
+
+using Simplex_tree = Gudhi::Simplex_tree<>;
+using St_persistence =
+ Gudhi::persistent_cohomology::Persistent_cohomology<Simplex_tree, Gudhi::persistent_cohomology::Field_Zp>;
+
+BOOST_AUTO_TEST_CASE( betti_numbers )
+{
+ Simplex_tree st;
+
+ /* Complex to build. */
+ /* 1 4 */
+ /* o---o */
+ /* /3\ / */
+ /* o---o o */
+ /* 2 0 5 */
+ const short tetra0123[] = {0, 1, 2, 3};
+ const short edge04[] = {0, 4};
+ const short edge14[] = {1, 4};
+ const short vertex5[] = {5};
+ st.insert_simplex_and_subfaces(tetra0123, 4.0);
+ st.insert_simplex_and_subfaces(edge04, 2.0);
+ st.insert_simplex(edge14, 2.0);
+ st.insert_simplex(vertex5, 1.0);
+ // FIXME: Remove this line
+ st.set_dimension(3);
+
+ // Sort the simplices in the order of the filtration
+ st.initialize_filtration();
+
+ // Class for homology computation
+ St_persistence pcoh(st);
+
+ // Initialize the coefficient field Z/3Z for homology
+ pcoh.init_coefficients(3);
+
+ // Compute the persistence diagram of the complex
+ pcoh.compute_persistent_cohomology();
+
+ // Check the Betti numbers are b0=2, b1=1 and b2=0.
+ BOOST_CHECK(pcoh.betti_number(0) == 2);
+ BOOST_CHECK(pcoh.betti_number(1) == 1);
+ BOOST_CHECK(pcoh.betti_number(2) == 0);
+
+ // Check the Betti numbers are b0=2, b1=1 and b2=0.
+ std::vector<int> bns = pcoh.betti_numbers();
+ BOOST_CHECK(bns.size() == 3);
+ BOOST_CHECK(bns[0] == 2);
+ BOOST_CHECK(bns[1] == 1);
+ BOOST_CHECK(bns[2] == 0);
+
+ // Check the persistent Betti numbers in [4., 10.] are b0=2, b1=1 and b2=0.
+ BOOST_CHECK(pcoh.persistent_betti_number(0, 4., 10.) == 2);
+ BOOST_CHECK(pcoh.persistent_betti_number(1, 4., 10.) == 1);
+ BOOST_CHECK(pcoh.persistent_betti_number(2, 4., 10.) == 0);
+
+ // Check the persistent Betti numbers in [2., 100.] are b0=2, b1=0 and b2=0.
+ BOOST_CHECK(pcoh.persistent_betti_number(0, 2., 100.) == 2);
+ BOOST_CHECK(pcoh.persistent_betti_number(1, 2., 100.) == 0);
+ BOOST_CHECK(pcoh.persistent_betti_number(2, 2., 100.) == 0);
+
+ // Check the persistent Betti numbers in [1., 1000.] are b0=1, b1=0 and b2=0.
+ BOOST_CHECK(pcoh.persistent_betti_number(0, 1., 1000.) == 1);
+ BOOST_CHECK(pcoh.persistent_betti_number(1, 1., 1000.) == 0);
+ BOOST_CHECK(pcoh.persistent_betti_number(2, 1., 1000.) == 0);
+
+ // Check the persistent Betti numbers in [.9, 1000.] are b0=0, b1=0 and b2=0.
+ BOOST_CHECK(pcoh.persistent_betti_number(0, .9, 1000.) == 0);
+ BOOST_CHECK(pcoh.persistent_betti_number(1, .9, 1000.) == 0);
+ BOOST_CHECK(pcoh.persistent_betti_number(2, .9, 1000.) == 0);
+
+ // Check the persistent Betti numbers in [4.1, 10000.] are b0=2, b1=1 and b2=0.
+ bns = pcoh.persistent_betti_numbers(4.1, 10000.);
+ BOOST_CHECK(bns[0] == 2);
+ BOOST_CHECK(bns[1] == 1);
+ BOOST_CHECK(bns[2] == 0);
+
+ // Check the persistent Betti numbers in [2.1, 100000.] are b0=2, b1=0 and b2=0.
+ bns = pcoh.persistent_betti_numbers(2.1, 100000.);
+ BOOST_CHECK(bns[0] == 2);
+ BOOST_CHECK(bns[1] == 0);
+ BOOST_CHECK(bns[2] == 0);
+
+ // Check the persistent Betti numbers in [1.1, 1000000.] are b0=1, b1=0 and b2=0.
+ bns = pcoh.persistent_betti_numbers(1.1, 1000000.);
+ BOOST_CHECK(bns[0] == 1);
+ BOOST_CHECK(bns[1] == 0);
+ BOOST_CHECK(bns[2] == 0);
+
+ // Check the persistent Betti numbers in [.1, 10000000.] are b0=0, b1=0 and b2=0.
+ bns = pcoh.persistent_betti_numbers(.1, 10000000.);
+ BOOST_CHECK(bns[0] == 0);
+ BOOST_CHECK(bns[1] == 0);
+ BOOST_CHECK(bns[2] == 0);
+
+ // Custom sort and output persistence
+ cmp_intervals_by_dim_then_length<Simplex_tree> cmp(&st);
+ auto persistent_pairs = pcoh.get_persistent_pairs();
+
+ std::sort(std::begin(persistent_pairs), std::end(persistent_pairs), cmp);
+
+ BOOST_CHECK(persistent_pairs.size() == 3);
+ // persistent_pairs[0] = 2 1 4 inf
+ BOOST_CHECK(st.dimension(get<0>(persistent_pairs[0])) == 1);
+ BOOST_CHECK(st.filtration(get<0>(persistent_pairs[0])) == 4);
+ BOOST_CHECK(get<1>(persistent_pairs[0]) == st.null_simplex());
+
+ // persistent_pairs[1] = 2 0 2 inf
+ BOOST_CHECK(st.dimension(get<0>(persistent_pairs[1])) == 0);
+ BOOST_CHECK(st.filtration(get<0>(persistent_pairs[1])) == 2);
+ BOOST_CHECK(get<1>(persistent_pairs[1]) == st.null_simplex());
+
+ // persistent_pairs[2] = 2 0 1 inf
+ BOOST_CHECK(st.dimension(get<0>(persistent_pairs[2])) == 0);
+ BOOST_CHECK(st.filtration(get<0>(persistent_pairs[2])) == 1);
+ BOOST_CHECK(get<1>(persistent_pairs[2]) == st.null_simplex());
+}
diff --git a/src/Persistent_cohomology/test/persistent_cohomology_unit_test.cpp b/src/Persistent_cohomology/test/persistent_cohomology_unit_test.cpp
index 194b3e74..6efd749e 100644
--- a/src/Persistent_cohomology/test/persistent_cohomology_unit_test.cpp
+++ b/src/Persistent_cohomology/test/persistent_cohomology_unit_test.cpp
@@ -4,6 +4,7 @@
#include <utility> // std::pair, std::make_pair
#include <cmath> // float comparison
#include <limits>
+#include <cstdint> // for std::uint8_t
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE "persistent_cohomology"
@@ -43,7 +44,7 @@ std::string test_rips_persistence(int coefficient, int min_persistence) {
st.initialize_filtration();
// Compute the persistence diagram of the complex
- persistent_cohomology::Persistent_cohomology<Simplex_tree<>, Field_Zp> pcoh(st);
+ Persistent_cohomology<Simplex_tree<>, Field_Zp> pcoh(st);
pcoh.init_coefficients( coefficient ); // initializes the coefficient field for homology
// Check infinite rips
@@ -172,3 +173,45 @@ BOOST_AUTO_TEST_CASE( rips_persistent_cohomology_single_field_dim_5 )
// std::string str_rips_persistence = test_rips_persistence(6, 0);
// TODO(VR): division by zero
// std::string str_rips_persistence = test_rips_persistence(0, 0);
+
+/** SimplexTree minimal options to test the limits.
+ *
+ * Maximum number of simplices to compute persistence is <CODE>std::numeric_limits<std::uint8_t>::max()<\CODE> = 256.*/
+struct MiniSTOptions {
+ typedef linear_indexing_tag Indexing_tag;
+ typedef short Vertex_handle;
+ typedef double Filtration_value;
+ // Maximum number of simplices to compute persistence is 2^8 - 1 = 255. One is reserved for null_key
+ typedef std::uint8_t Simplex_key;
+ static const bool store_key = true;
+ static const bool store_filtration = false;
+ static const bool contiguous_vertices = false;
+};
+
+using Mini_simplex_tree = Gudhi::Simplex_tree<MiniSTOptions>;
+using Mini_st_persistence =
+ Gudhi::persistent_cohomology::Persistent_cohomology<Mini_simplex_tree, Gudhi::persistent_cohomology::Field_Zp>;
+
+BOOST_AUTO_TEST_CASE( persistence_constructor_exception )
+{
+ Mini_simplex_tree st;
+
+ // To make number of simplices = 255
+ const short simplex_0[] = {0, 1, 2, 3, 4, 5, 6, 7};
+ st.insert_simplex_and_subfaces(simplex_0);
+ // FIXME: Remove this line
+ st.set_dimension(8);
+
+ // Sort the simplices in the order of the filtration
+ st.initialize_filtration();
+
+ BOOST_CHECK(st.num_simplices() <= std::numeric_limits<MiniSTOptions::Simplex_key>::max());
+ // Class for homology computation
+ BOOST_CHECK_NO_THROW(Mini_st_persistence pcoh(st));
+
+ st.insert_simplex({8});
+ BOOST_CHECK(st.num_simplices() > std::numeric_limits<MiniSTOptions::Simplex_key>::max());
+ // Class for homology computation
+ BOOST_CHECK_THROW(Mini_st_persistence pcoh2(st), std::out_of_range);
+
+}
diff --git a/src/Simplex_tree/concept/SimplexKey.h b/src/Simplex_tree/concept/SimplexKey.h
index 7fdbdd84..9fbed401 100644
--- a/src/Simplex_tree/concept/SimplexKey.h
+++ b/src/Simplex_tree/concept/SimplexKey.h
@@ -22,7 +22,7 @@
/** \brief Key type used as simplex identifier.
*
- * Must be a signed integer type.
+ * Must be an integer type.
*/
struct SimplexKey {};
diff --git a/src/Simplex_tree/concept/SimplexTreeOptions.h b/src/Simplex_tree/concept/SimplexTreeOptions.h
index a50a2bf1..89acdc18 100644
--- a/src/Simplex_tree/concept/SimplexTreeOptions.h
+++ b/src/Simplex_tree/concept/SimplexTreeOptions.h
@@ -31,11 +31,13 @@ struct SimplexTreeOptions {
typedef VertexHandle Vertex_handle;
/// Must be comparable with operator<.
typedef FiltrationValue Filtration_value;
- /// Must be a signed integer type.
+ /// Must be an integer type.
typedef SimplexKey Simplex_key;
/// If true, each simplex has extra storage for one `Simplex_key`. Necessary for `Persistent_cohomology`.
- static constexpr bool store_key;
- /// If true, each simplex has extra storage for one `Filtration_value`, and this value is propagated by operations like `Gudhi::Simplex_tree<SimplexTreeOptions>::expansion`. Without it, `Persistent_cohomology` degenerates to computing usual (non-persistent) cohomology.
- static constexpr bool store_filtration;
+ static const bool store_key;
+ /// If true, each simplex has extra storage for one `Filtration_value`, and this value is propagated by operations like `Gudhi::Simplex_tree::expansion`. Without it, `Persistent_cohomology` degenerates to computing usual (non-persistent) cohomology.
+ static const bool store_filtration;
+ /// If true, the list of vertices present in the complex must always be 0, ..., num_vertices-1, without any hole.
+ static constexpr bool contiguous_vertices;
};
diff --git a/src/Simplex_tree/doc/Intro_simplex_tree.h b/src/Simplex_tree/doc/Intro_simplex_tree.h
new file mode 100644
index 00000000..940dd694
--- /dev/null
+++ b/src/Simplex_tree/doc/Intro_simplex_tree.h
@@ -0,0 +1,85 @@
+/* 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
+ *
+ * Copyright (C) 2014 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 DOC_SIMPLEX_TREE_INTRO_SIMPLEX_TREE_H_
+#define DOC_SIMPLEX_TREE_INTRO_SIMPLEX_TREE_H_
+
+// needs namespace for Doxygen to link on classes
+namespace Gudhi {
+
+
+/** \defgroup simplex_tree Filtered Complexes
+ * @{
+ * \author Cl&eacute;ment Maria
+ *
+ * A simplicial complex \f$\mathbf{K}\f$ on a set of vertices \f$V = \{1, \cdots ,|V|\}\f$ is a collection of
+ * implices \f$\{\sigma\}\f$, \f$\sigma \subseteq V\f$ such that
+ * \f$\tau \subseteq \sigma \in \mathbf{K} \rightarrow \tau \in \mathbf{K}\f$. The dimension \f$n=|\sigma|-1\f$ of
+ * \f$\sigma\f$ is its number of elements minus \f$1\f$.
+ *
+ * A filtration of a simplicial complex is a function \f$f:\mathbf{K} \rightarrow \mathbb{R}\f$ satisfying
+ * \f$f(\tau)\leq f(\sigma)\f$ whenever \f$\tau \subseteq \sigma\f$. Ordering the simplices by increasing filtration
+ * values (breaking ties so as a simplex appears after its subsimplices of same filtration value) provides an
+ * indexing scheme.
+ *
+ * \section filteredcomplexesimplementation Implementations
+ * \subsection filteredcomplexessimplextree Simplex tree
+ * There are two implementation of complexes. The first on is the Simplex_tree data structure. The simplex tree is an
+ * efficient and flexible data structure for representing general (filtered) simplicial complexes. The data structure
+ * is described in \cite boissonnatmariasimplextreealgorithmica
+ * \image html "Simplex_tree_representation.png" "Simplex tree representation"
+ *
+ * \subsubsection filteredcomplexessimplextreeexamples Examples
+ *
+ * Here is a list of simplex tree examples :
+ * \li <a href="_simplex_tree_2simple_simplex_tree_8cpp-example.html">
+ * Simplex_tree/simple_simplex_tree.cpp</a> - Simple simplex tree construction and basic function use.
+ *
+ * \li <a href="_simplex_tree_2simplex_tree_from_cliques_of_graph_8cpp-example.html">
+ * Simplex_tree/simplex_tree_from_cliques_of_graph.cpp</a> - Simplex tree construction from cliques of graph read in
+ * a file.
+ *
+ * Simplex tree construction with \f$\mathbb{Z}/3\mathbb{Z}\f$ coefficients on weighted graph Klein bottle file:
+ * \code $> ./simplex_tree_from_cliques_of_graph ../../data/points/Klein_bottle_complex.txt 3 \endcode
+ * \code Insert the 1-skeleton in the simplex tree in 0.000404 s.
+max_dim = 3
+Expand the simplex tree in 3.8e-05 s.
+Information of the Simplex Tree:
+Number of vertices = 10 Number of simplices = 98 \endcode
+ *
+ * \li <a href="_simplex_tree_2example_alpha_shapes_3_simplex_tree_from_off_file_8cpp-example.html">
+ * Simplex_tree/example_alpha_shapes_3_simplex_tree_from_off_file.cpp</a> - Simplex tree is computed and displayed from a 3D alpha
+ * complex (Requires CGAL, GMP and GMPXX to be installed)
+ *
+ *
+ * \subsection filteredcomplexeshassecomplex Hasse complex
+ * The second one is the Hasse_complex. The Hasse complex is a data structure representing explicitly all co-dimension
+ * 1 incidence relations in a complex. It is consequently faster when accessing the boundary of a simplex, but is less
+ * compact and harder to construct from scratch.
+ *
+ * \copyright GNU General Public License v3.
+ * @}
+ */
+
+} // namespace Gudhi
+
+#endif // DOC_SIMPLEX_TREE_INTRO_SIMPLEX_TREE_H_
diff --git a/src/Simplex_tree/doc/Simplex_tree_representation.png b/src/Simplex_tree/doc/Simplex_tree_representation.png
new file mode 100644
index 00000000..9d401520
--- /dev/null
+++ b/src/Simplex_tree/doc/Simplex_tree_representation.png
Binary files differ
diff --git a/src/Simplex_tree/example/CMakeLists.txt b/src/Simplex_tree/example/CMakeLists.txt
index c70cfe35..e5285591 100644
--- a/src/Simplex_tree/example/CMakeLists.txt
+++ b/src/Simplex_tree/example/CMakeLists.txt
@@ -1,11 +1,19 @@
cmake_minimum_required(VERSION 2.6)
-project(GUDHISimplexTreeFromFile)
+project(Simplex_tree_examples)
add_executable ( simplex_tree_from_cliques_of_graph simplex_tree_from_cliques_of_graph.cpp )
-add_test(simplex_tree_from_cliques_of_graph_2 ${CMAKE_CURRENT_BINARY_DIR}/simplex_tree_from_cliques_of_graph ${CMAKE_SOURCE_DIR}/data/points/Klein_bottle_complex.txt 2)
-add_test(simplex_tree_from_cliques_of_graph_3 ${CMAKE_CURRENT_BINARY_DIR}/simplex_tree_from_cliques_of_graph ${CMAKE_SOURCE_DIR}/data/points/Klein_bottle_complex.txt 3)
+if (TBB_FOUND)
+ target_link_libraries(simplex_tree_from_cliques_of_graph ${TBB_LIBRARIES})
+endif()
+add_test(simplex_tree_from_cliques_of_graph_2 ${CMAKE_CURRENT_BINARY_DIR}/simplex_tree_from_cliques_of_graph
+ ${CMAKE_SOURCE_DIR}/data/filtered_simplicial_complex/Klein_bottle_complex.fsc 2)
+add_test(simplex_tree_from_cliques_of_graph_3 ${CMAKE_CURRENT_BINARY_DIR}/simplex_tree_from_cliques_of_graph
+ ${CMAKE_SOURCE_DIR}/data/filtered_simplicial_complex/Klein_bottle_complex.fsc 3)
add_executable ( simple_simplex_tree simple_simplex_tree.cpp )
+if (TBB_FOUND)
+ target_link_libraries(simple_simplex_tree ${TBB_LIBRARIES})
+endif()
add_test(simple_simplex_tree ${CMAKE_CURRENT_BINARY_DIR}/simple_simplex_tree)
add_executable ( mini_simplex_tree mini_simplex_tree.cpp )
@@ -14,11 +22,12 @@ add_test(mini_simplex_tree ${CMAKE_CURRENT_BINARY_DIR}/mini_simplex_tree)
# An example with Simplex-tree using CGAL alpha_shapes_3
if(GMP_FOUND AND CGAL_FOUND)
- message("CGAL_lib = ${CGAL_LIBRARIES_DIR}")
- message("GMP_LIBRARIES = ${GMP_LIBRARIES}")
- INCLUDE_DIRECTORIES(${GMP_INCLUDE_DIR})
- INCLUDE_DIRECTORIES(${CGAL_INCLUDE_DIRS})
- add_executable ( simplex_tree_from_alpha_shapes_3 simplex_tree_from_alpha_shapes_3.cpp )
- target_link_libraries(simplex_tree_from_alpha_shapes_3 ${GMP_LIBRARIES} ${CGAL_LIBRARY})
- add_test(simplex_tree_from_alpha_shapes_3 ${CMAKE_CURRENT_BINARY_DIR}/simplex_tree_from_alpha_shapes_3 ${CMAKE_SOURCE_DIR}/data/points/bunny_5000)
+ add_executable ( alpha_shapes_3_simplex_tree_from_off_file example_alpha_shapes_3_simplex_tree_from_off_file.cpp )
+ target_link_libraries(alpha_shapes_3_simplex_tree_from_off_file ${GMP_LIBRARIES} ${CGAL_LIBRARY} ${Boost_SYSTEM_LIBRARY})
+ if (TBB_FOUND)
+ target_link_libraries(alpha_shapes_3_simplex_tree_from_off_file ${TBB_LIBRARIES})
+ endif()
+ add_test(alpha_shapes_3_simplex_tree_from_off_file
+ ${CMAKE_CURRENT_BINARY_DIR}/alpha_shapes_3_simplex_tree_from_off_file
+ ${CMAKE_SOURCE_DIR}/data/points/bunny_5000.off)
endif()
diff --git a/src/Simplex_tree/example/README b/src/Simplex_tree/example/README
index 03c759cb..e37af790 100644
--- a/src/Simplex_tree/example/README
+++ b/src/Simplex_tree/example/README
@@ -52,7 +52,7 @@ EXAMPLE OF SIMPLE INSERTION
*** Simplex tree construction with Z/2Z coefficients on weighted graph Klein bottle file:
-./simplex_tree_from_file ../../../data/points/Klein_bottle_complex.txt 2
+./simplex_tree_from_cliques_of_graph ../../../data/points/Klein_bottle_complex.txt 2
Insert the 1-skeleton in the simplex tree in 0 s.
Expand the simplex tree in 0 s.
Information of the Simplex Tree:
@@ -60,7 +60,7 @@ Information of the Simplex Tree:
with Z/3Z coefficients:
-./simplex_tree_from_file ../../../data/points/Klein_bottle_complex.txt 3
+./simplex_tree_from_cliques_of_graph ../../../data/points/Klein_bottle_complex.txt 3
Insert the 1-skeleton in the simplex tree in 0 s.
Expand the simplex tree in 0 s.
diff --git a/src/Simplex_tree/example/simplex_tree_from_alpha_shapes_3.cpp b/src/Simplex_tree/example/example_alpha_shapes_3_simplex_tree_from_off_file.cpp
index 45efe3ed..ff2eebcb 100644
--- a/src/Simplex_tree/example/simplex_tree_from_alpha_shapes_3.cpp
+++ b/src/Simplex_tree/example/example_alpha_shapes_3_simplex_tree_from_off_file.cpp
@@ -20,8 +20,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <gudhi/graph_simplicial_complex.h>
#include <gudhi/Simplex_tree.h>
+#include <gudhi/Points_3D_off_io.h>
+
#include <boost/variant.hpp>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
@@ -62,7 +63,8 @@ typedef Alpha_shape_3::Edge Edge;
typedef std::list<Alpha_shape_3::Vertex_handle> Vertex_list;
// gudhi type definition
-typedef Gudhi::Simplex_tree<>::Vertex_handle Simplex_tree_vertex;
+typedef Gudhi::Simplex_tree<> Simplex_tree;
+typedef Simplex_tree::Vertex_handle Simplex_tree_vertex;
typedef std::map<Alpha_shape_3::Vertex_handle, Simplex_tree_vertex > Alpha_shape_simplex_tree_map;
typedef std::pair<Alpha_shape_3::Vertex_handle, Simplex_tree_vertex> Alpha_shape_simplex_tree_pair;
typedef std::vector< Simplex_tree_vertex > Simplex_tree_vector_vertex;
@@ -117,24 +119,21 @@ int main(int argc, char * const argv[]) {
// program args management
if (argc != 2) {
std::cerr << "Usage: " << argv[0]
- << " path_to_file_graph \n";
+ << " path_to_off_file \n";
return 0;
}
// Read points from file
- std::string filegraph = argv[1];
- std::list<Point> lp;
- std::ifstream is(filegraph.c_str());
- int n;
- is >> n;
-#ifdef DEBUG_TRACES
- std::cout << "Reading " << n << " points " << std::endl;
-#endif // DEBUG_TRACES
- Point p;
- for (; n > 0; n--) {
- is >> p;
- lp.push_back(p);
+ std::string offInputFile(argv[1]);
+ // Read the OFF file (input file name given as parameter) and triangulate points
+ Gudhi::Points_3D_off_reader<Point> off_reader(offInputFile);
+ // Check the read operation was correct
+ if (!off_reader.is_valid()) {
+ std::cerr << "Unable to read file " << argv[1] << std::endl;
+ return 0;
}
+ // Retrieve the triangulation
+ std::vector<Point> lp = off_reader.get_point_cloud();
// alpha shape construction from points. CGAL has a strange behavior in REGULARIZED mode.
Alpha_shape_3 as(lp.begin(), lp.end(), 0, Alpha_shape_3::GENERAL);
@@ -161,7 +160,7 @@ int main(int argc, char * const argv[]) {
// Loop on objects vector
Vertex_list vertex_list;
- Gudhi::Simplex_tree<> simplex_tree;
+ Simplex_tree simplex_tree;
Alpha_shape_simplex_tree_map map_cgal_simplex_tree;
std::vector<Alpha_value_type>::iterator the_alpha_value_iterator = the_alpha_values.begin();
for (auto object_iterator : the_objects) {
diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h
index 4c6a95e8..63e3f0e5 100644
--- a/src/Simplex_tree/include/gudhi/Simplex_tree.h
+++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h
@@ -30,64 +30,32 @@
#include <gudhi/reader_utils.h>
#include <gudhi/graph_simplicial_complex.h>
+#include <gudhi/Debug_utils.h>
#include <boost/container/flat_map.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/graph/adjacency_list.hpp>
+#include <boost/range/adaptor/reversed.hpp>
+
+#ifdef GUDHI_USE_TBB
+#include <tbb/parallel_sort.h>
+#endif
-#include <algorithm>
#include <utility>
#include <vector>
#include <functional> // for greater<>
+#include <stdexcept>
+#include <limits> // Inf
+#include <initializer_list>
+#include <algorithm> // for std::max
+#include <cstdint> // for std::uint32_t
namespace Gudhi {
-/** \defgroup simplex_tree Filtered Complexes
- *
- * A simplicial complex \f$\mathbf{K}\f$
- * on a set of vertices \f$V = \{1, \cdots ,|V|\}\f$ is a collection of simplices
- * \f$\{\sigma\}\f$,
- * \f$\sigma \subseteq V\f$ such that \f$\tau \subseteq \sigma \in \mathbf{K} \rightarrow \tau \in
- * \mathbf{K}\f$. The
- * dimension \f$n=|\sigma|-1\f$ of \f$\sigma\f$ is its number of elements minus \f$1\f$.
- *
- * A filtration of a simplicial complex is
- * a function \f$f:\mathbf{K} \rightarrow \mathbb{R}\f$ satisfying \f$f(\tau)\leq f(\sigma)\f$ whenever
- * \f$\tau \subseteq \sigma\f$. Ordering the simplices by increasing filtration values
- * (breaking ties so as a simplex appears after its subsimplices of same filtration value)
- * provides an indexing scheme.
- *
-
- <DT>Implementations:</DT>
- There are two implementation of complexes. The first on is the Simplex_tree data structure.
- The simplex tree is an efficient and flexible
- data structure for representing general (filtered) simplicial complexes. The data structure
- is described in \cite boissonnatmariasimplextreealgorithmica
-
- The second one is the Hasse_complex. The Hasse complex is a data structure representing
- explicitly all co-dimension 1 incidence relations in a complex. It is consequently faster
- when accessing the boundary of a simplex, but is less compact and harder to construct from
- scratch.
-
-
- * \author Clément Maria
- * \version 1.0
- * \date 2014
- * \copyright GNU General Public License v3.
- * @{
- */
-
-/// Model of SimplexTreeOptions.
-struct Simplex_tree_options_full_featured {
- typedef linear_indexing_tag Indexing_tag;
- typedef int Vertex_handle;
- typedef double Filtration_value;
- typedef int Simplex_key;
- static const bool store_key = true;
- static const bool store_filtration = true;
-};
+struct Simplex_tree_options_full_featured;
/**
+ * \class Simplex_tree Simplex_tree.h gudhi/Simplex_tree.h
* \brief Simplex Tree data structure for representing simplicial complexes.
*
* \details Every simplex \f$[v_0, \cdots ,v_d]\f$ admits a canonical orientation
@@ -110,7 +78,7 @@ class Simplex_tree {
typedef typename Options::Filtration_value Filtration_value;
/** \brief Key associated to each simplex.
*
- * Must be a signed integer type. */
+ * Must be an integer type. */
typedef typename Options::Simplex_key Simplex_key;
/** \brief Type for the vertex handle.
*
@@ -141,7 +109,8 @@ class Simplex_tree {
void assign_key(Simplex_key) { }
Simplex_key key() const { assert(false); return -1; }
};
- typedef typename std::conditional<Options::store_key, Key_simplex_base_real, Key_simplex_base_dummy>::type Key_simplex_base;
+ typedef typename std::conditional<Options::store_key, Key_simplex_base_real, Key_simplex_base_dummy>::type
+ Key_simplex_base;
struct Filtration_simplex_base_real {
Filtration_simplex_base_real() : filt_(0) {}
@@ -307,7 +276,8 @@ class Simplex_tree {
* of the simplex.
*
* @param[in] sh Simplex for which the boundary is computed. */
- Boundary_simplex_range boundary_simplex_range(Simplex_handle sh) {
+ template<class SimplexHandle>
+ Boundary_simplex_range boundary_simplex_range(SimplexHandle sh) {
return Boundary_simplex_range(Boundary_simplex_iterator(this, sh),
Boundary_simplex_iterator(this));
}
@@ -328,11 +298,10 @@ class Simplex_tree {
Simplex_tree(const Simplex_tree& simplex_source)
: null_vertex_(simplex_source.null_vertex_),
threshold_(simplex_source.threshold_),
+ root_(nullptr, null_vertex_ , simplex_source.root_.members_),
filtration_vect_(),
dimension_(simplex_source.dimension_) {
auto root_source = simplex_source.root_;
- auto memb_source = root_source.members();
- root_ = Siblings(nullptr, null_vertex_, memb_source);
rec_copy(&root_, &root_source);
}
@@ -344,7 +313,7 @@ class Simplex_tree {
Siblings * newsib = new Siblings(sib, sh_source->first);
newsib->members_.reserve(sh_source->second.children()->members().size());
for (auto & child : sh_source->second.children()->members())
- newsib->members_.emplace_hint(newsib->members_.end(), child.first, Node(sib, child.second.filtration()));
+ newsib->members_.emplace_hint(newsib->members_.end(), child.first, Node(newsib, child.second.filtration()));
rec_copy(newsib, sh_source->second.children());
sh->second.assign_children(newsib);
}
@@ -449,6 +418,15 @@ class Simplex_tree {
}
}
+ /** \brief Sets the filtration value of a simplex.
+ * \exception std::invalid_argument In debug mode, if sh is a null_simplex.
+ */
+ void assign_filtration(Simplex_handle sh, Filtration_value fv) {
+ GUDHI_CHECK(sh != null_simplex(),
+ std::invalid_argument("Simplex_tree::assign_filtration - cannot assign filtration on null_simplex"));
+ sh->second.assign_filtration(fv);
+ }
+
/** \brief Returns an upper bound of the filtration values of the simplices. */
Filtration_value filtration() const {
return threshold_;
@@ -518,9 +496,10 @@ class Simplex_tree {
return dimension_;
}
- /** \brief Returns true iff the node in the simplex tree pointed by
+ /** \brief Returns true if the node in the simplex tree pointed by
* sh has children.*/
- bool has_children(Simplex_handle sh) const {
+ template<class SimplexHandle>
+ bool has_children(SimplexHandle sh) const {
return (sh->second.children()->parent() == sh->first);
}
@@ -531,7 +510,7 @@ class Simplex_tree {
* The type InputVertexRange must be a range of <CODE>Vertex_handle</CODE>
* on which we can call std::begin() function
*/
- template<class InputVertexRange>
+ template<class InputVertexRange = std::initializer_list<Vertex_handle>>
Simplex_handle find(const InputVertexRange & s) {
auto first = std::begin(s);
auto last = std::end(s);
@@ -567,13 +546,38 @@ class Simplex_tree {
/** \brief Returns the Simplex_handle corresponding to the 0-simplex
* representing the vertex with Vertex_handle v. */
Simplex_handle find_vertex(Vertex_handle v) {
- return root_.members_.begin() + v;
+ if (Options::contiguous_vertices) {
+ assert(contiguous_vertices());
+ return root_.members_.begin() + v;
+ } else {
+ return root_.members_.find(v);
+ }
+ }
+
+ public:
+ /** \private \brief Test if the vertices have contiguous numbering: 0, 1, etc. */
+ bool contiguous_vertices() const {
+ if (root_.members_.empty()) return true;
+ if (root_.members_.begin()->first != 0) return false;
+ if (std::prev(root_.members_.end())->first != static_cast<Vertex_handle>(root_.members_.size() - 1)) return false;
+ return true;
}
- //{ return root_.members_.find(v); }
private:
/** \brief Inserts a simplex represented by a vector of vertex.
- \warning the vector must be sorted by increasing vertex handle order */
+ * @param[in] simplex vector of Vertex_handles, representing the vertices of the new simplex. The vector must be
+ * sorted by increasing vertex handle order.
+ * @param[in] filtration the filtration value assigned to the new simplex.
+ * @return If the new simplex is inserted successfully (i.e. it was not in the
+ * simplicial complex yet) the bool is set to true and the Simplex_handle is the handle assigned
+ * to the new simplex.
+ * If the insertion fails (the simplex is already there), the bool is set to false. If the insertion
+ * fails and the simplex already in the complex has a filtration value strictly bigger than 'filtration',
+ * we assign this simplex with the new value 'filtration', and set the Simplex_handle field of the
+ * output pair to the Simplex_handle of the simplex. Otherwise, we set the Simplex_handle part to
+ * null_simplex.
+ *
+ */
std::pair<Simplex_handle, bool> insert_vertex_vector(const std::vector<Vertex_handle>& simplex,
Filtration_value filtration) {
Siblings * curr_sib = &root_;
@@ -606,7 +610,7 @@ class Simplex_tree {
*
* @param[in] simplex range of Vertex_handles, representing the vertices of the new simplex
* @param[in] filtration the filtration value assigned to the new simplex.
- * The return type is a pair. If the new simplex is inserted successfully (i.e. it was not in the
+ * @return If the new simplex is inserted successfully (i.e. it was not in the
* simplicial complex yet) the bool is set to true and the Simplex_handle is the handle assigned
* to the new simplex.
* If the insertion fails (the simplex is already there), the bool is set to false. If the insertion
@@ -625,7 +629,7 @@ class Simplex_tree {
*
* The type InputVertexRange must be a range for which .begin() and
* .end() return input iterators, with 'value_type' Vertex_handle. */
- template<class InputVertexRange>
+ template<class InputVertexRange = std::initializer_list<Vertex_handle>>
std::pair<Simplex_handle, bool> insert_simplex(const InputVertexRange & simplex,
Filtration_value filtration = 0) {
auto first = std::begin(simplex);
@@ -645,7 +649,7 @@ class Simplex_tree {
*
* @param[in] Nsimplex range of Vertex_handles, representing the vertices of the new N-simplex
* @param[in] filtration the filtration value assigned to the new N-simplex.
- * The return type is a pair. If the new simplex is inserted successfully (i.e. it was not in the
+ * @return If the new simplex is inserted successfully (i.e. it was not in the
* simplicial complex yet) the bool is set to true and the Simplex_handle is the handle assigned
* to the new simplex.
* If the insertion fails (the simplex is already there), the bool is set to false. If the insertion
@@ -654,7 +658,7 @@ class Simplex_tree {
* output pair to the Simplex_handle of the simplex. Otherwise, we set the Simplex_handle part to
* null_simplex.
*/
- template<class InputVertexRange>
+ template<class InputVertexRange = std::initializer_list<Vertex_handle>>
std::pair<Simplex_handle, bool> insert_simplex_and_subfaces(const InputVertexRange& Nsimplex,
Filtration_value filtration = 0) {
auto first = std::begin(Nsimplex);
@@ -708,7 +712,7 @@ class Simplex_tree {
} else if (the_simplex.size() == 1) {
// When reaching the end of recursivity, vector of simplices shall be empty and filled on back recursive
if ((to_be_inserted.size() != 0) || (to_be_propagated.size() != 0)) {
- std::cerr << "Simplex_tree::rec_insert_simplex_and_subfaces - Error vector not empty" << std::endl;
+ std::cerr << "Simplex_tree::rec_insert_simplex_and_subfaces - Error vector not empty\n";
exit(-1);
}
std::vector<Vertex_handle> first_simplex(1, the_simplex.back());
@@ -717,7 +721,7 @@ class Simplex_tree {
insert_result = insert_vertex_vector(first_simplex, filtration);
} else {
- std::cerr << "Simplex_tree::rec_insert_simplex_and_subfaces - Recursivity error" << std::endl;
+ std::cerr << "Simplex_tree::rec_insert_simplex_and_subfaces - Recursivity error\n";
exit(-1);
}
return insert_result;
@@ -730,7 +734,6 @@ class Simplex_tree {
sh->second.assign_key(key);
}
- public:
/** Returns the two Simplex_handle corresponding to the endpoints of
* and edge. sh must point to a 1-dimensional simplex. This is an
* optimized version of the boundary computation. */
@@ -740,7 +743,8 @@ class Simplex_tree {
}
/** Returns the Siblings containing a simplex.*/
- Siblings * self_siblings(Simplex_handle sh) {
+ template<class SimplexHandle>
+ Siblings* self_siblings(SimplexHandle sh) {
if (sh->second.children()->parent() == sh->first)
return sh->second.children()->oncles();
else
@@ -788,8 +792,11 @@ class Simplex_tree {
* heuristic consists in inserting the cofaces of a simplex as soon as
* possible.
*/
- std::stable_sort(filtration_vect_.begin(), filtration_vect_.end(),
- is_before_in_filtration(this));
+#ifdef GUDHI_USE_TBB
+ tbb::parallel_sort(filtration_vect_.begin(), filtration_vect_.end(), is_before_in_filtration(this));
+#else
+ std::stable_sort(filtration_vect_.begin(), filtration_vect_.end(), is_before_in_filtration(this));
+#endif
}
private:
@@ -915,7 +922,7 @@ class Simplex_tree {
bool operator()(const Simplex_handle sh1, const Simplex_handle sh2) const {
// Not using st_->filtration(sh1) because it uselessly tests for null_simplex.
if (sh1->second.filtration() != sh2->second.filtration()) {
- return sh1->second.filtration() < sh2->second.filtration();
+ return sh1->second.filtration() < sh2->second.filtration();
}
// is sh1 a proper subface of sh2
return st_->reverse_lexicographic_order(sh1, sh2);
@@ -1092,6 +1099,120 @@ class Simplex_tree {
}
}
+ public:
+ /** \brief Browse the simplex tree to ensure the filtration is not decreasing.
+ * The simplex tree is browsed starting from the root until the leaf, and the filtration values are set with their
+ * parent value (increased), in case the values are decreasing.
+ * @return The filtration modification information.
+ * \post Some simplex tree functions require the filtration to be valid. `make_filtration_non_decreasing()`
+ * function is not launching `initialize_filtration()` but returns the filtration modification information. If the
+ * complex has changed , please call `initialize_filtration()` to recompute it.
+ */
+ bool make_filtration_non_decreasing() {
+ bool modified = false;
+ // Loop must be from the end to the beginning, as higher dimension simplex are always on the left part of the tree
+ for (auto& simplex : boost::adaptors::reverse(root_.members())) {
+ if (has_children(&simplex)) {
+ modified |= rec_make_filtration_non_decreasing(simplex.second.children());
+ }
+ }
+ return modified;
+ }
+
+ private:
+ /** \brief Recursively Browse the simplex tree to ensure the filtration is not decreasing.
+ * @param[in] sib Siblings to be parsed.
+ * @return The filtration modification information in order to trigger initialize_filtration.
+ */
+ bool rec_make_filtration_non_decreasing(Siblings * sib) {
+ bool modified = false;
+
+ // Loop must be from the end to the beginning, as higher dimension simplex are always on the left part of the tree
+ for (auto& simplex : boost::adaptors::reverse(sib->members())) {
+ // Find the maximum filtration value in the border
+ Boundary_simplex_range boundary = boundary_simplex_range(&simplex);
+ Boundary_simplex_iterator max_border = std::max_element(std::begin(boundary), std::end(boundary),
+ [](Simplex_handle sh1, Simplex_handle sh2) {
+ return filtration(sh1) < filtration(sh2);
+ });
+
+ Filtration_value max_filt_border_value = filtration(*max_border);
+ if (simplex.second.filtration() < max_filt_border_value) {
+ // Store the filtration modification information
+ modified = true;
+ simplex.second.assign_filtration(max_filt_border_value);
+ }
+ if (has_children(&simplex)) {
+ modified |= rec_make_filtration_non_decreasing(simplex.second.children());
+ }
+ }
+ // Make the modified information to be traced by upper call
+ return modified;
+ }
+
+ public:
+ /** \brief Prune above filtration value given as parameter.
+ * @param[in] filtration Maximum threshold value.
+ * @return The filtration modification information.
+ * \post Some simplex tree functions require the filtration to be valid. `prune_above_filtration()`
+ * function is not launching `initialize_filtration()` but returns the filtration modification information. If the
+ * complex has changed , please call `initialize_filtration()` to recompute it.
+ */
+ bool prune_above_filtration(Filtration_value filtration) {
+ return rec_prune_above_filtration(root(), filtration);
+ }
+
+ private:
+ bool rec_prune_above_filtration(Siblings* sib, Filtration_value filt) {
+ auto&& list = sib->members();
+ auto last = std::remove_if(list.begin(), list.end(), [=](Dit_value_t& simplex) {
+ if (simplex.second.filtration() <= filt) return false;
+ if (has_children(&simplex)) rec_delete(simplex.second.children());
+ return true;
+ });
+
+ bool modified = (last != list.end());
+ if (last == list.begin() && sib != root()) {
+ // Removing the whole siblings, parent becomes a leaf.
+ sib->oncles()->members()[sib->parent()].assign_children(sib->oncles());
+ delete sib;
+ return true;
+ } else {
+ // Keeping some elements of siblings. Remove the others, and recurse in the remaining ones.
+ list.erase(last, list.end());
+ for (auto&& simplex : list)
+ if (has_children(&simplex))
+ modified |= rec_prune_above_filtration(simplex.second.children(), filt);
+ }
+ return modified;
+ }
+
+ public:
+ /** \brief Remove a maximal simplex.
+ * @param[in] sh Simplex handle on the maximal simplex to remove.
+ * \pre Please check the simplex has no coface before removing it.
+ * \exception std::invalid_argument In debug mode, if sh has children.
+ * \post Be aware that removing is shifting data in a flat_map (initialize_filtration to be done).
+ */
+ void remove_maximal_simplex(Simplex_handle sh) {
+ // Guarantee the simplex has no children
+ GUDHI_CHECK(!has_children(sh),
+ std::invalid_argument("Simplex_tree::remove_maximal_simplex - argument has children"));
+
+ // Simplex is a leaf, it means the child is the Siblings owning the leaf
+ Siblings* child = sh->second.children();
+
+ if ((child->size() > 1) || (child == root())) {
+ // Not alone, just remove it from members
+ // Special case when child is the root of the simplex tree, just remove it from members
+ child->erase(sh);
+ } else {
+ // Sibling is emptied : must be deleted, and its parent must point on his own Sibling
+ child->oncles()->members().at(child->parent()).assign_children(child->oncles());
+ delete child;
+ }
+ }
+
private:
Vertex_handle null_vertex_;
/** \brief Upper bound on the filtration values of the simplices.*/
@@ -1106,7 +1227,6 @@ class Simplex_tree {
};
// Print a Simplex_tree in os.
-
template<typename...T>
std::ostream& operator<<(std::ostream & os, Simplex_tree<T...> & st) {
for (auto sh : st.filtration_simplex_range()) {
@@ -1145,6 +1265,37 @@ std::istream& operator>>(std::istream & is, Simplex_tree<T...> & st) {
return is;
}
+
+/** Model of SimplexTreeOptions.
+ *
+ * Maximum number of simplices to compute persistence is <CODE>std::numeric_limits<std::uint32_t>::max()</CODE>
+ * (about 4 billions of simplices). */
+struct Simplex_tree_options_full_featured {
+ typedef linear_indexing_tag Indexing_tag;
+ typedef int Vertex_handle;
+ typedef double Filtration_value;
+ typedef std::uint32_t Simplex_key;
+ static const bool store_key = true;
+ static const bool store_filtration = true;
+ static const bool contiguous_vertices = false;
+};
+
+/** Model of SimplexTreeOptions, faster than `Simplex_tree_options_full_featured` but note the unsafe
+ * `contiguous_vertices` option.
+ *
+ * Maximum number of simplices to compute persistence is <CODE>std::numeric_limits<std::uint32_t>::max()</CODE>
+ * (about 4 billions of simplices). */
+
+struct Simplex_tree_options_fast_persistence {
+ typedef linear_indexing_tag Indexing_tag;
+ typedef int Vertex_handle;
+ typedef float Filtration_value;
+ typedef std::uint32_t Simplex_key;
+ static const bool store_key = true;
+ static const bool store_filtration = true;
+ static const bool contiguous_vertices = true;
+};
+
/** @} */ // end defgroup simplex_tree
} // namespace Gudhi
diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_iterators.h b/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_iterators.h
index 372ef329..7e0a454d 100644
--- a/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_iterators.h
+++ b/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_iterators.h
@@ -54,7 +54,7 @@ class Simplex_tree_simplex_vertex_iterator : public boost::iterator_facade<
explicit Simplex_tree_simplex_vertex_iterator(SimplexTree * st)
: // any end() iterator
- sib_(NULL),
+ sib_(nullptr),
v_(st->null_vertex()) {
}
@@ -99,21 +99,23 @@ class Simplex_tree_boundary_simplex_iterator : public boost::iterator_facade<
// any end() iterator
explicit Simplex_tree_boundary_simplex_iterator(SimplexTree * st)
- : last_(st->null_vertex()),
- sib_(NULL) {
+ : sib_(nullptr),
+ sh_(st->null_simplex()),
+ st_(st) {
}
- Simplex_tree_boundary_simplex_iterator(SimplexTree * st, Simplex_handle sh)
- : suffix_(),
+ template<class SimplexHandle>
+ Simplex_tree_boundary_simplex_iterator(SimplexTree * st, SimplexHandle sh)
+ : last_(sh->first),
+ sib_(nullptr),
st_(st) {
- last_ = sh->first;
Siblings * sib = st->self_siblings(sh);
next_ = sib->parent();
- sib_ = sib->oncles(); /* \todo check if NULL*/
- if (sib_ != NULL) {
+ sib_ = sib->oncles();
+ if (sib_ != nullptr) {
sh_ = sib_->find(next_);
} else {
- last_ = st->null_vertex();
+ sh_ = st->null_simplex();
} // vertex: == end()
}
@@ -121,28 +123,40 @@ class Simplex_tree_boundary_simplex_iterator : public boost::iterator_facade<
friend class boost::iterator_core_access;
// valid when iterating along the SAME boundary.
bool equal(Simplex_tree_boundary_simplex_iterator const& other) const {
- return (sib_ == other.sib_ && last_ == other.last_);
+ return sh_ == other.sh_;
}
Simplex_handle const& dereference() const {
+ assert(sh_ != st_->null_simplex());
return sh_;
}
void increment() {
- if (sib_ == NULL) {
- last_ = st_->null_vertex();
+ if (sib_ == nullptr) {
+ sh_ = st_->null_simplex();
return;
}
Siblings * for_sib = sib_;
- for (auto rit = suffix_.rbegin(); rit != suffix_.rend(); ++rit) {
+ Siblings * new_sib = sib_->oncles();
+ auto rit = suffix_.rbegin();
+ if (SimplexTree::Options::contiguous_vertices && new_sib == nullptr && rit != suffix_.rend()) {
+ // We reached the root, use a short-cut to find a vertex. We could also
+ // optimize finding the second vertex of a segment, but people are
+ // expected to call endpoints().
+ assert(st_->contiguous_vertices());
+ sh_ = for_sib->members_.begin()+*rit;
+ for_sib = sh_->second.children();
+ ++rit;
+ }
+ for (; rit != suffix_.rend(); ++rit) {
sh_ = for_sib->find(*rit);
for_sib = sh_->second.children();
}
sh_ = for_sib->find(last_); // sh_ points to the right simplex now
suffix_.push_back(next_);
next_ = sib_->parent();
- sib_ = sib_->oncles();
+ sib_ = new_sib;
}
// Most of the storage should be moved to the range, iterators should be light.
@@ -176,13 +190,15 @@ class Simplex_tree_complex_simplex_iterator : public boost::iterator_facade<
// any end() iterator
Simplex_tree_complex_simplex_iterator()
- : st_(NULL) {
+ : sib_(nullptr),
+ st_(nullptr) {
}
explicit Simplex_tree_complex_simplex_iterator(SimplexTree * st)
- : st_(st) {
- if (st == NULL || st->root() == NULL || st->root()->members().empty()) {
- st_ = NULL;
+ : sib_(nullptr),
+ st_(st) {
+ if (st == nullptr || st->root() == nullptr || st->root()->members().empty()) {
+ st_ = nullptr;
} else {
sh_ = st->root()->members().begin();
sib_ = st->root();
@@ -197,10 +213,10 @@ class Simplex_tree_complex_simplex_iterator : public boost::iterator_facade<
// valid when iterating along the SAME boundary.
bool equal(Simplex_tree_complex_simplex_iterator const& other) const {
- if (other.st_ == NULL) {
- return (st_ == NULL);
+ if (other.st_ == nullptr) {
+ return (st_ == nullptr);
}
- if (st_ == NULL) {
+ if (st_ == nullptr) {
return false;
}
return (&(sh_->second) == &(other.sh_->second));
@@ -214,8 +230,8 @@ class Simplex_tree_complex_simplex_iterator : public boost::iterator_facade<
void increment() {
++sh_;
if (sh_ == sib_->members().end()) {
- if (sib_->oncles() == NULL) {
- st_ = NULL;
+ if (sib_->oncles() == nullptr) {
+ st_ = nullptr;
return;
} // reach the end
sh_ = sib_->oncles()->members().find(sib_->parent());
@@ -248,15 +264,19 @@ class Simplex_tree_skeleton_simplex_iterator : public boost::iterator_facade<
// any end() iterator
Simplex_tree_skeleton_simplex_iterator()
- : st_(NULL) {
+ : sib_(nullptr),
+ st_(nullptr),
+ dim_skel_(0),
+ curr_dim_(0) {
}
Simplex_tree_skeleton_simplex_iterator(SimplexTree * st, int dim_skel)
- : st_(st),
+ : sib_(nullptr),
+ st_(st),
dim_skel_(dim_skel),
curr_dim_(0) {
- if (st == NULL || st->root() == NULL || st->root()->members().empty()) {
- st_ = NULL;
+ if (st == nullptr || st->root() == nullptr || st->root()->members().empty()) {
+ st_ = nullptr;
} else {
sh_ = st->root()->members().begin();
sib_ = st->root();
@@ -272,10 +292,10 @@ class Simplex_tree_skeleton_simplex_iterator : public boost::iterator_facade<
// valid when iterating along the SAME boundary.
bool equal(Simplex_tree_skeleton_simplex_iterator const& other) const {
- if (other.st_ == NULL) {
- return (st_ == NULL);
+ if (other.st_ == nullptr) {
+ return (st_ == nullptr);
}
- if (st_ == NULL) {
+ if (st_ == nullptr) {
return false;
}
return (&(sh_->second) == &(other.sh_->second));
@@ -289,8 +309,8 @@ class Simplex_tree_skeleton_simplex_iterator : public boost::iterator_facade<
void increment() {
++sh_;
if (sh_ == sib_->members().end()) {
- if (sib_->oncles() == NULL) {
- st_ = NULL;
+ if (sib_->oncles() == nullptr) {
+ st_ = nullptr;
return;
} // reach the end
sh_ = sib_->oncles()->members().find(sib_->parent());
diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_siblings.h b/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_siblings.h
index 158ee1f7..1eca7f6f 100644
--- a/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_siblings.h
+++ b/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_siblings.h
@@ -57,7 +57,7 @@ class Simplex_tree_siblings {
/* Default constructor.*/
Simplex_tree_siblings()
- : oncles_(NULL),
+ : oncles_(nullptr),
parent_(-1),
members_() {
}
@@ -116,6 +116,10 @@ class Simplex_tree_siblings {
return members_.size();
}
+ void erase(const Dictionary_it iterator) {
+ members_.erase(iterator);
+ }
+
Simplex_tree_siblings * oncles_;
Vertex_handle parent_;
Dictionary members_;
diff --git a/src/Simplex_tree/test/CMakeLists.txt b/src/Simplex_tree/test/CMakeLists.txt
index c9eae163..e95d0782 100644
--- a/src/Simplex_tree/test/CMakeLists.txt
+++ b/src/Simplex_tree/test/CMakeLists.txt
@@ -1,21 +1,20 @@
cmake_minimum_required(VERSION 2.6)
-project(GUDHISimplexTreeUT)
+project(Simplex_tree_tests)
if (GCOVR_PATH)
# for gcovr to make coverage reports - Corbera Jenkins plugin
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
- set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fprofile-arcs -ftest-coverage")
- set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fprofile-arcs -ftest-coverage")
endif()
if (GPROF_PATH)
# for gprof to make coverage reports - Jenkins
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg")
- set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pg")
- set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pg")
endif()
add_executable ( SimplexTreeUT simplex_tree_unit_test.cpp )
target_link_libraries(SimplexTreeUT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+if (TBB_FOUND)
+ target_link_libraries(SimplexTreeUT ${TBB_LIBRARIES})
+endif()
# Do not forget to copy test files in current binary dir
file(COPY "simplex_tree_for_unit_test.txt" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
diff --git a/src/Simplex_tree/test/simplex_tree_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_unit_test.cpp
index fff00d77..28bf202b 100644
--- a/src/Simplex_tree/test/simplex_tree_unit_test.cpp
+++ b/src/Simplex_tree/test/simplex_tree_unit_test.cpp
@@ -4,10 +4,12 @@
#include <utility> // std::pair, std::make_pair
#include <cmath> // float comparison
#include <limits>
+#include <functional> // greater
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE "simplex_tree"
#include <boost/test/unit_test.hpp>
+#include <boost/mpl/list.hpp>
// ^
// /!\ Nothing else from Simplex_tree shall be included to test includes are well defined.
@@ -15,26 +17,25 @@
using namespace Gudhi;
-typedef Simplex_tree<> typeST;
-typedef std::pair<typeST::Simplex_handle, bool> typePairSimplexBool;
-typedef std::vector<Vertex_handle> typeVectorVertex;
-typedef std::pair<typeVectorVertex, Filtration_value> typeSimplex;
+typedef boost::mpl::list<Simplex_tree<>, Simplex_tree<Simplex_tree_options_fast_persistence>> list_of_tested_variants;
const Vertex_handle DEFAULT_VERTEX_HANDLE = (const Vertex_handle) - 1;
const Filtration_value DEFAULT_FILTRATION_VALUE = (const Filtration_value) 0.0;
+template<class typeST>
void test_empty_simplex_tree(typeST& tst) {
BOOST_CHECK(tst.null_vertex() == DEFAULT_VERTEX_HANDLE);
BOOST_CHECK(tst.filtration() == DEFAULT_FILTRATION_VALUE);
BOOST_CHECK(tst.num_vertices() == (size_t) 0);
BOOST_CHECK(tst.num_simplices() == (size_t) 0);
- typeST::Siblings* STRoot = tst.root();
- BOOST_CHECK(STRoot != NULL);
- BOOST_CHECK(STRoot->oncles() == NULL);
+ typename typeST::Siblings* STRoot = tst.root();
+ BOOST_CHECK(STRoot != nullptr);
+ BOOST_CHECK(STRoot->oncles() == nullptr);
BOOST_CHECK(STRoot->parent() == DEFAULT_VERTEX_HANDLE);
BOOST_CHECK(tst.dimension() == -1);
}
+template<class typeST>
void test_iterators_on_empty_simplex_tree(typeST& tst) {
std::cout << "Iterator on vertices: " << std::endl;
for (auto vertex : tst.complex_vertex_range()) {
@@ -56,8 +57,9 @@ void test_iterators_on_empty_simplex_tree(typeST& tst) {
}
}
-BOOST_AUTO_TEST_CASE(simplex_tree_when_empty) {
- const Filtration_value DEFAULT_FILTRATION_VALUE = 0;
+BOOST_AUTO_TEST_CASE_TEMPLATE(simplex_tree_when_empty, typeST, list_of_tested_variants) {
+ typedef std::pair<typename typeST::Simplex_handle, bool> typePairSimplexBool;
+ typedef std::vector<Vertex_handle> typeVectorVertex;
std::cout << "********************************************************************" << std::endl;
std::cout << "TEST OF DEFAULT CONSTRUCTOR" << std::endl;
@@ -72,7 +74,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_when_empty) {
BOOST_CHECK(simplexVectorEmpty.empty() == true);
typePairSimplexBool returnEmptyValue = st.insert_simplex(simplexVectorEmpty,
DEFAULT_FILTRATION_VALUE);
- BOOST_CHECK(returnEmptyValue.first == typeST::Simplex_handle(NULL));
+ BOOST_CHECK(returnEmptyValue.first == typename typeST::Simplex_handle(nullptr));
BOOST_CHECK(returnEmptyValue.second == true);
test_empty_simplex_tree(st);
@@ -84,7 +86,7 @@ bool AreAlmostTheSame(float a, float b) {
return std::fabs(a - b) < std::numeric_limits<float>::epsilon();
}
-BOOST_AUTO_TEST_CASE(simplex_tree_from_file) {
+BOOST_AUTO_TEST_CASE_TEMPLATE(simplex_tree_from_file, typeST, list_of_tested_variants) {
// TEST OF INSERTION
std::cout << "********************************************************************" << std::endl;
std::cout << "TEST OF SIMPLEX TREE FROM A FILE" << std::endl;
@@ -101,7 +103,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_from_file) {
// Check
BOOST_CHECK(st.num_simplices() == 143353);
BOOST_CHECK(st.dimension() == 3);
- BOOST_CHECK(st.filtration() == 0.4);
+ BOOST_CHECK(AreAlmostTheSame(st.filtration(), 0.4));
int previous_size = 0;
for (auto f_simplex : st.filtration_simplex_range()) {
@@ -119,6 +121,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_from_file) {
simplex_tree_stream.close();
}
+template<class typeST, class typeSimplex>
void test_simplex_tree_contains(typeST& simplexTree, typeSimplex& simplex, int pos) {
auto f_simplex = simplexTree.filtration_simplex_range().begin() + pos;
@@ -135,16 +138,18 @@ void test_simplex_tree_contains(typeST& simplexTree, typeSimplex& simplex, int p
}
}
+template<class typeST, class typePairSimplexBool>
void test_simplex_tree_insert_returns_true(const typePairSimplexBool& returnValue) {
BOOST_CHECK(returnValue.second == true);
- typeST::Simplex_handle shReturned = returnValue.first; // Simplex_handle = boost::container::flat_map< Vertex_handle, Node >::iterator
- BOOST_CHECK(shReturned != typeST::Simplex_handle(NULL));
+ typename typeST::Simplex_handle shReturned = returnValue.first; // Simplex_handle = boost::container::flat_map< Vertex_handle, Node >::iterator
+ BOOST_CHECK(shReturned != typename typeST::Simplex_handle(nullptr));
}
// Global variables
Filtration_value max_fil = DEFAULT_FILTRATION_VALUE;
int dim_max = -1;
+template<class typeST, class Filtration_value>
void set_and_test_simplex_tree_dim_fil(typeST& simplexTree, int vectorSize, const Filtration_value& fil) {
if (vectorSize > dim_max + 1) {
dim_max = vectorSize - 1;
@@ -173,11 +178,17 @@ void set_and_test_simplex_tree_dim_fil(typeST& simplexTree, int vectorSize, cons
BOOST_CHECK(simplexTree.num_simplices() == num_simp);
}
-BOOST_AUTO_TEST_CASE(simplex_tree_insertion) {
+BOOST_AUTO_TEST_CASE_TEMPLATE(simplex_tree_insertion, typeST, list_of_tested_variants) {
+ typedef std::pair<typename typeST::Simplex_handle, bool> typePairSimplexBool;
+ typedef std::vector<Vertex_handle> typeVectorVertex;
+ typedef std::pair<typeVectorVertex, Filtration_value> typeSimplex;
const Filtration_value FIRST_FILTRATION_VALUE = 0.1;
const Filtration_value SECOND_FILTRATION_VALUE = 0.2;
const Filtration_value THIRD_FILTRATION_VALUE = 0.3;
const Filtration_value FOURTH_FILTRATION_VALUE = 0.4;
+ // reset since we run the test several times
+ dim_max = -1;
+ max_fil = DEFAULT_FILTRATION_VALUE;
// TEST OF INSERTION
std::cout << "********************************************************************" << std::endl;
@@ -191,7 +202,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) {
typeSimplex firstSimplex = std::make_pair(firstSimplexVector, Filtration_value(FIRST_FILTRATION_VALUE));
typePairSimplexBool returnValue = st.insert_simplex(firstSimplex.first, firstSimplex.second);
- test_simplex_tree_insert_returns_true(returnValue);
+ test_simplex_tree_insert_returns_true<typeST>(returnValue);
set_and_test_simplex_tree_dim_fil(st, firstSimplexVector.size(), firstSimplex.second);
BOOST_CHECK(st.num_vertices() == (size_t) 1);
@@ -202,7 +213,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) {
typeSimplex secondSimplex = std::make_pair(secondSimplexVector, Filtration_value(FIRST_FILTRATION_VALUE));
returnValue = st.insert_simplex(secondSimplex.first, secondSimplex.second);
- test_simplex_tree_insert_returns_true(returnValue);
+ test_simplex_tree_insert_returns_true<typeST>(returnValue);
set_and_test_simplex_tree_dim_fil(st, secondSimplexVector.size(), secondSimplex.second);
BOOST_CHECK(st.num_vertices() == (size_t) 2);
@@ -213,7 +224,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) {
typeSimplex thirdSimplex = std::make_pair(thirdSimplexVector, Filtration_value(SECOND_FILTRATION_VALUE));
returnValue = st.insert_simplex(thirdSimplex.first, thirdSimplex.second);
- test_simplex_tree_insert_returns_true(returnValue);
+ test_simplex_tree_insert_returns_true<typeST>(returnValue);
set_and_test_simplex_tree_dim_fil(st, thirdSimplexVector.size(), thirdSimplex.second);
BOOST_CHECK(st.num_vertices() == (size_t) 2); // Not incremented !!
@@ -224,7 +235,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) {
typeSimplex fourthSimplex = std::make_pair(fourthSimplexVector, Filtration_value(FIRST_FILTRATION_VALUE));
returnValue = st.insert_simplex(fourthSimplex.first, fourthSimplex.second);
- test_simplex_tree_insert_returns_true(returnValue);
+ test_simplex_tree_insert_returns_true<typeST>(returnValue);
set_and_test_simplex_tree_dim_fil(st, fourthSimplexVector.size(), fourthSimplex.second);
BOOST_CHECK(st.num_vertices() == (size_t) 3);
@@ -235,7 +246,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) {
typeSimplex fifthSimplex = std::make_pair(fifthSimplexVector, Filtration_value(SECOND_FILTRATION_VALUE));
returnValue = st.insert_simplex(fifthSimplex.first, fifthSimplex.second);
- test_simplex_tree_insert_returns_true(returnValue);
+ test_simplex_tree_insert_returns_true<typeST>(returnValue);
set_and_test_simplex_tree_dim_fil(st, fifthSimplexVector.size(), fifthSimplex.second);
BOOST_CHECK(st.num_vertices() == (size_t) 3); // Not incremented !!
@@ -246,7 +257,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) {
typeSimplex sixthSimplex = std::make_pair(sixthSimplexVector, Filtration_value(SECOND_FILTRATION_VALUE));
returnValue = st.insert_simplex(sixthSimplex.first, sixthSimplex.second);
- test_simplex_tree_insert_returns_true(returnValue);
+ test_simplex_tree_insert_returns_true<typeST>(returnValue);
set_and_test_simplex_tree_dim_fil(st, sixthSimplexVector.size(), sixthSimplex.second);
BOOST_CHECK(st.num_vertices() == (size_t) 3); // Not incremented !!
@@ -257,7 +268,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) {
typeSimplex seventhSimplex = std::make_pair(seventhSimplexVector, Filtration_value(THIRD_FILTRATION_VALUE));
returnValue = st.insert_simplex(seventhSimplex.first, seventhSimplex.second);
- test_simplex_tree_insert_returns_true(returnValue);
+ test_simplex_tree_insert_returns_true<typeST>(returnValue);
set_and_test_simplex_tree_dim_fil(st, seventhSimplexVector.size(), seventhSimplex.second);
BOOST_CHECK(st.num_vertices() == (size_t) 3); // Not incremented !!
@@ -268,7 +279,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) {
typeSimplex eighthSimplex = std::make_pair(eighthSimplexVector, Filtration_value(FIRST_FILTRATION_VALUE));
returnValue = st.insert_simplex(eighthSimplex.first, eighthSimplex.second);
- test_simplex_tree_insert_returns_true(returnValue);
+ test_simplex_tree_insert_returns_true<typeST>(returnValue);
set_and_test_simplex_tree_dim_fil(st, eighthSimplexVector.size(), eighthSimplex.second);
BOOST_CHECK(st.num_vertices() == (size_t) 4);
@@ -279,7 +290,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) {
typeSimplex ninethSimplex = std::make_pair(ninethSimplexVector, Filtration_value(SECOND_FILTRATION_VALUE));
returnValue = st.insert_simplex(ninethSimplex.first, ninethSimplex.second);
- test_simplex_tree_insert_returns_true(returnValue);
+ test_simplex_tree_insert_returns_true<typeST>(returnValue);
set_and_test_simplex_tree_dim_fil(st, ninethSimplexVector.size(), ninethSimplex.second);
BOOST_CHECK(st.num_vertices() == (size_t) 4); // Not incremented !!
@@ -292,8 +303,8 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) {
returnValue = st.insert_simplex(tenthSimplex.first, tenthSimplex.second);
BOOST_CHECK(returnValue.second == false);
- typeST::Simplex_handle shReturned = returnValue.first; // Simplex_handle = boost::container::flat_map< Vertex_handle, Node >::iterator
- BOOST_CHECK(shReturned == typeST::Simplex_handle(NULL));
+ typename typeST::Simplex_handle shReturned = returnValue.first; // Simplex_handle = boost::container::flat_map< Vertex_handle, Node >::iterator
+ BOOST_CHECK(shReturned == typename typeST::Simplex_handle(nullptr));
BOOST_CHECK(st.num_vertices() == (size_t) 4); // Not incremented !!
BOOST_CHECK(st.dimension() == dim_max);
BOOST_CHECK(AreAlmostTheSame(st.filtration(), max_fil));
@@ -307,7 +318,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) {
BOOST_CHECK(returnValue.second == false);
shReturned = returnValue.first; // Simplex_handle = boost::container::flat_map< Vertex_handle, Node >::iterator
- BOOST_CHECK(shReturned == typeST::Simplex_handle(NULL));
+ BOOST_CHECK(shReturned == typename typeST::Simplex_handle(nullptr));
BOOST_CHECK(st.num_vertices() == (size_t) 4); // Not incremented !!
BOOST_CHECK(st.dimension() == dim_max);
BOOST_CHECK(AreAlmostTheSame(st.filtration(), max_fil));
@@ -362,9 +373,10 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) {
}
-bool sort_in_decr_order (Vertex_handle i,Vertex_handle j) { return (i>j); }
-
-BOOST_AUTO_TEST_CASE(NSimplexAndSubfaces_tree_insertion) {
+BOOST_AUTO_TEST_CASE_TEMPLATE(NSimplexAndSubfaces_tree_insertion, typeST, list_of_tested_variants) {
+ typedef std::pair<typename typeST::Simplex_handle, bool> typePairSimplexBool;
+ typedef std::vector<Vertex_handle> typeVectorVertex;
+ typedef std::pair<typeVectorVertex, Filtration_value> typeSimplex;
std::cout << "********************************************************************" << std::endl;
std::cout << "TEST OF RECURSIVE INSERTION" << std::endl;
typeST st;
@@ -382,7 +394,7 @@ BOOST_AUTO_TEST_CASE(NSimplexAndSubfaces_tree_insertion) {
// Check it is well inserted
BOOST_CHECK(true == returnValue.second);
position = 0;
- std::sort(SimplexVector1.begin(), SimplexVector1.end(), sort_in_decr_order);
+ std::sort(SimplexVector1.begin(), SimplexVector1.end(), std::greater<Vertex_handle>());
for (auto vertex : st.simplex_vertex_range(returnValue.first)) {
// Check returned Simplex_handle
std::cout << "vertex = " << vertex << " | vector[" << position << "] = " << SimplexVector1[position] << std::endl;
@@ -401,7 +413,7 @@ BOOST_AUTO_TEST_CASE(NSimplexAndSubfaces_tree_insertion) {
// Check it is well inserted
BOOST_CHECK(true == returnValue.second);
position = 0;
- std::sort(SimplexVector2.begin(), SimplexVector2.end(), sort_in_decr_order);
+ std::sort(SimplexVector2.begin(), SimplexVector2.end(), std::greater<Vertex_handle>());
for (auto vertex : st.simplex_vertex_range(returnValue.first)) {
// Check returned Simplex_handle
std::cout << "vertex = " << vertex << " | vector[" << position << "] = " << SimplexVector2[position] << std::endl;
@@ -420,7 +432,7 @@ BOOST_AUTO_TEST_CASE(NSimplexAndSubfaces_tree_insertion) {
// Check it is well inserted
BOOST_CHECK(true == returnValue.second);
position = 0;
- std::sort(SimplexVector3.begin(), SimplexVector3.end(), sort_in_decr_order);
+ std::sort(SimplexVector3.begin(), SimplexVector3.end(), std::greater<Vertex_handle>());
for (auto vertex : st.simplex_vertex_range(returnValue.first)) {
// Check returned Simplex_handle
std::cout << "vertex = " << vertex << " | vector[" << position << "] = " << SimplexVector3[position] << std::endl;
@@ -450,7 +462,7 @@ BOOST_AUTO_TEST_CASE(NSimplexAndSubfaces_tree_insertion) {
// Check it is well inserted
BOOST_CHECK(true == returnValue.second);
position = 0;
- std::sort(SimplexVector5.begin(), SimplexVector5.end(), sort_in_decr_order);
+ std::sort(SimplexVector5.begin(), SimplexVector5.end(), std::greater<Vertex_handle>());
for (auto vertex : st.simplex_vertex_range(returnValue.first)) {
// Check returned Simplex_handle
std::cout << "vertex = " << vertex << " | vector[" << position << "] = " << SimplexVector5[position] << std::endl;
@@ -469,7 +481,7 @@ BOOST_AUTO_TEST_CASE(NSimplexAndSubfaces_tree_insertion) {
// Check it is well inserted
BOOST_CHECK(true == returnValue.second);
position = 0;
- std::sort(SimplexVector6.begin(), SimplexVector6.end(), sort_in_decr_order);
+ std::sort(SimplexVector6.begin(), SimplexVector6.end(), std::greater<Vertex_handle>());
for (auto vertex : st.simplex_vertex_range(returnValue.first)) {
// Check returned Simplex_handle
std::cout << "vertex = " << vertex << " | vector[" << position << "] = " << SimplexVector6[position] << std::endl;
@@ -509,7 +521,7 @@ BOOST_AUTO_TEST_CASE(NSimplexAndSubfaces_tree_insertion) {
// Find in the simplex_tree
// ------------------------------------------------------------------------------------------------------------------
typeVectorVertex simpleSimplexVector{1};
- Simplex_tree<>::Simplex_handle simplexFound = st.find(simpleSimplexVector);
+ typename typeST::Simplex_handle simplexFound = st.find(simpleSimplexVector);
std::cout << "**************IS THE SIMPLEX {1} IN THE SIMPLEX TREE ?\n";
if (simplexFound != st.null_simplex())
std::cout << "***+ YES IT IS!\n";
@@ -570,14 +582,15 @@ BOOST_AUTO_TEST_CASE(NSimplexAndSubfaces_tree_insertion) {
}
}
-void test_cofaces(typeST& st, std::vector<Vertex_handle> expected, int dim, std::vector<typeST::Simplex_handle> res) {
- typeST::Cofaces_simplex_range cofaces;
+template<class typeST, class Vertex_handle>
+void test_cofaces(typeST& st, const std::vector<Vertex_handle>& expected, int dim, const std::vector<typename typeST::Simplex_handle>& res) {
+ typename typeST::Cofaces_simplex_range cofaces;
if (dim == 0)
cofaces = st.star_simplex_range(st.find(expected));
else
cofaces = st.cofaces_simplex_range(st.find(expected), dim);
for (auto simplex = cofaces.begin(); simplex != cofaces.end(); ++simplex) {
- typeST::Simplex_vertex_range rg = st.simplex_vertex_range(*simplex);
+ typename typeST::Simplex_vertex_range rg = st.simplex_vertex_range(*simplex);
for (auto vertex = rg.begin(); vertex != rg.end(); ++vertex) {
std::cout << "(" << *vertex << ")";
}
@@ -586,7 +599,8 @@ void test_cofaces(typeST& st, std::vector<Vertex_handle> expected, int dim, std:
}
}
-BOOST_AUTO_TEST_CASE(coface_on_simplex_tree) {
+BOOST_AUTO_TEST_CASE_TEMPLATE(coface_on_simplex_tree, typeST, list_of_tested_variants) {
+ typedef std::vector<Vertex_handle> typeVectorVertex;
std::cout << "********************************************************************" << std::endl;
std::cout << "TEST COFACE ALGORITHM" << std::endl;
typeST st;
@@ -616,7 +630,7 @@ BOOST_AUTO_TEST_CASE(coface_on_simplex_tree) {
st.set_dimension(3);
std::vector<Vertex_handle> simplex_result;
- std::vector<typeST::Simplex_handle> result;
+ std::vector<typename typeST::Simplex_handle> result;
std::cout << "First test - Star of (3):" << std::endl;
simplex_result = {3};
@@ -684,7 +698,8 @@ BOOST_AUTO_TEST_CASE(coface_on_simplex_tree) {
}
-BOOST_AUTO_TEST_CASE(copy_move_on_simplex_tree) {
+BOOST_AUTO_TEST_CASE_TEMPLATE(copy_move_on_simplex_tree, typeST, list_of_tested_variants) {
+ typedef std::vector<Vertex_handle> typeVectorVertex;
std::cout << "********************************************************************" << std::endl;
std::cout << "TEST COPY MOVE CONSTRUCTORS" << std::endl;
typeST st;
@@ -744,3 +759,391 @@ BOOST_AUTO_TEST_CASE(copy_move_on_simplex_tree) {
std::cout << "Printing st once again- address = " << &st << std::endl;
}
+
+template<class typeST>
+void test_simplex_is_vertex(typeST& st, typename typeST::Simplex_handle sh, typename typeST::Vertex_handle v) {
+ BOOST_CHECK(st.dimension(sh) == 0);
+ auto&& r = st.simplex_vertex_range(sh);
+ auto i = std::begin(r);
+ BOOST_CHECK(*i == v);
+ BOOST_CHECK(++i == std::end(r));
+}
+
+BOOST_AUTO_TEST_CASE(non_contiguous) {
+ typedef Simplex_tree<> typeST;
+ typedef typeST::Vertex_handle Vertex_handle;
+ typedef typeST::Simplex_handle Simplex_handle;
+ std::cout << "********************************************************************" << std::endl;
+ std::cout << "TEST NON-CONTIGUOUS VERTICES" << std::endl;
+ typeST st;
+ Vertex_handle e[] = {3,-7};
+ std::cout << "Insert" << std::endl;
+ st.insert_simplex_and_subfaces(e);
+ BOOST_CHECK(st.num_vertices() == 2);
+ BOOST_CHECK(st.num_simplices() == 3);
+ std::cout << "Find" << std::endl;
+ Simplex_handle sh = st.find(e);
+ BOOST_CHECK(sh != st.null_simplex());
+ std::cout << "Endpoints" << std::endl;
+ auto p = st.endpoints(sh);
+ test_simplex_is_vertex(st, p.first, 3);
+ test_simplex_is_vertex(st, p.second, -7);
+ std::cout << "Boundary" << std::endl;
+ auto&& b = st.boundary_simplex_range(sh);
+ auto i = std::begin(b);
+ test_simplex_is_vertex(st, *i, -7);
+ test_simplex_is_vertex(st, *++i, 3);
+ BOOST_CHECK(++i == std::end(b));
+}
+
+BOOST_AUTO_TEST_CASE(make_filtration_non_decreasing) {
+ std::cout << "********************************************************************" << std::endl;
+ std::cout << "MAKE FILTRATION NON DECREASING" << std::endl;
+ typedef Simplex_tree<> typeST;
+ typeST st;
+
+ st.insert_simplex_and_subfaces({2, 1, 0}, 2.0);
+ st.insert_simplex_and_subfaces({3, 0}, 2.0);
+ st.insert_simplex_and_subfaces({3, 4, 5}, 2.0);
+
+ /* Inserted simplex: */
+ /* 1 */
+ /* o */
+ /* /X\ */
+ /* o---o---o---o */
+ /* 2 0 3\X/4 */
+ /* o */
+ /* 5 */
+
+ std::cout << "Check default insertion ensures the filtration values are non decreasing" << std::endl;
+ BOOST_CHECK(!st.make_filtration_non_decreasing());
+
+ // Because of non decreasing property of simplex tree, { 0 } , { 1 } and { 0, 1 } are going to be set from value 2.0
+ // to 1.0
+ st.insert_simplex_and_subfaces({0, 1, 6, 7}, 1.0);
+
+ // Inserted simplex:
+ // 1 6
+ // o---o
+ // /X\7/
+ // o---o---o---o
+ // 2 0 3\X/4
+ // o
+ // 5
+
+ std::cout << "Check default second insertion ensures the filtration values are non decreasing" << std::endl;
+ BOOST_CHECK(!st.make_filtration_non_decreasing());
+
+ // Copy original simplex tree
+ typeST st_copy = st;
+
+ // Modify specific values for st to become like st_copy thanks to make_filtration_non_decreasing
+ st.assign_filtration(st.find({0,1,6,7}), 0.8);
+ st.assign_filtration(st.find({0,1,6}), 0.9);
+ st.assign_filtration(st.find({0,6}), 0.6);
+ st.assign_filtration(st.find({3,4,5}), 1.2);
+ st.assign_filtration(st.find({3,4}), 1.1);
+ st.assign_filtration(st.find({4,5}), 1.99);
+
+ std::cout << "Check the simplex_tree is rolled back in case of decreasing filtration values" << std::endl;
+ BOOST_CHECK(st.make_filtration_non_decreasing());
+ BOOST_CHECK(st == st_copy);
+
+ // Other simplex tree
+ typeST st_other;
+ st_other.insert_simplex_and_subfaces({2, 1, 0}, 3.0); // This one is different from st
+ st_other.insert_simplex_and_subfaces({3, 0}, 2.0);
+ st_other.insert_simplex_and_subfaces({3, 4, 5}, 2.0);
+ st_other.insert_simplex_and_subfaces({0, 1, 6, 7}, 1.0);
+
+ // Modify specific values for st to become like st_other thanks to make_filtration_non_decreasing
+ st.assign_filtration(st.find({2}), 3.0);
+ // By modifying just the simplex {2}
+ // {0,1,2}, {1,2} and {0,2} will be modified
+
+ std::cout << "Check the simplex_tree is repaired in case of decreasing filtration values" << std::endl;
+ BOOST_CHECK(st.make_filtration_non_decreasing());
+ BOOST_CHECK(st == st_other);
+
+ // Modify specific values for st still to be non-decreasing
+ st.assign_filtration(st.find({0,1,2}), 10.0);
+ st.assign_filtration(st.find({0,2}), 9.0);
+ st.assign_filtration(st.find({0,1,6,7}), 50.0);
+ st.assign_filtration(st.find({0,1,6}), 49.0);
+ st.assign_filtration(st.find({0,1,7}), 48.0);
+ // Other copy simplex tree
+ typeST st_other_copy = st;
+
+ std::cout << "Check the simplex_tree is not modified in case of non-decreasing filtration values" << std::endl;
+ BOOST_CHECK(!st.make_filtration_non_decreasing());
+ BOOST_CHECK(st == st_other_copy);
+
+}
+
+struct MyOptions : Simplex_tree_options_full_featured {
+ // Not doing persistence, so we don't need those
+ static const bool store_key = false;
+ static const bool store_filtration = false;
+ // I have few vertices
+ typedef short Vertex_handle;
+};
+
+BOOST_AUTO_TEST_CASE(remove_maximal_simplex) {
+ std::cout << "********************************************************************" << std::endl;
+ std::cout << "REMOVE MAXIMAL SIMPLEX" << std::endl;
+
+
+ typedef Simplex_tree<MyOptions> miniST;
+ miniST st;
+
+ // FIXME
+ st.set_dimension(3);
+
+ st.insert_simplex_and_subfaces({0, 1, 6, 7});
+ st.insert_simplex_and_subfaces({3, 4, 5});
+
+ // Constructs a copy at this state for further test purpose
+ miniST st_pruned = st;
+
+ st.insert_simplex_and_subfaces({3, 0});
+ st.insert_simplex_and_subfaces({2, 1, 0});
+
+ // Constructs a copy at this state for further test purpose
+ miniST st_complete = st;
+ // st_complete and st:
+ // 1 6
+ // o---o
+ // /X\7/
+ // o---o---o---o
+ // 2 0 3\X/4
+ // o
+ // 5
+ // st_pruned:
+ // 1 6
+ // o---o
+ // \7/
+ // o o---o
+ // 0 3\X/4
+ // o
+ // 5
+
+#ifdef GUDHI_DEBUG
+ std::cout << "Check exception throw in debug mode" << std::endl;
+ // throw excpt because sh has children
+ BOOST_CHECK_THROW (st.remove_maximal_simplex(st.find({0, 1, 6})), std::invalid_argument);
+ BOOST_CHECK_THROW (st.remove_maximal_simplex(st.find({3})), std::invalid_argument);
+ BOOST_CHECK(st == st_complete);
+#endif
+
+ st.remove_maximal_simplex(st.find({0, 2}));
+ st.remove_maximal_simplex(st.find({0, 1, 2}));
+ st.remove_maximal_simplex(st.find({1, 2}));
+ st.remove_maximal_simplex(st.find({2}));
+ st.remove_maximal_simplex(st.find({0, 3}));
+
+ BOOST_CHECK(st == st_pruned);
+ // Remove all, but as the simplex tree is not storing filtration, there is no modification
+ st.prune_above_filtration(0.0);
+ BOOST_CHECK(st == st_pruned);
+
+ miniST st_wo_seven;
+ // FIXME
+ st_wo_seven.set_dimension(3);
+
+ st_wo_seven.insert_simplex_and_subfaces({0, 1, 6});
+ st_wo_seven.insert_simplex_and_subfaces({3, 4, 5});
+ // st_wo_seven:
+ // 1 6
+ // o---o
+ // \X/
+ // o o---o
+ // 0 3\X/4
+ // o
+ // 5
+
+ // Remove all 7 to test the both remove_maximal_simplex cases (when _members is empty or not)
+ st.remove_maximal_simplex(st.find({0, 1, 6, 7}));
+ st.remove_maximal_simplex(st.find({0, 1, 7}));
+ st.remove_maximal_simplex(st.find({0, 6, 7}));
+ st.remove_maximal_simplex(st.find({0, 7}));
+ st.remove_maximal_simplex(st.find({1, 6, 7}));
+ st.remove_maximal_simplex(st.find({1, 7}));
+ st.remove_maximal_simplex(st.find({6, 7}));
+ st.remove_maximal_simplex(st.find({7}));
+
+ BOOST_CHECK(st == st_wo_seven);
+}
+
+BOOST_AUTO_TEST_CASE(prune_above_filtration) {
+ std::cout << "********************************************************************" << std::endl;
+ std::cout << "PRUNE ABOVE FILTRATION" << std::endl;
+ typedef Simplex_tree<> typeST;
+ typeST st;
+
+ // FIXME
+ st.set_dimension(3);
+
+ st.insert_simplex_and_subfaces({0, 1, 6, 7}, 1.0);
+ st.insert_simplex_and_subfaces({3, 4, 5}, 2.0);
+
+ // Constructs a copy at this state for further test purpose
+ typeST st_pruned = st;
+ st_pruned.initialize_filtration(); // reset
+
+ st.insert_simplex_and_subfaces({3, 0}, 3.0);
+ st.insert_simplex_and_subfaces({2, 1, 0}, 4.0);
+
+ // Constructs a copy at this state for further test purpose
+ typeST st_complete = st;
+ // st_complete and st:
+ // 1 6
+ // o---o
+ // /X\7/
+ // o---o---o---o
+ // 2 0 3\X/4
+ // o
+ // 5
+ // st_pruned:
+ // 1 6
+ // o---o
+ // \7/
+ // o o---o
+ // 0 3\X/4
+ // o
+ // 5
+
+ bool simplex_is_changed = false;
+ // Check the no action cases
+ // greater than initial filtration value
+ simplex_is_changed = st.prune_above_filtration(10.0);
+ if (simplex_is_changed)
+ st.initialize_filtration();
+ BOOST_CHECK(st == st_complete);
+ BOOST_CHECK(!simplex_is_changed);
+ // equal to initial filtration value
+ simplex_is_changed = st.prune_above_filtration(6.0);
+ if (simplex_is_changed)
+ st.initialize_filtration();
+ BOOST_CHECK(st == st_complete);
+ BOOST_CHECK(!simplex_is_changed);
+ // lower than initial filtration value, but still greater than the maximum filtration value
+ simplex_is_changed = st.prune_above_filtration(5.0);
+ if (simplex_is_changed)
+ st.initialize_filtration();
+ BOOST_CHECK(st == st_complete);
+ BOOST_CHECK(!simplex_is_changed);
+
+ // Display the Simplex_tree
+ std::cout << "The complex contains " << st.num_simplices() << " simplices";
+ std::cout << " - dimension " << st.dimension() << std::endl;
+ std::cout << "Iterator on Simplices in the filtration, with [filtration value]:" << std::endl;
+ for (auto f_simplex : st.filtration_simplex_range()) {
+ std::cout << " " << "[" << st.filtration(f_simplex) << "] ";
+ for (auto vertex : st.simplex_vertex_range(f_simplex)) {
+ std::cout << (int) vertex << " ";
+ }
+ std::cout << std::endl;
+ }
+
+ // Check the pruned cases
+ simplex_is_changed = st.prune_above_filtration(2.5);
+ if (simplex_is_changed)
+ st.initialize_filtration();
+ BOOST_CHECK(st == st_pruned);
+ BOOST_CHECK(simplex_is_changed);
+
+ // Display the Simplex_tree
+ std::cout << "The complex pruned at 2.5 contains " << st.num_simplices() << " simplices";
+ std::cout << " - dimension " << st.dimension() << std::endl;
+
+ simplex_is_changed = st.prune_above_filtration(2.0);
+ if (simplex_is_changed)
+ st.initialize_filtration();
+
+ std::cout << "The complex pruned at 2.0 contains " << st.num_simplices() << " simplices";
+ std::cout << " - dimension " << st.dimension() << std::endl;
+
+ BOOST_CHECK(st == st_pruned);
+ BOOST_CHECK(!simplex_is_changed);
+
+ typeST st_empty;
+ // FIXME
+ st_empty.set_dimension(3);
+ simplex_is_changed = st.prune_above_filtration(0.0);
+ if (simplex_is_changed)
+ st.initialize_filtration();
+
+ // Display the Simplex_tree
+ std::cout << "The complex pruned at 0.0 contains " << st.num_simplices() << " simplices";
+ std::cout << " - dimension " << st.dimension() << std::endl;
+
+ BOOST_CHECK(st == st_empty);
+ BOOST_CHECK(simplex_is_changed);
+
+ // Test case to the limit
+ simplex_is_changed = st.prune_above_filtration(-1.0);
+ if (simplex_is_changed)
+ st.initialize_filtration();
+ BOOST_CHECK(st == st_empty);
+ BOOST_CHECK(!simplex_is_changed);
+}
+
+BOOST_AUTO_TEST_CASE(mini_prune_above_filtration) {
+ std::cout << "********************************************************************" << std::endl;
+ std::cout << "MINI PRUNE ABOVE FILTRATION" << std::endl;
+ typedef Simplex_tree<MyOptions> typeST;
+ typeST st;
+
+ // FIXME
+ st.set_dimension(3);
+
+ st.insert_simplex_and_subfaces({0, 1, 6, 7});
+ st.insert_simplex_and_subfaces({3, 4, 5});
+ st.insert_simplex_and_subfaces({3, 0});
+ st.insert_simplex_and_subfaces({2, 1, 0});
+
+ // st:
+ // 1 6
+ // o---o
+ // /X\7/
+ // o---o---o---o
+ // 2 0 3\X/4
+ // o
+ // 5
+
+ st.initialize_filtration();
+
+ // Display the Simplex_tree
+ std::cout << "The complex contains " << st.num_simplices() << " simplices" << std::endl;
+ BOOST_CHECK(st.num_simplices() == 27);
+
+ // Test case to the limit - With these options, there is no filtration, which means filtration is 0
+ bool simplex_is_changed = st.prune_above_filtration(1.0);
+ if (simplex_is_changed)
+ st.initialize_filtration();
+ // Display the Simplex_tree
+ std::cout << "The complex pruned at 1.0 contains " << st.num_simplices() << " simplices" << std::endl;
+ BOOST_CHECK(!simplex_is_changed);
+ BOOST_CHECK(st.num_simplices() == 27);
+
+ simplex_is_changed = st.prune_above_filtration(0.0);
+ if (simplex_is_changed)
+ st.initialize_filtration();
+ // Display the Simplex_tree
+ std::cout << "The complex pruned at 0.0 contains " << st.num_simplices() << " simplices" << std::endl;
+ BOOST_CHECK(!simplex_is_changed);
+ BOOST_CHECK(st.num_simplices() == 27);
+
+ // Test case to the limit
+ simplex_is_changed = st.prune_above_filtration(-1.0);
+ if (simplex_is_changed)
+ st.initialize_filtration();
+ // Display the Simplex_tree
+ std::cout << "The complex pruned at -1.0 contains " << st.num_simplices() << " simplices" << std::endl;
+ BOOST_CHECK(simplex_is_changed);
+ BOOST_CHECK(st.num_simplices() == 0);
+
+ // Display the Simplex_tree
+ std::cout << "The complex contains " << st.num_simplices() << " simplices" << std::endl;
+
+} \ No newline at end of file
diff --git a/src/Skeleton_blocker/concept/SkeletonBlockerDS.h b/src/Skeleton_blocker/concept/SkeletonBlockerDS.h
index c0386590..d82425a0 100644
--- a/src/Skeleton_blocker/concept/SkeletonBlockerDS.h
+++ b/src/Skeleton_blocker/concept/SkeletonBlockerDS.h
@@ -1,20 +1,31 @@
-/*
- * SkeletonBlockerDS.h
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
*
- * Created on: Feb 20, 2014
- * Author: David Salinas
- * Copyright 2013 INRIA. All rights reserved
+ * 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 GUDHI_SKELETONBLOCKERDS_H_
-#define GUDHI_SKELETONBLOCKERDS_H_
-
+#ifndef CONCEPT_SKELETON_BLOCKER_SKELETONBLOCKERDS_H_
+#define CONCEPT_SKELETON_BLOCKER_SKELETONBLOCKERDS_H_
namespace Gudhi {
-namespace skbl {
-
-
+namespace skeleton_blocker {
/** \brief Concept for the template class passed for Skeleton_blocker_complex.
* Most importantly, it contains the nodes for vertices and edges
@@ -22,104 +33,97 @@ namespace skbl {
* complex. The user can redefine these classes to attach
* additional information to vertices and edges.
*/
-struct SkeletonBlockerDS
-{
- /**
- * @brief index that allows to find the vertex in the boost graph
- */
- typedef int boost_vertex_handle;
-
-
- /**
- * @brief Root_vertex_handle and Vertex_handle are similar to global and local vertex descriptor
- * used in <a href="http://www.boost.org/doc/libs/1_38_0/libs/graph/doc/subgraph.html">boost subgraphs</a>
- * and allow to localize a vertex of a subcomplex on its parent root complex.
- *
- * In gross, vertices are stored in a vector
- * and the Root_vertex_handle and Vertex_handle store indices of a vertex in this vector.
- *
- * For the root simplicial complex, the Root_vertex_handle and Vertex_handle of a vertex
- * are the same.
- *
- *
- * For a subcomplex L of a simplicial complex K, the local descriptor, ie the Vertex_handle, of a
- * vertex v (that belongs to L) is its position in the vector of vertices
- * of the subcomplex L whereas its Root_vertex_handle (global descriptor) is the position of v in the vector of the
- * vertices of the root simplicial complex K.
- */
- struct Root_vertex_handle{
-
- boost_vertex_handle vertex;
-
- friend ostream& operator << (ostream& o, const Root_vertex_handle & v);
- };
-
- /**
- * A Vertex_handle must be Default Constructible, Assignable and Equality Comparable.
- */
- struct Vertex_handle{
- boost_vertex_handle vertex;
-
- friend ostream& operator << (ostream& o, const Vertex_handle & v);
- };
-
-
- /**
- * \brief The type of vertices that are stored the boost graph.
- * A Vertex must be Default Constructible and Equality Comparable.
- *
- */
- struct Graph_vertex{
- /** \brief Used to deactivate a vertex for example when contracting an edge.
- * It allows in some cases to remove the vertex at low cost.
- */
- void deactivate();
-
- /** \brief Used to activate a vertex.
- */
- void activate();
-
- /** \brief Tells if the vertex is active.
- */
- bool is_active() const;
-
- void set_id(Root_vertex_handle i);
- Root_vertex_handle get_id() const;
- virtual string to_string() const ;
- friend ostream& operator << (ostream& o, const Graph_vertex & v);
- };
-
-
- /**
- * \brief The type of edges that are stored the boost graph.
- * An Edge must be Default Constructible and Equality Comparable.
- */
- struct Graph_edge{
- /**
- * @brief Allows to modify vertices of the edge.
- */
- void setId(Root_vertex_handle a,Root_vertex_handle b);
-
- /**
- * @brief Returns the first vertex of the edge.
- */
- Root_vertex_handle first() const ;
-
- /**
- * @brief Returns the second vertex of the edge.
- */
- Root_vertex_handle second() const ;
-
- friend ostream& operator << (ostream& o, const Simple_edge & v);
- };
-
-
+struct SkeletonBlockerDS {
+ /**
+ * @brief index that allows to find the vertex in the boost graph
+ */
+ typedef int boost_vertex_handle;
+
+ /**
+ * @brief Root_vertex_handle and Vertex_handle are similar to global and local vertex descriptor
+ * used in <a href="http://www.boost.org/doc/libs/1_38_0/libs/graph/doc/subgraph.html">boost subgraphs</a>
+ * and allow to localize a vertex of a subcomplex on its parent root complex.
+ *
+ * In gross, vertices are stored in a vector
+ * and the Root_vertex_handle and Vertex_handle store indices of a vertex in this vector.
+ *
+ * For the root simplicial complex, the Root_vertex_handle and Vertex_handle of a vertex
+ * are the same.
+ *
+ *
+ * For a subcomplex L of a simplicial complex K, the local descriptor, ie the Vertex_handle, of a
+ * vertex v (that belongs to L) is its position in the vector of vertices
+ * of the subcomplex L whereas its Root_vertex_handle (global descriptor) is the position of v in the vector of the
+ * vertices of the root simplicial complex K.
+ */
+ struct Root_vertex_handle {
+ boost_vertex_handle vertex;
+
+ friend ostream& operator<<(ostream& o, const Root_vertex_handle & v);
+ };
+
+ /**
+ * A Vertex_handle must be Default Constructible, Assignable and Equality Comparable.
+ */
+ struct Vertex_handle {
+ boost_vertex_handle vertex;
+
+ friend ostream& operator<<(ostream& o, const Vertex_handle & v);
+ };
+
+ /**
+ * \brief The type of vertices that are stored the boost graph.
+ * A Vertex must be Default Constructible and Equality Comparable.
+ *
+ */
+ struct Graph_vertex {
+ /** \brief Used to deactivate a vertex for example when contracting an edge.
+ * It allows in some cases to remove the vertex at low cost.
+ */
+ void deactivate();
+
+ /** \brief Used to activate a vertex.
+ */
+ void activate();
+
+ /** \brief Tells if the vertex is active.
+ */
+ bool is_active() const;
+
+ void set_id(Root_vertex_handle i);
+ Root_vertex_handle get_id() const;
+ virtual string to_string() const;
+ friend ostream& operator<<(ostream& o, const Graph_vertex & v);
+ };
+
+ /**
+ * \brief The type of edges that are stored the boost graph.
+ * An Edge must be Default Constructible and Equality Comparable.
+ */
+ struct Graph_edge {
+ /**
+ * @brief Allows to modify vertices of the edge.
+ */
+ void setId(Root_vertex_handle a, Root_vertex_handle b);
+
+ /**
+ * @brief Returns the first vertex of the edge.
+ */
+ Root_vertex_handle first() const;
+
+ /**
+ * @brief Returns the second vertex of the edge.
+ */
+ Root_vertex_handle second() const;
+
+ friend ostream& operator<<(ostream& o, const Simple_edge & v);
+ };
};
+} // namespace skeleton_blocker
+namespace skbl = skeleton_blocker;
-} // namespace skbl
-} // namespace GUDHI
-
+} // namespace Gudhi
-#endif /* GUDHI_SKELETONBLOCKERDS_H_ */
+#endif // CONCEPT_SKELETON_BLOCKER_SKELETONBLOCKERDS_H_
diff --git a/src/Skeleton_blocker/concept/SkeletonBlockerGeometricDS.h b/src/Skeleton_blocker/concept/SkeletonBlockerGeometricDS.h
index 8fbf0d12..477464c4 100644
--- a/src/Skeleton_blocker/concept/SkeletonBlockerGeometricDS.h
+++ b/src/Skeleton_blocker/concept/SkeletonBlockerGeometricDS.h
@@ -1,16 +1,30 @@
-/*
- * SkeletonBlockerGeometricDS.h
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
*
- * Created on: Feb 20, 2014
- * Author: David Salinas
- * Copyright 2013 INRIA. All rights reserved
+ * 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 GUDHI_SKELETONBLOCKERGEOMETRICDS_H_
-#define GUDHI_SKELETONBLOCKERGEOMETRICDS_H_
+#ifndef CONCEPT_SKELETON_BLOCKER_SKELETONBLOCKERGEOMETRICDS_H_
+#define CONCEPT_SKELETON_BLOCKER_SKELETONBLOCKERGEOMETRICDS_H_
namespace Gudhi {
-namespace skbl {
+namespace skeleton_blocker {
/**
* \brief Concept for template class of Skeleton_blocker_geometric_complex .
@@ -20,55 +34,57 @@ namespace skbl {
* Graph_edge must specify how to access to an index.
*
*/
- //todo the index is just for contraction, to remove
-template<typename GeometryTrait>
-struct SkeletonBlockerGeometricDS : public SkeletonBlockerDS
-{
+// TODO(DS): the index is just for contraction, to remove
- /**
- * Geometry information.
- */
- typedef GeometryTrait GT ;
+template<typename GeometryTrait>
+struct SkeletonBlockerGeometricDS : public SkeletonBlockerDS {
+ /**
+ * Geometry information.
+ */
+ typedef GeometryTrait GT;
- /**
- * Type of point (should be the same as GT::Point).
- */
- typedef typename GeometryTrait::Point Point;
+ /**
+ * Type of point (should be the same as GT::Point).
+ */
+ typedef typename GeometryTrait::Point Point;
- /**
- * @brief Vertex that stores a point.
- */
- class Graph_vertex : public SkeletonBlockerDS::Graph_vertex{
- public:
- /**
- * @brief Access to the point.
- */
- Point& point();
- /**
- * @brief Access to the point.
- */
- const Point& point();
- };
+ /**
+ * @brief Vertex that stores a point.
+ */
+ class Graph_vertex : public SkeletonBlockerDS::Graph_vertex {
+ public:
+ /**
+ * @brief Access to the point.
+ */
+ Point& point();
+ /**
+ * @brief Access to the point.
+ */
+ const Point& point();
+ };
- /**
- * @brief Edge that allows to access to an index.
- * The indices of the edges are used to store heap information
- * in the edge contraction algorithm.
- */
- class Graph_Edge : public SkeletonBlockerDS::Graph_edge{
- public:
- /**
- * @brief Access to the index.
- */
- int& index();
- /**
- * @brief Access to the index.
- */
- int index();
- };
+ /**
+ * @brief Edge that allows to access to an index.
+ * The indices of the edges are used to store heap information
+ * in the edge contraction algorithm.
+ */
+ class Graph_Edge : public SkeletonBlockerDS::Graph_edge {
+ public:
+ /**
+ * @brief Access to the index.
+ */
+ int& index();
+ /**
+ * @brief Access to the index.
+ */
+ int index();
+ };
};
-} // namespace skbl
-} // namespace GUDHI
+} // namespace skeleton_blocker
+
+namespace skbl = skeleton_blocker;
+
+} // namespace Gudhi
-#endif /* GUDHI_SKELETONBLOCKERGEOMETRICDS_H_ */
+#endif // CONCEPT_SKELETON_BLOCKER_SKELETONBLOCKERGEOMETRICDS_H_
diff --git a/src/Skeleton_blocker/example/CMakeLists.txt b/src/Skeleton_blocker/example/CMakeLists.txt
index de0c7bba..cc7f37f3 100644
--- a/src/Skeleton_blocker/example/CMakeLists.txt
+++ b/src/Skeleton_blocker/example/CMakeLists.txt
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 2.6)
-project(GUDHIskbl)
+project(Skeleton_blocker_examples)
add_executable(SkeletonBlockerFromSimplices Skeleton_blocker_from_simplices.cpp)
add_executable(SkeletonBlockerIteration Skeleton_blocker_iteration.cpp)
diff --git a/src/Skeleton_blocker/example/Skeleton_blocker_from_simplices.cpp b/src/Skeleton_blocker/example/Skeleton_blocker_from_simplices.cpp
index 2738c01c..076c6a53 100644
--- a/src/Skeleton_blocker/example/Skeleton_blocker_from_simplices.cpp
+++ b/src/Skeleton_blocker/example/Skeleton_blocker_from_simplices.cpp
@@ -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
@@ -29,30 +29,26 @@
#include <sstream>
#include <vector>
-using namespace std;
-using namespace Gudhi;
-using namespace skbl;
-
-typedef Skeleton_blocker_complex<Skeleton_blocker_simple_traits> Complex;
+typedef Gudhi::skeleton_blocker::Skeleton_blocker_simple_traits Traits;
+typedef Gudhi::skeleton_blocker::Skeleton_blocker_complex<Traits> Complex;
typedef Complex::Vertex_handle Vertex_handle;
-typedef Complex::Simplex_handle Simplex_handle;
-typedef Complex::Simplex_handle Simplex;
+typedef Complex::Simplex Simplex;
int main(int argc, char *argv[]) {
- std::vector<Simplex_handle> simplices;
+ std::vector<Simplex> simplices;
// add 4 triangles of a tetrahedron 0123
- simplices.push_back(Simplex_handle(Vertex_handle(0), Vertex_handle(1), Vertex_handle(2)));
- simplices.push_back(Simplex_handle(Vertex_handle(1), Vertex_handle(2), Vertex_handle(3)));
- simplices.push_back(Simplex_handle(Vertex_handle(3), Vertex_handle(0), Vertex_handle(2)));
- simplices.push_back(Simplex_handle(Vertex_handle(3), Vertex_handle(0), Vertex_handle(1)));
+ 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)));
// get complex from top faces
- Complex complex(make_complex_from_top_faces<Complex>(simplices.begin(), simplices.end()));
+ Complex complex(Gudhi::skeleton_blocker::make_complex_from_top_faces<Complex>(simplices.begin(), simplices.end()));
std::cout << "Simplices:" << std::endl;
- for (const Simplex & s : complex.simplex_range())
+ for (const Simplex & s : complex.complex_simplex_range())
std::cout << s << " ";
std::cout << std::endl;
@@ -61,16 +57,16 @@ int main(int argc, char *argv[]) {
// now build a complex from its full list of simplices
simplices.clear();
- simplices.push_back(Simplex_handle(Vertex_handle(0)));
- simplices.push_back(Simplex_handle(Vertex_handle(1)));
- simplices.push_back(Simplex_handle(Vertex_handle(2)));
- simplices.push_back(Simplex_handle(Vertex_handle(0), Vertex_handle(1)));
- simplices.push_back(Simplex_handle(Vertex_handle(1), Vertex_handle(2)));
- simplices.push_back(Simplex_handle(Vertex_handle(2), Vertex_handle(0)));
+ 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.simplex_range())
+ for (const Simplex & s : complex.complex_simplex_range())
std::cout << s << " ";
std::cout << std::endl;
diff --git a/src/Skeleton_blocker/example/Skeleton_blocker_iteration.cpp b/src/Skeleton_blocker/example/Skeleton_blocker_iteration.cpp
index 69557694..6a1bc480 100644
--- a/src/Skeleton_blocker/example/Skeleton_blocker_iteration.cpp
+++ b/src/Skeleton_blocker/example/Skeleton_blocker_iteration.cpp
@@ -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
@@ -30,14 +30,10 @@
#include <fstream>
#include <sstream>
-
-using namespace std;
-using namespace Gudhi;
-using namespace skbl;
-
-typedef Skeleton_blocker_complex<Skeleton_blocker_simple_traits> Complex;
+typedef Gudhi::skeleton_blocker::Skeleton_blocker_simple_traits Traits;
+typedef Gudhi::skeleton_blocker::Skeleton_blocker_complex<Traits> Complex;
typedef Complex::Vertex_handle Vertex_handle;
-typedef Complex::Simplex_handle Simplex;
+typedef Complex::Simplex Simplex;
Complex build_complete_complex(int n) {
// build a full complex with n vertices and 2^n-1 simplices
@@ -46,8 +42,7 @@ Complex build_complete_complex(int n) {
complex.add_vertex();
for (int i = 0; i < n; i++)
for (int j = 0; j < i; j++)
- // note that add_edge, add the edge and all its cofaces
- complex.add_edge(Vertex_handle(i), Vertex_handle(j));
+ complex.add_edge_without_blockers(Vertex_handle(i), Vertex_handle(j));
return complex;
}
@@ -77,7 +72,7 @@ int main(int argc, char *argv[]) {
// 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.simplex_range()) {
+ for (const Simplex & s : complex.complex_simplex_range()) {
++num_simplices;
if (s.dimension() % 2 == 0)
euler += 1;
diff --git a/src/Skeleton_blocker/example/Skeleton_blocker_link.cpp b/src/Skeleton_blocker/example/Skeleton_blocker_link.cpp
index 002cbc49..58322038 100644
--- a/src/Skeleton_blocker/example/Skeleton_blocker_link.cpp
+++ b/src/Skeleton_blocker/example/Skeleton_blocker_link.cpp
@@ -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
@@ -28,40 +28,42 @@
#include <fstream>
#include <sstream>
-using namespace std;
-using namespace Gudhi;
-using namespace skbl;
-
-typedef Skeleton_blocker_complex<Skeleton_blocker_simple_traits> Complex;
+typedef Gudhi::skeleton_blocker::Skeleton_blocker_simple_traits Traits;
+typedef Gudhi::skeleton_blocker::Skeleton_blocker_complex<Traits> Complex;
typedef Complex::Vertex_handle Vertex_handle;
typedef Complex::Root_vertex_handle Root_vertex_handle;
-typedef Complex::Simplex_handle Simplex;
+typedef Complex::Simplex Simplex;
int main(int argc, char *argv[]) {
// build a full complex with 4 vertices and 2^4-1 simplices
- // Initial vertices are (0,1,2,3,4)
- Simplex tetrahedron(Vertex_handle(0), Vertex_handle(1), Vertex_handle(2), Vertex_handle(3));
+
+ // Create a complex with four vertices (0,1,2,3)
Complex complex;
+
+ // Add a tetrahedron to this complex
+ Simplex tetrahedron(Vertex_handle(0), Vertex_handle(1), Vertex_handle(2), Vertex_handle(3));
complex.add_simplex(tetrahedron);
- cout << "complex:" << complex.to_string() << endl;
+ std::cout << "complex:" << complex.to_string() << std::endl;
// build the link of vertex 1, eg a triangle {0,2,3}
auto link = complex.link(Vertex_handle(1));
- cout << "link:" << link.to_string() << endl;
+ std::cout << "link:" << link.to_string() << std::endl;
// Internally link is a subcomplex of 'complex' and its vertices are stored in a vector.
// They can be accessed via Vertex_handle(x) where x is an index of the vector.
// In that example, link has three vertices and thus it contains only
// Vertex_handle(0),Vertex_handle(1) and Vertex_handle(2) are).
for (int i = 0; i < 5; ++i)
- cout << "link.contains_vertex(Vertex_handle(" << i << ")):" << link.contains_vertex(Vertex_handle(i)) << endl;
- cout << endl;
+ std::cout << "link.contains_vertex(Vertex_handle(" << i << ")):" << link.contains_vertex(Vertex_handle(i)) <<
+ std::endl;
+ std::cout << std::endl;
// To access to the initial vertices eg (0,1,2,3,4), Root_vertex_handle must be used.
// For instance, to test if the link contains the vertex that was labeled i:
for (int i = 0; i < 5; ++i)
- cout << "link.contains_vertex(Root_vertex_handle(" << i << ")):" << link.contains_vertex(Root_vertex_handle(i)) << endl;
+ std::cout << "link.contains_vertex(Root_vertex_handle(" << i << ")):" <<
+ link.contains_vertex(Root_vertex_handle(i)) << std::endl;
return EXIT_SUCCESS;
}
diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker.h
index 792a7994..32fe411c 100644
--- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker.h
+++ b/src/Skeleton_blocker/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_
@@ -31,17 +31,18 @@
#include <gudhi/Skeleton_blocker/Skeleton_blocker_simple_traits.h>
#include <gudhi/Skeleton_blocker/Skeleton_blocker_simple_geometric_traits.h>
-#include <gudhi/Utils.h> // xxx
+#include <gudhi/Debug_utils.h>
namespace Gudhi {
-namespace skbl {
+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,47 +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_handle 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++)
- //note that add_edge adds the edge and all its cofaces
- complex.add_edge(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.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
@@ -182,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_handle> simplices;
-
- //add 4 triangles of a tetrahedron 0123
- simplices.push_back(Simplex_handle(Vertex_handle(0),Vertex_handle(1),Vertex_handle(2)));
- simplices.push_back(Simplex_handle(Vertex_handle(1),Vertex_handle(2),Vertex_handle(3)));
- simplices.push_back(Simplex_handle(Vertex_handle(3),Vertex_handle(0),Vertex_handle(2)));
- simplices.push_back(Simplex_handle(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.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_handle(Vertex_handle(0)));
- simplices.push_back(Simplex_handle(Vertex_handle(1)));
- simplices.push_back(Simplex_handle(Vertex_handle(2)));
- simplices.push_back(Simplex_handle(Vertex_handle(0),Vertex_handle(1)));
- simplices.push_back(Simplex_handle(Vertex_handle(1),Vertex_handle(2)));
- simplices.push_back(Simplex_handle(Vertex_handle(2),Vertex_handle(0)));
- complex = Complex(simplices.begin(),simplices.end());
-
- std::cout << "Simplices:"<<std::endl;
- for(const Simplex & s : complex.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
@@ -237,15 +237,16 @@ 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.
-\verbatim Contact: David Salinas, david.salinas@inria.fr \endverbatim
-*/
-/** @} */ // end defgroup
+\copyright GNU General Public License v3.
-} // namespace skbl
+@} */
+
+} // namespace skeleton_blocker
+
+namespace skbl = skeleton_blocker;
} // namespace Gudhi
diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_complex_visitor.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_complex_visitor.h
index 72bdf4c9..ba3636bc 100644
--- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_complex_visitor.h
+++ b/src/Skeleton_blocker/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_
@@ -26,8 +27,8 @@
namespace Gudhi {
-namespace skbl {
-// todo rajouter les const
+namespace skeleton_blocker {
+// TODO(DS): to be constified
/**
*@class Skeleton_blocker_complex_visitor
@@ -36,12 +37,12 @@ namespace skbl {
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;
- virtual void on_add_edge(Vertex_handle a, Vertex_handle b) = 0;
+ virtual void on_add_edge_without_blockers(Vertex_handle a, Vertex_handle b) = 0;
virtual void on_remove_edge(Vertex_handle a, Vertex_handle b) = 0;
/**
@@ -54,16 +55,16 @@ class Skeleton_blocker_complex_visitor {
* @brief Called when performing an edge contraction when
* an edge bx is replaced by an edge ax (not already present).
* Precisely, this methods is called this way in contract_edge :
- * add_edge(a,x)
+ * add_edge_without_blockers(a,x)
* on_swaped_edge(a,b,x)
* remove_edge(b,x)
*/
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(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,35 +100,44 @@ 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(Vertex_handle a, Vertex_handle b) {
- std::cerr << "on_add_edge:" << a << "," << b << 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;
}
};
-} // namespace skbl
+} // namespace skeleton_blocker
+
+namespace skbl = skeleton_blocker;
} // namespace Gudhi
diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_link_superior.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_link_superior.h
index d39fa9f3..d4b60613 100644
--- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_link_superior.h
+++ b/src/Skeleton_blocker/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_
@@ -26,7 +27,7 @@
namespace Gudhi {
-namespace skbl {
+namespace skeleton_blocker {
template<class ComplexType> class Skeleton_blocker_sub_complex;
@@ -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;
@@ -44,33 +45,32 @@ class Skeleton_blocker_link_superior : public Skeleton_blocker_link_complex<
public:
typedef typename ComplexType::Vertex_handle Vertex_handle;
typedef typename ComplexType::Root_vertex_handle Root_vertex_handle;
- typedef typename ComplexType::Simplex_handle Simplex_handle;
+ typedef typename ComplexType::Simplex Simplex;
typedef typename ComplexType::Root_simplex_handle Root_simplex_handle;
typedef typename ComplexType::BlockerMap BlockerMap;
typedef typename ComplexType::BlockerPair BlockerPair;
typedef typename ComplexType::BlockerMapIterator BlockerMapIterator;
typedef typename ComplexType::BlockerMapConstIterator BlockerMapConstIterator;
- typedef typename ComplexType::Simplex_handle::Simplex_vertex_const_iterator AddressSimplexConstIterator;
+ typedef typename ComplexType::Simplex::Simplex_vertex_const_iterator AddressSimplexConstIterator;
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_handle& alpha_parent_adress)
+ 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 skbl
+} // namespace skeleton_blocker
+
+namespace skbl = skeleton_blocker;
} // namespace Gudhi
diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_off_io.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_off_io.h
index ec000986..747e60f1 100644
--- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_off_io.h
+++ b/src/Skeleton_blocker/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_
@@ -30,7 +31,7 @@
namespace Gudhi {
-namespace skbl {
+namespace skeleton_blocker {
/**
*@brief Off reader visitor that can be passed to Off_reader to read a Skeleton_blocker_complex.
@@ -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) {
@@ -61,7 +62,7 @@ class Skeleton_blocker_off_flag_visitor_reader {
if (!load_only_points_) {
for (size_t i = 0; i < face.size(); ++i)
for (size_t j = i + 1; j < face.size(); ++j) {
- complex_.add_edge(Vertex_handle(face[i]), Vertex_handle(face[j]));
+ complex_.add_edge_without_blockers(Vertex_handle(face[i]), Vertex_handle(face[j]));
}
}
}
@@ -76,12 +77,12 @@ template<typename Complex>
class Skeleton_blocker_off_visitor_reader {
Complex& complex_;
typedef typename Complex::Vertex_handle Vertex_handle;
- typedef typename Complex::Simplex_handle Simplex_handle;
+ typedef typename Complex::Simplex Simplex;
typedef typename Complex::Point Point;
const bool load_only_points_;
std::vector<Point> points_;
- std::vector<Simplex_handle> maximal_faces_;
+ std::vector<Simplex> maximal_faces_;
public:
explicit Skeleton_blocker_off_visitor_reader(Complex& complex, bool load_only_points = false) :
@@ -99,7 +100,7 @@ class Skeleton_blocker_off_visitor_reader {
void maximal_face(const std::vector<int>& face) {
if (!load_only_points_) {
- Simplex_handle s;
+ Simplex s;
for (auto x : face)
s.add_vertex(Vertex_handle(x));
maximal_faces_.emplace_back(s);
@@ -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_;
@@ -193,7 +194,9 @@ class Skeleton_blocker_off_writer {
}
};
-} // namespace skbl
+} // namespace skeleton_blocker
+
+namespace skbl = skeleton_blocker;
} // namespace Gudhi
diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_simple_geometric_traits.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_simple_geometric_traits.h
index 8508d9a5..275376e6 100644
--- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_simple_geometric_traits.h
+++ b/src/Skeleton_blocker/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_
@@ -29,7 +30,7 @@
namespace Gudhi {
-namespace skbl {
+namespace skeleton_blocker {
/**
* @extends SkeletonBlockerGeometricDS
@@ -39,7 +40,7 @@ namespace skbl {
*/
template<typename GeometryTrait>
struct Skeleton_blocker_simple_geometric_traits :
- public skbl::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_;
}
@@ -87,7 +90,9 @@ struct Skeleton_blocker_simple_geometric_traits :
typedef Skeleton_blocker_simple_traits::Graph_edge Graph_edge;
};
-} // namespace skbl
+} // namespace skeleton_blocker
+
+namespace skbl = skeleton_blocker;
} // namespace Gudhi
diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_simple_traits.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_simple_traits.h
index 0d2de767..3835cf77 100644
--- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_simple_traits.h
+++ b/src/Skeleton_blocker/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_
@@ -29,7 +30,7 @@
namespace Gudhi {
-namespace skbl {
+namespace skeleton_blocker {
/**
* @extends SkeletonBlockerDS
@@ -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,14 +174,16 @@ 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;
}
};
};
-} // namespace skbl
+} // namespace skeleton_blocker
+
+namespace skbl = skeleton_blocker;
} // namespace Gudhi
diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_simplex.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_simplex.h
index 0d838d50..aa6f2215 100644
--- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_simplex.h
+++ b/src/Skeleton_blocker/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
@@ -33,7 +33,7 @@
namespace Gudhi {
-namespace skbl {
+namespace skeleton_blocker {
/**
*@brief Abstract simplex used in Skeleton blockers data-structure.
@@ -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();
}
@@ -218,7 +215,7 @@ class Skeleton_blocker_simplex {
}
/**
- * Returns the first vertex of the (oriented) simplex.
+ * Returns the first and smallest vertex of the simplex.
*
* Be careful : assumes the simplex is non-empty.
*/
@@ -228,7 +225,7 @@ class Skeleton_blocker_simplex {
}
/**
- * Returns the last vertex of the (oriented) simplex.
+ * Returns the last and greatest vertex of the simplex.
*
* Be careful : assumes the simplex is non-empty.
*/
@@ -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) {
@@ -367,7 +365,9 @@ class Skeleton_blocker_simplex {
}
};
-} // namespace skbl
+} // namespace skeleton_blocker
+
+namespace skbl = skeleton_blocker;
} // namespace Gudhi
diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_sub_complex.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_sub_complex.h
index b33b9606..fadf6619 100644
--- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_sub_complex.h
+++ b/src/Skeleton_blocker/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
@@ -25,14 +25,14 @@
#include <gudhi/Skeleton_blocker_complex.h>
#include <gudhi/Skeleton_blocker/Skeleton_blocker_simplex.h>
-#include <gudhi/Utils.h>
+#include <gudhi/Debug_utils.h>
#include <map>
#include <vector>
namespace Gudhi {
-namespace skbl {
+namespace skeleton_blocker {
/**
* @brief Simplicial subcomplex of a complex represented by a skeleton/blockers pair.
@@ -66,12 +66,12 @@ class Skeleton_blocker_sub_complex : public ComplexType {
public:
using ComplexType::add_vertex;
- using ComplexType::add_edge;
+ using ComplexType::add_edge_without_blockers;
using ComplexType::add_blocker;
typedef typename ComplexType::Vertex_handle Vertex_handle;
typedef typename ComplexType::Root_vertex_handle Root_vertex_handle;
- typedef typename ComplexType::Simplex_handle Simplex_handle;
+ typedef typename ComplexType::Simplex Simplex;
typedef typename ComplexType::Root_simplex_handle Root_simplex_handle;
protected:
@@ -109,11 +109,11 @@ class Skeleton_blocker_sub_complex : public ComplexType {
* It assumes that both vertices corresponding to v1_root and v2_root are present
* in the sub-complex.
*/
- void add_edge(Root_vertex_handle v1_root, Root_vertex_handle v2_root) {
+ void add_edge_without_blockers(Root_vertex_handle v1_root, Root_vertex_handle v2_root) {
auto v1_sub(this->get_address(v1_root));
auto v2_sub(this->get_address(v2_root));
assert(v1_sub && v2_sub);
- this->ComplexType::add_edge(*v1_sub, *v2_sub);
+ this->ComplexType::add_edge_without_blockers(*v1_sub, *v2_sub);
}
/**
@@ -124,7 +124,7 @@ class Skeleton_blocker_sub_complex : public ComplexType {
void add_blocker(const Root_simplex_handle& blocker_root) {
auto blocker_sub = this->get_address(blocker_root);
assert(blocker_sub);
- this->add_blocker(new Simplex_handle(*blocker_sub));
+ this->add_blocker(new Simplex(*blocker_sub));
}
public:
@@ -133,7 +133,7 @@ class Skeleton_blocker_sub_complex : public ComplexType {
* vertices of 'simplex'.
*/
void make_restricted_complex(const ComplexType & parent_complex,
- const Simplex_handle& simplex) {
+ const Simplex& simplex) {
this->clear();
// add vertices to the sub complex
for (auto x : simplex) {
@@ -145,11 +145,11 @@ class Skeleton_blocker_sub_complex : public ComplexType {
// add edges to the sub complex
for (auto x : simplex) {
// x_neigh is the neighbor of x intersected with vertices_simplex
- Simplex_handle x_neigh;
+ Simplex x_neigh;
parent_complex.add_neighbours(x, x_neigh, true);
x_neigh.intersection(simplex);
for (auto y : x_neigh) {
- this->add_edge(parent_complex[x].get_id(), parent_complex[y].get_id());
+ this->add_edge_without_blockers(parent_complex[x].get_id(), parent_complex[y].get_id());
}
}
@@ -158,9 +158,9 @@ class Skeleton_blocker_sub_complex : public ComplexType {
// check if it is the first time we encounter the blocker
if (simplex.contains(*blocker)) {
Root_simplex_handle blocker_root(parent_complex.get_id(*(blocker)));
- Simplex_handle blocker_restr(
- *(this->get_simplex_address(blocker_root)));
- this->add_blocker(new Simplex_handle(blocker_restr));
+ Simplex blocker_restr(
+ *(this->get_simplex_address(blocker_root)));
+ this->add_blocker(new Simplex(blocker_restr));
}
}
}
@@ -188,16 +188,17 @@ class Skeleton_blocker_sub_complex : public ComplexType {
// * Allocates a simplex in L corresponding to the simplex s in K
// * with its local adresses and returns an AddressSimplex.
// */
- // boost::optional<Simplex_handle> get_address(const Root_simplex_handle & s) const;
+ // 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_handle sigma_in_link;
- for (int i = 0; i < addresses_sigma_in_link.size(); ++i) {
+ typename ComplexType::Simplex sigma_in_link;
+ 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)) {
@@ -282,9 +264,10 @@ bool proper_faces_in_union(
return true;
}
-} // namespace skbl
+} // namespace skeleton_blocker
+
+namespace skbl = skeleton_blocker;
} // namespace Gudhi
#endif // SKELETON_BLOCKER_SKELETON_BLOCKER_SUB_COMPLEX_H_
-
diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/internal/Top_faces.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/internal/Top_faces.h
index eb970195..2b681752 100644
--- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/internal/Top_faces.h
+++ b/src/Skeleton_blocker/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_
@@ -28,7 +29,7 @@
namespace Gudhi {
-namespace skbl {
+namespace skeleton_blocker {
template<typename SimplexHandle>
std::list<SimplexHandle> subfaces(SimplexHandle top_face) {
@@ -63,8 +64,10 @@ void register_faces(std::vector< std::set<SimplexHandle> >& simplices_per_dimens
}
}
-} // namespace skbl
+} // namespace skeleton_blocker
+
+namespace skbl = skeleton_blocker;
} // namespace Gudhi
-#endif // SKELETON_BLOCKER_INTERNAL_TOP_FACES_H_
+#endif // SKELETON_BLOCKER_INTERNAL_TOP_FACES_H_
diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/internal/Trie.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/internal/Trie.h
index aa0416ef..2c9602fa 100644
--- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/internal/Trie.h
+++ b/src/Skeleton_blocker/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_
@@ -32,11 +31,11 @@
namespace Gudhi {
-namespace skbl {
+namespace skeleton_blocker {
template<typename SimplexHandle>
struct Trie {
- typedef SimplexHandle Simplex_handle;
+ typedef SimplexHandle Simplex;
typedef typename SimplexHandle::Vertex_handle Vertex_handle;
Vertex_handle v;
@@ -64,7 +63,7 @@ struct Trie {
}
}
- typedef typename Simplex_handle::Simplex_vertex_const_iterator Simplex_vertex_const_iterator;
+ typedef typename Simplex::Simplex_vertex_const_iterator Simplex_vertex_const_iterator;
Trie* make_trie(Simplex_vertex_const_iterator s_it, Simplex_vertex_const_iterator s_end) {
if (s_it == s_end) {
@@ -97,7 +96,7 @@ struct Trie {
return;
}
- void maximal_faces_helper(std::vector<Simplex_handle>& res) const {
+ void maximal_faces_helper(std::vector<Simplex>& res) const {
if (is_leaf()) res.push_back(simplex());
else
for (auto child : childs)
@@ -108,14 +107,14 @@ struct Trie {
/**
* adds the simplex to the trie
*/
- void add_simplex(const Simplex_handle& s) {
+ void add_simplex(const Simplex& s) {
if (s.empty()) return;
assert(v == s.first_vertex());
add_simplex_helper(s.begin(), s.end());
}
- std::vector<Simplex_handle> maximal_faces() const {
- std::vector<Simplex_handle> res;
+ std::vector<Simplex> maximal_faces() const {
+ std::vector<Simplex> res;
maximal_faces_helper(res);
return res;
}
@@ -123,14 +122,14 @@ struct Trie {
/**
* Goes to the root in the trie to consitute simplex
*/
- void add_vertices_up_to_the_root(Simplex_handle& res) const {
+ void add_vertices_up_to_the_root(Simplex& res) const {
res.add_vertex(v);
if (parent_)
parent_->add_vertices_up_to_the_root(res);
}
- Simplex_handle simplex() const {
- Simplex_handle res;
+ Simplex simplex() const {
+ Simplex res;
add_vertices_up_to_the_root(res);
return res;
}
@@ -148,7 +147,7 @@ struct Trie {
}
void remove_leaf() {
- assert(is_leaf);
+ assert(is_leaf());
if (!is_root())
parent_->childs.erase(this);
}
@@ -156,7 +155,7 @@ struct Trie {
/**
* true iff the simplex corresponds to one node in the trie
*/
- bool contains(const Simplex_handle& s) const {
+ bool contains(const Simplex& s) const {
Trie const* current = this;
if (s.empty()) return true;
if (current->v != s.first_vertex()) return false;
@@ -196,9 +195,9 @@ struct Trie {
template<typename SimplexHandle>
struct Tries {
typedef typename SimplexHandle::Vertex_handle Vertex_handle;
- typedef SimplexHandle Simplex_handle;
+ typedef SimplexHandle Simplex;
- typedef Trie<Simplex_handle> STrie;
+ typedef Trie<Simplex> STrie;
template<typename SimpleHandleOutputIterator>
Tries(unsigned num_vertices, SimpleHandleOutputIterator simplex_begin, SimpleHandleOutputIterator simplex_end) :
@@ -218,14 +217,14 @@ struct Tries {
// return a simplex that consists in all u such uv is an edge and u>v
- Simplex_handle positive_neighbors(Vertex_handle v) const {
- Simplex_handle res;
+ Simplex positive_neighbors(Vertex_handle v) const {
+ Simplex res;
for (auto child : cofaces_[v]->childs)
res.add_vertex(child->v);
return res;
}
- bool contains(const Simplex_handle& s) const {
+ bool contains(const Simplex& s) const {
auto first_v = s.first_vertex();
return cofaces_[first_v]->contains(s);
}
@@ -238,9 +237,9 @@ struct Tries {
// init_next_dimension must be called first
- std::vector<Simplex_handle> next_dimension_simplices() const {
- std::vector<Simplex_handle> res;
- while (!to_see_.empty() && to_see_.front()->simplex().dimension() == current_dimension_) {
+ std::vector<Simplex> next_dimension_simplices() const {
+ std::vector<Simplex> res;
+ 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,11 +256,13 @@ struct Tries {
private:
mutable std::deque<STrie*> to_see_;
- mutable unsigned current_dimension_ = 0;
+ mutable int current_dimension_ = 0;
std::vector<STrie*> cofaces_;
};
-} // namespace skbl
+} // namespace skeleton_blocker
+
+namespace skbl = skeleton_blocker;
} // namespace Gudhi
diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_blockers_iterators.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_blockers_iterators.h
index 56a20a24..d2fff960 100644
--- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_blockers_iterators.h
+++ b/src/Skeleton_blocker/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_
@@ -26,12 +27,12 @@
namespace Gudhi {
-namespace skbl {
+namespace skeleton_blocker {
/**
* @brief Iterator through the blockers of a vertex.
*/
-// ReturnType = const Simplex_handle* or Simplex_handle*
+// ReturnType = const Simplex* or Simplex*
// MapIteratorType = BlockerMapConstIterator or BlockerMapIterator
template<typename MapIteratorType, typename ReturnType>
@@ -83,7 +84,7 @@ ReturnType
/**
* @brief Iterator through the blockers of a vertex
*/
-// ReturnType = const Simplex_handle* or Simplex_handle*
+// ReturnType = const Simplex* or Simplex*
// MapIteratorType = BlockerMapConstIterator or BlockerMapIterator
template<typename MapIteratorType, typename ReturnType>
@@ -124,7 +125,9 @@ ReturnType
}
};
-} // namespace skbl
+} // namespace skeleton_blocker
+
+namespace skbl = skeleton_blocker;
} // namespace Gudhi
diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_edges_iterators.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_edges_iterators.h
index ef4c7970..b90dcf34 100644
--- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_edges_iterators.h
+++ b/src/Skeleton_blocker/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_
@@ -29,7 +30,7 @@
namespace Gudhi {
-namespace skbl {
+namespace skeleton_blocker {
template<typename SkeletonBlockerComplex>
class Edge_around_vertex_iterator : public boost::iterator_facade <Edge_around_vertex_iterator<SkeletonBlockerComplex>
@@ -137,7 +138,9 @@ class Edge_iterator : public boost::iterator_facade <Edge_iterator<SkeletonBlock
}
};
-} // namespace skbl
+} // namespace skeleton_blocker
+
+namespace skbl = skeleton_blocker;
} // namespace Gudhi
diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_iterators.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_iterators.h
index cc3ed276..1351614f 100644
--- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_iterators.h
+++ b/src/Skeleton_blocker/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/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_simplices_iterators.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_simplices_iterators.h
index 4d71b3f5..2acdb555 100644
--- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_simplices_iterators.h
+++ b/src/Skeleton_blocker/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,13 +19,14 @@
* 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_
#include <gudhi/Skeleton_blocker_link_complex.h>
#include <gudhi/Skeleton_blocker/Skeleton_blocker_link_superior.h>
#include <gudhi/Skeleton_blocker/internal/Trie.h>
-#include <gudhi/Utils.h>
+#include <gudhi/Debug_utils.h>
#include <boost/iterator/iterator_facade.hpp>
@@ -35,7 +36,7 @@
namespace Gudhi {
-namespace skbl {
+namespace skeleton_blocker {
/**
* Link may be Skeleton_blocker_link_complex<SkeletonBlockerComplex> to iterate over all
@@ -48,30 +49,31 @@ namespace skbl {
template<typename SkeletonBlockerComplex, typename Link>
class Simplex_around_vertex_iterator :
public boost::iterator_facade < Simplex_around_vertex_iterator<SkeletonBlockerComplex, Link>
-, typename SkeletonBlockerComplex::Simplex_handle
+, typename SkeletonBlockerComplex::Simplex
, boost::forward_traversal_tag
-, typename SkeletonBlockerComplex::Simplex_handle
+, typename SkeletonBlockerComplex::Simplex
> {
friend class boost::iterator_core_access;
typedef SkeletonBlockerComplex Complex;
typedef typename Complex::Vertex_handle Vertex_handle;
typedef typename Complex::Edge_handle Edge_handle;
- typedef typename Complex::Simplex_handle Simplex_handle;
+ typedef typename Complex::Simplex Simplex;
// Link_vertex_handle == Complex_Vertex_handle but this renaming helps avoiding confusion
typedef typename Link::Vertex_handle Link_vertex_handle;
- typedef typename Gudhi::skbl::Trie<Simplex_handle> Trie;
+ typedef typename Gudhi::skeleton_blocker::Trie<Simplex> Trie;
private:
const Complex* complex;
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()) {
+ }
}
/**
@@ -120,7 +123,7 @@ public boost::iterator_facade < Simplex_around_vertex_iterator<SkeletonBlockerCo
Trie* res = new Trie(parent_vertex(link_vh), parent);
for (Link_vertex_handle nv : link_v->vertex_range(link_vh)) {
if (link_vh < nv) {
- Simplex_handle simplex_node_plus_nv(res->simplex());
+ Simplex simplex_node_plus_nv(res->simplex());
simplex_node_plus_nv.add_vertex(parent_vertex(nv));
if (complex->contains(simplex_node_plus_nv)) {
res->add_child(build_trie(nv, res));
@@ -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;
@@ -176,13 +180,13 @@ public boost::iterator_facade < Simplex_around_vertex_iterator<SkeletonBlockerCo
}
}
- Simplex_handle dereference() const {
+ Simplex dereference() const {
assert(!nodes_to_be_seen.empty());
Trie* first_node = nodes_to_be_seen.front();
return first_node->simplex();
}
- Simplex_handle get_trie_address() const {
+ Simplex get_trie_address() const {
assert(!nodes_to_be_seen.empty());
return nodes_to_be_seen.front();
}
@@ -200,9 +204,9 @@ public boost::iterator_facade < Simplex_around_vertex_iterator<SkeletonBlockerCo
template<typename SkeletonBlockerComplex>
class Simplex_iterator :
public boost::iterator_facade < Simplex_iterator<SkeletonBlockerComplex>
-, typename SkeletonBlockerComplex::Simplex_handle
+, typename SkeletonBlockerComplex::Simplex
, boost::forward_traversal_tag
-, typename SkeletonBlockerComplex::Simplex_handle
+, typename SkeletonBlockerComplex::Simplex
> {
typedef Skeleton_blocker_link_superior<SkeletonBlockerComplex> Link;
@@ -213,7 +217,7 @@ public boost::iterator_facade < Simplex_iterator<SkeletonBlockerComplex>
typedef SkeletonBlockerComplex Complex;
typedef typename Complex::Vertex_handle Vertex_handle;
typedef typename Complex::Edge_handle Edge_handle;
- typedef typename Complex::Simplex_handle Simplex_handle;
+ typedef typename Complex::Simplex Simplex;
typedef typename Complex::Complex_vertex_iterator Complex_vertex_iterator;
typedef typename Link::Vertex_handle Link_vertex_handle;
@@ -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();
@@ -290,7 +293,7 @@ public boost::iterator_facade < Simplex_iterator<SkeletonBlockerComplex>
}
}
- Simplex_handle dereference() const {
+ Simplex dereference() const {
return current_simplex_around_current_vertex_.dereference();
}
@@ -304,7 +307,95 @@ public boost::iterator_facade < Simplex_iterator<SkeletonBlockerComplex>
}
};
-} // namespace skbl
+/**
+ * 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>
+, typename SkeletonBlockerComplex::Simplex, boost::forward_traversal_tag, typename SkeletonBlockerComplex::Simplex> {
+ friend class boost::iterator_core_access;
+ typedef SkeletonBlockerComplex Complex;
+ typedef typename Complex::Vertex_handle Vertex_handle;
+ typedef typename Complex::Edge_handle Edge_handle;
+ typedef typename Complex::Simplex Simplex;
+ typedef typename Complex::Complex_vertex_iterator Complex_vertex_iterator;
+
+ // Link_vertex_handle == Complex_Vertex_handle but this renaming helps avoiding confusion
+ typedef typename Link::Vertex_handle Link_vertex_handle;
+
+ private:
+ const Complex* complex;
+ const Simplex& sigma;
+ std::shared_ptr<Link> link;
+ Complex_vertex_iterator current_vertex;
+ Complex_vertex_iterator link_vertex_end;
+
+ public:
+ 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
+ link(new Link(*complex_, sigma_, false, true)) {
+ auto link_vertex_range = link->vertex_range();
+ current_vertex = link_vertex_range.begin();
+ link_vertex_end = link_vertex_range.end();
+ }
+
+ Simplex_coboundary_iterator(const Simplex_coboundary_iterator& other) :
+ complex(other.complex),
+ sigma(other.sigma),
+ 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) :
+ complex(complex_),
+ sigma(sigma_) {
+ // to represent an end iterator without having to build a useless link, we use
+ // the convection that link is not initialized.
+ }
+
+ private:
+ Vertex_handle parent_vertex(Link_vertex_handle link_vh) const {
+ return complex->convert_handle_from_another_complex(*link, link_vh);
+ }
+
+ public:
+ friend std::ostream& operator<<(std::ostream& stream, const Simplex_coboundary_iterator& sci) {
+ return stream;
+ }
+
+ // 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();
+ return *current_vertex == *(other.current_vertex);
+ }
+
+ void increment() {
+ ++current_vertex;
+ }
+
+ Simplex dereference() const {
+ Simplex res(sigma);
+ res.add_vertex(parent_vertex(*current_vertex));
+ return res;
+ }
+
+ private:
+ bool is_end() const {
+ return !link || current_vertex == link_vertex_end;
+ }
+};
+
+} // namespace skeleton_blocker
+
+namespace skbl = skeleton_blocker;
} // namespace Gudhi
diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_triangles_iterators.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_triangles_iterators.h
index 28f5805d..736941dd 100644
--- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_triangles_iterators.h
+++ b/src/Skeleton_blocker/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_
@@ -27,7 +28,7 @@
namespace Gudhi {
-namespace skbl {
+namespace skeleton_blocker {
/**
* \brief Iterator over the triangles that are
@@ -37,15 +38,15 @@ namespace skbl {
template<typename Complex, typename LinkType>
class Triangle_around_vertex_iterator : public boost::iterator_facade
< Triangle_around_vertex_iterator <Complex, LinkType>
-, typename Complex::Simplex_handle const
+, typename Complex::Simplex const
, boost::forward_traversal_tag
-, typename Complex::Simplex_handle const> {
+, typename Complex::Simplex const> {
friend class boost::iterator_core_access;
template<typename T> friend class Triangle_iterator;
private:
typedef typename LinkType::Vertex_handle Vertex_handle;
typedef typename LinkType::Root_vertex_handle Root_vertex_handle;
- typedef typename LinkType::Simplex_handle Simplex_handle;
+ typedef typename LinkType::Simplex Simplex;
typedef typename Complex::Complex_edge_iterator Complex_edge_iterator_;
const Complex* complex_;
@@ -87,10 +88,10 @@ class Triangle_around_vertex_iterator : public boost::iterator_facade
return (complex_ == other.complex_) && ((finished() && other.finished()) || current_edge_ == other.current_edge_);
}
- Simplex_handle dereference() const {
+ Simplex dereference() const {
Root_vertex_handle v1 = (*link_)[*current_edge_].first();
Root_vertex_handle v2 = (*link_)[*current_edge_].second();
- return Simplex_handle(v_, *(complex_->get_address(v1)), *(complex_->get_address(v2)));
+ return Simplex(v_, *(complex_->get_address(v1)), *(complex_->get_address(v2)));
}
void increment() {
@@ -112,14 +113,14 @@ class Triangle_around_vertex_iterator : public boost::iterator_facade
template<typename SkeletonBlockerComplex>
class Triangle_iterator : public boost::iterator_facade<
Triangle_iterator <SkeletonBlockerComplex>,
-typename SkeletonBlockerComplex::Simplex_handle const
+typename SkeletonBlockerComplex::Simplex const
, boost::forward_traversal_tag
-, typename SkeletonBlockerComplex::Simplex_handle const> {
+, typename SkeletonBlockerComplex::Simplex const> {
friend class boost::iterator_core_access;
private:
typedef typename SkeletonBlockerComplex::Vertex_handle Vertex_handle;
typedef typename SkeletonBlockerComplex::Root_vertex_handle Root_vertex_handle;
- typedef typename SkeletonBlockerComplex::Simplex_handle Simplex_handle;
+ typedef typename SkeletonBlockerComplex::Simplex Simplex;
typedef typename SkeletonBlockerComplex::Superior_triangle_around_vertex_iterator STAVI;
typedef typename SkeletonBlockerComplex::Complex_vertex_iterator Complex_vertex_iterator;
@@ -135,7 +136,7 @@ typename SkeletonBlockerComplex::Simplex_handle 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,10 +173,11 @@ typename SkeletonBlockerComplex::Simplex_handle 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_handle dereference() const {
+ Simplex dereference() const {
return *current_triangle_;
}
@@ -183,8 +185,10 @@ typename SkeletonBlockerComplex::Simplex_handle 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_;
@@ -213,7 +217,9 @@ typename SkeletonBlockerComplex::Simplex_handle const
}
};
-} // namespace skbl
+} // namespace skeleton_blocker
+
+namespace skbl = skeleton_blocker;
} // namespace Gudhi
diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_vertices_iterators.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_vertices_iterators.h
index 14ae136a..9e9ae961 100644
--- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_vertices_iterators.h
+++ b/src/Skeleton_blocker/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_
@@ -28,7 +29,7 @@
namespace Gudhi {
-namespace skbl {
+namespace skeleton_blocker {
/**
*@brief Iterator on the vertices of a simplicial complex
@@ -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,16 +155,16 @@ 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_;
}
};
-} // namespace skbl
+} // namespace skeleton_blocker
+
+namespace skbl = skeleton_blocker;
} // namespace Gudhi
#endif // SKELETON_BLOCKER_ITERATORS_SKELETON_BLOCKERS_VERTICES_ITERATORS_H_
-
-
diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_complex.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_complex.h
index 07f371a2..4f052ba5 100644
--- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_complex.h
+++ b/src/Skeleton_blocker/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
@@ -28,12 +28,10 @@
#include <gudhi/Skeleton_blocker/Skeleton_blocker_link_superior.h>
#include <gudhi/Skeleton_blocker/Skeleton_blocker_sub_complex.h>
#include <gudhi/Skeleton_blocker/Skeleton_blocker_simplex.h>
-
#include <gudhi/Skeleton_blocker/Skeleton_blocker_complex_visitor.h>
#include <gudhi/Skeleton_blocker/internal/Top_faces.h>
#include <gudhi/Skeleton_blocker/internal/Trie.h>
-
-#include <gudhi/Utils.h>
+#include <gudhi/Debug_utils.h>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/connected_components.hpp>
@@ -54,7 +52,7 @@
namespace Gudhi {
-namespace skbl {
+namespace skeleton_blocker {
/**
*@class Skeleton_blocker_complex
@@ -94,16 +92,16 @@ class Skeleton_blocker_complex {
/**
* @brief A ordered set of integers that represents a simplex.
*/
- typedef Skeleton_blocker_simplex<Vertex_handle> Simplex_handle;
+ typedef Skeleton_blocker_simplex<Vertex_handle> Simplex;
typedef Skeleton_blocker_simplex<Root_vertex_handle> Root_simplex_handle;
/**
* @brief Handle to a blocker of the complex.
*/
- typedef Simplex_handle* Blocker_handle;
+ typedef Simplex* Blocker_handle;
typedef typename Root_simplex_handle::Simplex_vertex_const_iterator Root_simplex_iterator;
- typedef typename Simplex_handle::Simplex_vertex_const_iterator Simplex_handle_iterator;
+ typedef typename Simplex::Simplex_vertex_const_iterator Simplex_handle_iterator;
protected:
typedef typename boost::adjacency_list<boost::setS, // edges
@@ -128,14 +126,14 @@ class Skeleton_blocker_complex {
typedef typename boost::graph_traits<Graph>::edge_descriptor Edge_handle;
protected:
- typedef std::multimap<Vertex_handle, Simplex_handle *> BlockerMap;
- typedef typename std::multimap<Vertex_handle, Simplex_handle *>::value_type BlockerPair;
- typedef typename std::multimap<Vertex_handle, Simplex_handle *>::iterator BlockerMapIterator;
- typedef typename std::multimap<Vertex_handle, Simplex_handle *>::const_iterator BlockerMapConstIterator;
+ typedef std::multimap<Vertex_handle, Simplex *> BlockerMap;
+ typedef typename std::multimap<Vertex_handle, Simplex *>::value_type BlockerPair;
+ typedef typename std::multimap<Vertex_handle, Simplex *>::iterator BlockerMapIterator;
+ typedef typename std::multimap<Vertex_handle, Simplex *>::const_iterator BlockerMapConstIterator;
protected:
- int num_vertices_;
- int num_blockers_;
+ size_t num_vertices_;
+ size_t num_blockers_;
typedef Skeleton_blocker_complex_visitor<Vertex_handle> Visitor;
// typedef Visitor* Visitor_ptr;
@@ -164,17 +162,17 @@ class Skeleton_blocker_complex {
/**
*@brief constructs a simplicial complex with a given number of vertices and a visitor.
*/
- explicit Skeleton_blocker_complex(int num_vertices_ = 0, Visitor* visitor_ = NULL)
+ explicit Skeleton_blocker_complex(size_t num_vertices_ = 0, Visitor* visitor_ = NULL)
: visitor(visitor_) {
clear();
- for (int i = 0; i < num_vertices_; ++i) {
+ for (size_t i = 0; i < num_vertices_; ++i) {
add_vertex();
}
}
private:
// typedef Trie<Skeleton_blocker_complex<SkeletonBlockerDS>> STrie;
- typedef Trie<Simplex_handle> STrie;
+ typedef Trie<Simplex> STrie;
public:
/**
@@ -182,37 +180,40 @@ class Skeleton_blocker_complex {
* @details is_flag_complex indicates if the complex is a flag complex or not (to know if blockers have to be computed or not).
*/
template<typename SimpleHandleOutputIterator>
- Skeleton_blocker_complex(SimpleHandleOutputIterator simplex_begin, SimpleHandleOutputIterator simplex_end,
+ Skeleton_blocker_complex(SimpleHandleOutputIterator simplices_begin, SimpleHandleOutputIterator simplices_end,
bool is_flag_complex = false, Visitor* visitor_ = NULL)
: num_vertices_(0),
num_blockers_(0),
visitor(visitor_) {
- add_vertex_and_edges(simplex_begin, simplex_end);
+ add_vertices_and_edges(simplices_begin, simplices_end);
if (!is_flag_complex)
// need to compute blockers
- add_blockers(simplex_begin, simplex_end);
+ add_blockers(simplices_begin, simplices_end);
}
private:
+ /**
+ * Add vertices and edges of a simplex in one pass
+ */
template<typename SimpleHandleOutputIterator>
- void add_vertex_and_edges(SimpleHandleOutputIterator simplex_begin, SimpleHandleOutputIterator simplex_end) {
+ void add_vertices_and_edges(SimpleHandleOutputIterator simplices_begin, SimpleHandleOutputIterator simplices_end) {
std::vector<std::pair<Vertex_handle, Vertex_handle>> edges;
// first pass to add vertices and edges
int num_vertex = -1;
- for (auto s_it = simplex_begin; s_it != simplex_end; ++s_it) {
+ for (auto s_it = simplices_begin; s_it != simplices_end; ++s_it) {
if (s_it->dimension() == 0) num_vertex = (std::max)(num_vertex, s_it->first_vertex().vertex);
if (s_it->dimension() == 1) edges.emplace_back(s_it->first_vertex(), s_it->last_vertex());
}
while (num_vertex-- >= 0) add_vertex();
for (const auto& e : edges)
- add_edge(e.first, e.second);
+ add_edge_without_blockers(e.first, e.second);
}
template<typename SimpleHandleOutputIterator>
- void add_blockers(SimpleHandleOutputIterator simplex_begin, SimpleHandleOutputIterator simplex_end) {
- Tries<Simplex_handle> tries(num_vertices(), simplex_begin, simplex_end);
+ void add_blockers(SimpleHandleOutputIterator simplices_begin, SimpleHandleOutputIterator simplices_end) {
+ Tries<Simplex> tries(num_vertices(), simplices_begin, simplices_end);
tries.init_next_dimension();
auto simplices(tries.next_dimension_simplices());
@@ -221,7 +222,7 @@ class Skeleton_blocker_complex {
for (auto& sigma : simplices) {
// common_positive_neighbors is the set of vertices u such that
// for all s in sigma, us is an edge and u>s
- Simplex_handle common_positive_neighbors(tries.positive_neighbors(sigma.last_vertex()));
+ Simplex common_positive_neighbors(tries.positive_neighbors(sigma.last_vertex()));
for (auto sigma_it = sigma.rbegin(); sigma_it != sigma.rend(); ++sigma_it)
if (sigma_it != sigma.rbegin())
common_positive_neighbors.intersection(tries.positive_neighbors(*sigma_it));
@@ -378,6 +379,7 @@ class Skeleton_blocker_complex {
/**
* @brief Adds a vertex to the simplicial complex and returns its Vertex_handle.
+ * @remark Vertex representation is contiguous.
*/
Vertex_handle add_vertex() {
Vertex_handle address(boost::add_vertex(skeleton));
@@ -411,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();
}
@@ -427,7 +430,7 @@ class Skeleton_blocker_complex {
* @return true iff the simplicial complex contains all vertices
* of simplex sigma
*/
- bool contains_vertices(const Simplex_handle & sigma) const {
+ bool contains_vertices(const Simplex & sigma) const {
for (auto vertex : sigma)
if (!contains_vertex(vertex))
return false;
@@ -438,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;
}
@@ -535,41 +538,67 @@ class Skeleton_blocker_complex {
* @details it assumes that the edge is present in the complex
*/
- Simplex_handle get_vertices(Edge_handle edge_handle) const {
+ Simplex get_vertices(Edge_handle edge_handle) const {
auto edge((*this)[edge_handle]);
- return Simplex_handle((*this)[edge.first()], (*this)[edge.second()]);
+ return Simplex((*this)[edge.first()], (*this)[edge.second()]);
}
/**
- * @brief Adds an edge between vertices a and b and all its cofaces.
+ * @brief Adds an edge between vertices a and b.
+ * @details For instance, the complex contains edge 01 and 12, then calling
+ * add_edge with vertex 0 and 2 will create a complex containing
+ * the edges 01, 12, 20 but not the triangle 012 (and hence this complex
+ * will contains a blocker 012).
*/
Edge_handle add_edge(Vertex_handle a, Vertex_handle b) {
+ // if the edge is already there we musnt go further
+ // as we may add blockers that should not be here
+ if (contains_edge(a, b))
+ return *((*this)[std::make_pair(a, b)]);
+ auto res = add_edge_without_blockers(a, b);
+ add_blockers_after_simplex_insertion(Simplex(a, b));
+ return res;
+ }
+
+ /**
+ * @brief Adds all edges of s in the complex.
+ */
+ void add_edge(const Simplex& s) {
+ for (auto i = s.begin(); i != s.end(); ++i)
+ for (auto j = i; ++j != s.end(); /**/)
+ add_edge(*i, *j);
+ }
+
+ /**
+ * @brief Adds an edge between vertices a and b without blockers.
+ * @details For instance, the complex contains edge 01 and 12, then calling
+ * add_edge with vertex 0 and 2 will create a complex containing
+ * the triangle 012.
+ */
+ Edge_handle add_edge_without_blockers(Vertex_handle a, Vertex_handle b) {
assert(contains_vertex(a) && contains_vertex(b));
assert(a != b);
auto edge_handle((*this)[std::make_pair(a, b)]);
- // std::pair<Edge_handle,bool> pair_descr_bool = (*this)[std::make_pair(a,b)];
- // Edge_handle edge_descr;
- // bool edge_present = pair_descr_bool.second;
if (!edge_handle) {
edge_handle = boost::add_edge(a.vertex, b.vertex, skeleton).first;
(*this)[*edge_handle].setId(get_id(a), get_id(b));
degree_[a.vertex]++;
degree_[b.vertex]++;
if (visitor)
- visitor->on_add_edge(a, b);
+ visitor->on_add_edge_without_blockers(a, b);
}
return *edge_handle;
}
/**
- * @brief Adds all edges and their cofaces of a simplex to the simplicial complex.
+ * @brief Adds all edges of s in the complex without adding blockers.
*/
- void add_edges(const Simplex_handle & sigma) {
- Simplex_handle_iterator i, j;
- for (i = sigma.begin(); i != sigma.end(); ++i)
- for (j = i, j++; j != sigma.end(); ++j)
- add_edge(*i, *j);
+ void add_edge_without_blockers(Simplex s) {
+ for (auto i = s.begin(); i != s.end(); ++i) {
+ for (auto j = i; ++j != s.end(); /**/)
+ add_edge_without_blockers(*i, *j);
+ }
}
/**
@@ -627,7 +656,7 @@ class Skeleton_blocker_complex {
* @return true iff the simplicial complex contains all vertices
* and all edges of simplex sigma
*/
- bool contains_edges(const Simplex_handle & sigma) const {
+ bool contains_edges(const Simplex & sigma) const {
for (auto i = sigma.begin(); i != sigma.end(); ++i) {
if (!contains_vertex(*i))
return false;
@@ -649,15 +678,14 @@ class Skeleton_blocker_complex {
* @brief Adds the simplex to the set of blockers and
* returns a Blocker_handle toward it if was not present before and 0 otherwise.
*/
- Blocker_handle add_blocker(const Simplex_handle& blocker) {
+ Blocker_handle add_blocker(const Simplex& blocker) {
assert(blocker.dimension() > 1);
if (contains_blocker(blocker)) {
- // std::cerr << "ATTEMPT TO ADD A BLOCKER ALREADY THERE ---> BLOCKER IGNORED" << endl;
return 0;
} else {
if (visitor)
visitor->on_add_blocker(blocker);
- Blocker_handle blocker_pt = new Simplex_handle(blocker);
+ Blocker_handle blocker_pt = new Simplex(blocker);
num_blockers_++;
auto vertex = blocker_pt->begin();
while (vertex != blocker_pt->end()) {
@@ -739,7 +767,7 @@ class Skeleton_blocker_complex {
*
* @remark contrarily to delete_blockers does not call the destructor
*/
- void remove_blocker(const Simplex_handle& sigma) {
+ void remove_blocker(const Simplex& sigma) {
assert(contains_blocker(sigma));
for (auto vertex : sigma)
remove_blocker(sigma, vertex);
@@ -777,7 +805,7 @@ class Skeleton_blocker_complex {
/**
* @return true iff s is a blocker of the simplicial complex
*/
- bool contains_blocker(const Simplex_handle & s) const {
+ bool contains_blocker(const Simplex & s) const {
if (s.dimension() < 2)
return false;
@@ -795,7 +823,7 @@ class Skeleton_blocker_complex {
* @return true iff a blocker of the simplicial complex
* is a face of sigma.
*/
- bool blocks(const Simplex_handle & sigma) const {
+ bool blocks(const Simplex & sigma) const {
for (auto s : sigma)
for (auto blocker : const_blocker_range(s))
if (sigma.contains(*blocker))
@@ -810,17 +838,18 @@ class Skeleton_blocker_complex {
* @details Adds to simplex the neighbours of v e.g. \f$ n \leftarrow n \cup N(v) \f$.
* If keep_only_superior is true then only vertices that are greater than v are added.
*/
- virtual void add_neighbours(Vertex_handle v, Simplex_handle & n,
+ virtual void add_neighbours(Vertex_handle v, Simplex & n,
bool keep_only_superior = false) const {
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);
}
}
}
@@ -833,7 +862,7 @@ class Skeleton_blocker_complex {
* todo revoir
*
*/
- virtual void add_neighbours(const Simplex_handle &alpha, Simplex_handle & res,
+ virtual void add_neighbours(const Simplex &alpha, Simplex & res,
bool keep_only_superior = false) const {
res.clear();
auto alpha_vertex = alpha.begin();
@@ -848,9 +877,9 @@ class Skeleton_blocker_complex {
* not neighbours of v e.g. \f$ res \leftarrow res \cap N(v) \f$.
* If 'keep_only_superior' is true then only vertices that are greater than v are keeped.
*/
- virtual void keep_neighbours(Vertex_handle v, Simplex_handle& res,
+ virtual void keep_neighbours(Vertex_handle v, Simplex& res,
bool keep_only_superior = false) const {
- Simplex_handle nv;
+ Simplex nv;
add_neighbours(v, nv, keep_only_superior);
res.intersection(nv);
}
@@ -860,9 +889,9 @@ class Skeleton_blocker_complex {
* neighbours of v eg \f$ res \leftarrow res \setminus N(v) \f$.
* If 'keep_only_superior' is true then only vertices that are greater than v are added.
*/
- virtual void remove_neighbours(Vertex_handle v, Simplex_handle & res,
+ virtual void remove_neighbours(Vertex_handle v, Simplex & res,
bool keep_only_superior = false) const {
- Simplex_handle nv;
+ Simplex nv;
add_neighbours(v, nv, keep_only_superior);
res.difference(nv);
}
@@ -874,7 +903,7 @@ class Skeleton_blocker_complex {
* Constructs the link of 'simplex' with points coordinates.
*/
Link_complex link(Vertex_handle v) const {
- return Link_complex(*this, Simplex_handle(v));
+ return Link_complex(*this, Simplex(v));
}
/**
@@ -887,7 +916,7 @@ class Skeleton_blocker_complex {
/**
* Constructs the link of 'simplex' with points coordinates.
*/
- Link_complex link(const Simplex_handle& simplex) const {
+ Link_complex link(const Simplex& simplex) const {
return Link_complex(*this, simplex);
}
@@ -899,11 +928,11 @@ class Skeleton_blocker_complex {
*/
// xxx rename get_address et place un using dans sub_complex
- boost::optional<Simplex_handle> get_simplex_address(
- const Root_simplex_handle& s) const {
- boost::optional<Simplex_handle> res;
+ boost::optional<Simplex> get_simplex_address(
+ const Root_simplex_handle& s) const {
+ boost::optional<Simplex> res;
- Simplex_handle s_address;
+ Simplex s_address;
// Root_simplex_const_iterator i;
for (auto i = s.begin(); i != s.end(); ++i) {
boost::optional<Vertex_handle> address = get_address(*i);
@@ -920,7 +949,7 @@ class Skeleton_blocker_complex {
* @brief returns a simplex with vertices which are the id of vertices of the
* argument.
*/
- Root_simplex_handle get_id(const Simplex_handle& local_simplex) const {
+ Root_simplex_handle get_id(const Simplex& local_simplex) const {
Root_simplex_handle global_simplex;
for (auto x = local_simplex.begin(); x != local_simplex.end(); ++x) {
global_simplex.add_vertex(get_id(*x));
@@ -932,7 +961,7 @@ class Skeleton_blocker_complex {
* @brief returns true iff the simplex s belongs to the simplicial
* complex.
*/
- virtual bool contains(const Simplex_handle & s) const {
+ virtual bool contains(const Simplex & s) const {
if (s.dimension() == -1) {
return false;
} else if (s.dimension() == 0) {
@@ -973,9 +1002,29 @@ class Skeleton_blocker_complex {
}
/*
+ * @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());
+ }
+
+ /*
+ * @brief returns the number of simplices of a given dimension in the complex.
+ */
+ size_t num_simplices(int dimension) const {
+ // TODO(DS): iterator on k-simplices
+ size_t res = 0;
+ for (const auto& s : complex_simplex_range())
+ if (s.dimension() == dimension)
+ ++res;
+ return res;
+ }
+
+ /*
* @brief returns the number of blockers in the complex.
*/
- int num_blockers() const {
+ size_t num_blockers() const {
return num_blockers_;
}
@@ -1018,7 +1067,7 @@ class Skeleton_blocker_complex {
}
//@}
- /** @Simplification operations
+ /** @name Simplification operations
*/
//@{
@@ -1061,7 +1110,7 @@ class Skeleton_blocker_complex {
* Furthermore, all simplices tau of the form sigma \setminus simplex_to_be_removed must be added
* whenever the dimension of tau is at least 2.
*/
- void update_blockers_after_remove_star_of_vertex_or_edge(const Simplex_handle& simplex_to_be_removed);
+ void update_blockers_after_remove_star_of_vertex_or_edge(const Simplex& simplex_to_be_removed);
public:
/**
@@ -1078,31 +1127,33 @@ class Skeleton_blocker_complex {
/**
* Remove the star of the simplex 'sigma' which needs to belong to the complex
*/
- void remove_star(const Simplex_handle& sigma);
+ void remove_star(const Simplex& sigma);
/**
- * @brief add a maximal simplex plus all its cofaces.
- * @details the simplex must have dimension greater than one (otherwise use add_vertex or add_edge).
+ * @brief add a simplex and all its faces.
+ * @details the simplex must have dimension greater than one (otherwise use add_vertex or add_edge_without_blockers).
*/
- void add_simplex(const Simplex_handle& sigma);
+ void add_simplex(const Simplex& sigma);
private:
+ void add_blockers_after_simplex_insertion(Simplex s);
+
/**
* remove all blockers that contains sigma
*/
- void remove_blocker_containing_simplex(const Simplex_handle& sigma);
+ void remove_blocker_containing_simplex(const Simplex& sigma);
/**
* remove all blockers that contains sigma
*/
- void remove_blocker_include_in_simplex(const Simplex_handle& sigma);
+ void remove_blocker_include_in_simplex(const Simplex& sigma);
public:
enum simplifiable_status {
NOT_HOMOTOPY_EQ, MAYBE_HOMOTOPY_EQ, HOMOTOPY_EQ
};
- simplifiable_status is_remove_star_homotopy_preserving(const Simplex_handle& simplex) {
+ simplifiable_status is_remove_star_homotopy_preserving(const Simplex& simplex) {
// todo write a virtual method 'link' in Skeleton_blocker_complex which will be overloaded by the current one of
// Skeleton_blocker_geometric_complex
// then call it there to build the link and return the value of link.is_contractible()
@@ -1131,7 +1182,7 @@ class Skeleton_blocker_complex {
}
//@}
- /** @Edge contraction operations
+ /** @name Edge contraction operations
*/
//@{
@@ -1174,7 +1225,7 @@ class Skeleton_blocker_complex {
* that may be used to construct a new blocker after contracting ab.
* It requires that the link condition is satisfied.
*/
- void tip_blockers(Vertex_handle a, Vertex_handle b, std::vector<Simplex_handle> & buffer) const;
+ void tip_blockers(Vertex_handle a, Vertex_handle b, std::vector<Simplex> & buffer) const;
private:
/**
@@ -1217,7 +1268,7 @@ class Skeleton_blocker_complex {
private:
void get_blockers_to_be_added_after_contraction(Vertex_handle a, Vertex_handle b,
- std::set<Simplex_handle>& blockers_to_add);
+ std::set<Simplex>& blockers_to_add);
/**
* delete all blockers that passes through a or b
*/
@@ -1358,12 +1409,28 @@ class Skeleton_blocker_complex {
/**
* @brief Returns a Complex_simplex_around_vertex_range over all the simplices around a vertex of the complex
*/
- Complex_simplex_around_vertex_range simplex_range(Vertex_handle v) const {
+ Complex_simplex_around_vertex_range star_simplex_range(Vertex_handle v) const {
assert(contains_vertex(v));
return Complex_simplex_around_vertex_range(
Complex_simplex_around_vertex_iterator(this, v),
Complex_simplex_around_vertex_iterator(this, v, true));
}
+ typedef Simplex_coboundary_iterator<Skeleton_blocker_complex, Link> Complex_simplex_coboundary_iterator;
+
+ /**
+ * @brief Range over the simplices of the coboundary of a simplex.
+ * Methods .begin() and .end() return a Complex_simplex_coboundary_iterator.
+ */
+ typedef boost::iterator_range < Complex_simplex_coboundary_iterator > Complex_coboundary_range;
+
+ /**
+ * @brief Returns a Complex_simplex_coboundary_iterator over the simplices of the coboundary of a simplex.
+ */
+ Complex_coboundary_range coboundary_range(const Simplex& s) const {
+ assert(contains(s));
+ return Complex_coboundary_range(Complex_simplex_coboundary_iterator(this, s),
+ Complex_simplex_coboundary_iterator(this, s, true));
+ }
// typedef Simplex_iterator<Skeleton_blocker_complex,Superior_link> Complex_simplex_iterator;
typedef Simplex_iterator<Skeleton_blocker_complex> Complex_simplex_iterator;
@@ -1373,7 +1440,7 @@ class Skeleton_blocker_complex {
/**
* @brief Returns a Complex_simplex_range over all the simplices of the complex
*/
- Complex_simplex_range simplex_range() const {
+ Complex_simplex_range complex_simplex_range() const {
Complex_simplex_iterator end(this, true);
if (empty()) {
return Complex_simplex_range(end, end);
@@ -1393,7 +1460,7 @@ class Skeleton_blocker_complex {
* @brief Iterator over the blockers adjacent to a vertex
*/
typedef Blocker_iterator_around_vertex_internal<
- typename std::multimap<Vertex_handle, Simplex_handle *>::iterator,
+ typename std::multimap<Vertex_handle, Simplex *>::iterator,
Blocker_handle>
Complex_blocker_around_vertex_iterator;
@@ -1401,7 +1468,7 @@ class Skeleton_blocker_complex {
* @brief Iterator over (constant) blockers adjacent to a vertex
*/
typedef Blocker_iterator_around_vertex_internal<
- typename std::multimap<Vertex_handle, Simplex_handle *>::const_iterator,
+ typename std::multimap<Vertex_handle, Simplex *>::const_iterator,
const Blocker_handle>
Const_complex_blocker_around_vertex_iterator;
@@ -1433,7 +1500,7 @@ class Skeleton_blocker_complex {
* @brief Iterator over the blockers.
*/
typedef Blocker_iterator_internal<
- typename std::multimap<Vertex_handle, Simplex_handle *>::iterator,
+ typename std::multimap<Vertex_handle, Simplex *>::iterator,
Blocker_handle>
Complex_blocker_iterator;
@@ -1441,7 +1508,7 @@ class Skeleton_blocker_complex {
* @brief Iterator over the (constant) blockers.
*/
typedef Blocker_iterator_internal<
- typename std::multimap<Vertex_handle, Simplex_handle *>::const_iterator,
+ typename std::multimap<Vertex_handle, Simplex *>::const_iterator,
const Blocker_handle>
Const_complex_blocker_iterator;
@@ -1515,18 +1582,21 @@ class Skeleton_blocker_complex {
* return the total number of simplices
*/
template<typename Complex, typename SimplexHandleIterator>
-Complex make_complex_from_top_faces(SimplexHandleIterator simplex_begin, SimplexHandleIterator simplex_end,
+Complex make_complex_from_top_faces(SimplexHandleIterator simplices_begin, SimplexHandleIterator simplices_end,
bool is_flag_complex = false) {
- typedef typename Complex::Simplex_handle Simplex_handle;
- std::vector<Simplex_handle> simplices;
- for (auto top_face = simplex_begin; top_face != simplex_end; ++top_face) {
+ // TODO(DS): use add_simplex instead! should be more efficient and more elegant :)
+ typedef typename Complex::Simplex Simplex;
+ std::vector<Simplex> simplices;
+ for (auto top_face = simplices_begin; top_face != simplices_end; ++top_face) {
auto subfaces_topface = subfaces(*top_face);
simplices.insert(simplices.end(), subfaces_topface.begin(), subfaces_topface.end());
}
return Complex(simplices.begin(), simplices.end(), is_flag_complex);
}
-} // namespace skbl
+} // namespace skeleton_blocker
+
+namespace skbl = skeleton_blocker;
} // namespace Gudhi
diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_geometric_complex.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_geometric_complex.h
index b8395251..95331b7a 100644
--- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_geometric_complex.h
+++ b/src/Skeleton_blocker/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,16 +19,17 @@
* 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_
-#include <gudhi/Utils.h>
#include <gudhi/Skeleton_blocker_complex.h>
#include <gudhi/Skeleton_blocker/Skeleton_blocker_sub_complex.h>
+#include <gudhi/Debug_utils.h>
namespace Gudhi {
-namespace skbl {
+namespace skeleton_blocker {
/**
* @brief Class that represents a geometric complex that can be simplified.
@@ -46,7 +47,7 @@ public Skeleton_blocker_complex<SkeletonBlockerGeometricDS> {
typedef typename SimplifiableSkeletonblocker::Vertex_handle Vertex_handle;
typedef typename SimplifiableSkeletonblocker::Root_vertex_handle Root_vertex_handle;
typedef typename SimplifiableSkeletonblocker::Edge_handle Edge_handle;
- typedef typename SimplifiableSkeletonblocker::Simplex_handle Simplex_handle;
+ typedef typename SimplifiableSkeletonblocker::Simplex Simplex;
typedef typename SimplifiableSkeletonblocker::Graph_vertex Graph_vertex;
@@ -140,7 +141,7 @@ public Skeleton_blocker_complex<SkeletonBlockerGeometricDS> {
* Constructs the link of 'simplex' with points coordinates.
*/
Geometric_link link(Vertex_handle v) const {
- Geometric_link link(*this, Simplex_handle(v));
+ Geometric_link link(*this, Simplex(v));
// we now add the point info
add_points_to_link(link);
return link;
@@ -149,7 +150,7 @@ public Skeleton_blocker_complex<SkeletonBlockerGeometricDS> {
/**
* Constructs the link of 'simplex' with points coordinates.
*/
- Geometric_link link(const Simplex_handle& simplex) const {
+ Geometric_link link(const Simplex& simplex) const {
Geometric_link link(*this, simplex);
// we now add the point info
add_points_to_link(link);
@@ -172,13 +173,13 @@ public Skeleton_blocker_complex<SkeletonBlockerGeometricDS> {
* Constructs the abstract link of v (without points coordinates).
*/
Abstract_link abstract_link(Vertex_handle v) const {
- return Abstract_link(*this, Simplex_handle(v));
+ return Abstract_link(*this, Simplex(v));
}
/**
* Constructs the link of 'simplex' with points coordinates.
*/
- Abstract_link abstract_link(const Simplex_handle& simplex) const {
+ Abstract_link abstract_link(const Simplex& simplex) const {
return Abstract_link(*this, simplex);
}
@@ -217,7 +218,9 @@ SkeletonBlockerGeometricComplex make_complex_from_top_faces(
return complex;
}
-} // namespace skbl
+} // namespace skeleton_blocker
+
+namespace skbl = skeleton_blocker;
} // namespace Gudhi
diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_link_complex.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_link_complex.h
index 95d8fa97..4db075b0 100644
--- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_link_complex.h
+++ b/src/Skeleton_blocker/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,15 +19,16 @@
* 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_
-#include <gudhi/Utils.h>
#include <gudhi/Skeleton_blocker_complex.h>
+#include <gudhi/Debug_utils.h>
namespace Gudhi {
-namespace skbl {
+namespace skeleton_blocker {
template<class ComplexType> class Skeleton_blocker_sub_complex;
@@ -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;
@@ -52,28 +53,28 @@ class Skeleton_blocker_link_complex : public Skeleton_blocker_sub_complex<
typedef typename ComplexType::Vertex_handle Vertex_handle;
typedef typename ComplexType::Root_vertex_handle Root_vertex_handle;
- typedef typename ComplexType::Simplex_handle Simplex_handle;
+ typedef typename ComplexType::Simplex Simplex;
typedef typename ComplexType::Root_simplex_handle Root_simplex_handle;
typedef typename ComplexType::Blocker_handle Blocker_handle;
- typedef typename ComplexType::Simplex_handle::Simplex_vertex_const_iterator Simplex_handle_iterator;
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,
* only vertices greater than the one of alpha are added.
+ * Only vertices are computed if only_vertices is true.
*/
Skeleton_blocker_link_complex(const ComplexType & parent_complex,
- const Simplex_handle& alpha_parent_adress,
- bool only_superior_vertices = false)
+ const Simplex& alpha_parent_adress,
+ bool only_superior_vertices = false,
+ bool only_vertices = false)
: only_superior_vertices_(only_superior_vertices) {
if (!alpha_parent_adress.empty())
- build_link(parent_complex, alpha_parent_adress);
+ build_link(parent_complex, alpha_parent_adress, only_vertices);
}
/**
@@ -84,7 +85,7 @@ class Skeleton_blocker_link_complex : public Skeleton_blocker_sub_complex<
Vertex_handle a_parent_adress,
bool only_superior_vertices = false)
: only_superior_vertices_(only_superior_vertices) {
- Simplex_handle alpha_simplex(a_parent_adress);
+ Simplex alpha_simplex(a_parent_adress);
build_link(parent_complex, alpha_simplex);
}
@@ -94,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_handle alpha_simplex(parent_complex.first_vertex(edge),
- parent_complex.second_vertex(edge));
+ Simplex alpha_simplex(parent_complex.first_vertex(edge),
+ parent_complex.second_vertex(edge));
build_link(parent_complex, alpha_simplex);
}
@@ -108,7 +109,7 @@ class Skeleton_blocker_link_complex : public Skeleton_blocker_sub_complex<
* are greater than vertices of alpha_parent_adress are added.
*/
void compute_link_vertices(const ComplexType & parent_complex,
- const Simplex_handle& alpha_parent_adress,
+ const Simplex& alpha_parent_adress,
bool only_superior_vertices,
bool is_alpha_blocker = false) {
if (alpha_parent_adress.dimension() == 0) {
@@ -119,7 +120,7 @@ class Skeleton_blocker_link_complex : public Skeleton_blocker_sub_complex<
only_superior_vertices_);
} else {
// we compute the intersection of neighbors of alpha and store it in link_vertices
- Simplex_handle link_vertices_parent;
+ Simplex link_vertices_parent;
parent_complex.add_neighbours(alpha_parent_adress, link_vertices_parent,
only_superior_vertices);
// For all vertex 'v' in this intersection, we go through all its adjacent blockers.
@@ -150,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.
@@ -162,39 +163,34 @@ class Skeleton_blocker_link_complex : public Skeleton_blocker_sub_complex<
}
void compute_link_edges(const ComplexType & parent_complex,
- const Simplex_handle& alpha_parent_adress,
+ const Simplex& alpha_parent_adress,
bool is_alpha_blocker = false) {
- Simplex_handle_iterator y_link, x_parent, y_parent;
- // ----------------------------
- // Compute edges in the link
- // -------------------------
-
if (this->num_vertices() <= 1)
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;
}
}
}
if (new_edge)
- this->add_edge(*x_link, *y_link);
+ this->add_edge_without_blockers(*x_link, *y_link);
}
}
}
@@ -205,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);
}
@@ -217,7 +213,7 @@ class Skeleton_blocker_link_complex : public Skeleton_blocker_sub_complex<
* the blocker is anticollapsed.
*/
void compute_link_blockers(const ComplexType & parent_complex,
- const Simplex_handle& alpha_parent,
+ const Simplex& alpha_parent,
bool is_alpha_blocker = false) {
for (auto x_link : this->vertex_range()) {
Vertex_handle x_parent = *this->give_equivalent_vertex(parent_complex,
@@ -225,7 +221,7 @@ class Skeleton_blocker_link_complex : public Skeleton_blocker_sub_complex<
for (auto blocker_parent : parent_complex.const_blocker_range(x_parent)) {
if (!is_alpha_blocker || *blocker_parent != alpha_parent) {
- Simplex_handle sigma_parent(*blocker_parent);
+ Simplex sigma_parent(*blocker_parent);
sigma_parent.difference(alpha_parent);
@@ -239,7 +235,7 @@ class Skeleton_blocker_link_complex : public Skeleton_blocker_sub_complex<
for (auto a : alpha_parent) {
for (auto eta_parent : parent_complex.const_blocker_range(a)) {
if (!is_alpha_blocker || *eta_parent != alpha_parent) {
- Simplex_handle eta_minus_alpha(*eta_parent);
+ Simplex eta_minus_alpha(*eta_parent);
eta_minus_alpha.difference(alpha_parent);
if (eta_minus_alpha != sigma_parent
&& sigma_parent.contains_difference(*eta_parent,
@@ -253,7 +249,7 @@ class Skeleton_blocker_link_complex : public Skeleton_blocker_sub_complex<
break;
}
if (is_new_blocker)
- this->add_blocker(new Simplex_handle(*sigma_link));
+ this->add_blocker(new Simplex(*sigma_link));
}
}
}
@@ -268,14 +264,15 @@ class Skeleton_blocker_link_complex : public Skeleton_blocker_sub_complex<
* with vertices that are greater than vertices of alpha_parent_adress.
*/
void build_link(const ComplexType & parent_complex,
- const Simplex_handle& alpha_parent_adress,
- bool is_alpha_blocker = false) {
+ const Simplex& alpha_parent_adress,
+ bool is_alpha_blocker = false,
+ 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_);
- compute_link_edges(parent_complex, alpha_parent_adress, is_alpha_blocker);
- compute_link_blockers(parent_complex, alpha_parent_adress,
- is_alpha_blocker);
+ compute_link_vertices(parent_complex, alpha_parent_adress, only_superior_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);
+ }
}
/**
@@ -284,7 +281,7 @@ class Skeleton_blocker_link_complex : public Skeleton_blocker_sub_complex<
* removed from the blockers of the complex.
*/
friend void build_link_of_blocker(const ComplexType & parent_complex,
- Simplex_handle& blocker,
+ Simplex& blocker,
Skeleton_blocker_link_complex & result) {
assert(blocker.dimension() >= 2);
assert(parent_complex.contains_blocker(blocker));
@@ -293,7 +290,9 @@ class Skeleton_blocker_link_complex : public Skeleton_blocker_sub_complex<
}
};
-} // namespace skbl
+} // namespace skeleton_blocker
+
+namespace skbl = skeleton_blocker;
} // namespace Gudhi
diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_simplifiable_complex.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_simplifiable_complex.h
index 17a237a7..544e02e8 100644
--- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_simplifiable_complex.h
+++ b/src/Skeleton_blocker/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_
@@ -30,10 +31,10 @@
namespace Gudhi {
-namespace skbl {
+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'
@@ -45,9 +46,7 @@ bool Skeleton_blocker_complex<SkeletonBlockerDS>::is_popable_blocker(Blocker_han
assert(this->contains_blocker(*sigma));
Skeleton_blocker_link_complex<Skeleton_blocker_complex> link_blocker_sigma;
build_link_of_blocker(*this, *sigma, link_blocker_sigma);
-
- bool res = link_blocker_sigma.is_contractible() == CONTRACTIBLE;
- return res;
+ return link_blocker_sigma.is_contractible() == CONTRACTIBLE;
}
/**
@@ -133,7 +132,7 @@ void Skeleton_blocker_complex<SkeletonBlockerDS>::remove_all_popable_blockers(Ve
template<typename SkeletonBlockerDS>
void Skeleton_blocker_complex<SkeletonBlockerDS>::remove_star(Vertex_handle v) {
// we remove the blockers that are not consistent anymore
- update_blockers_after_remove_star_of_vertex_or_edge(Simplex_handle(v));
+ update_blockers_after_remove_star_of_vertex_or_edge(Simplex(v));
while (this->degree(v) > 0) {
Vertex_handle w(* (adjacent_vertices(v.vertex, this->skeleton).first));
this->remove_edge(v, w);
@@ -147,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_handle& 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;
@@ -159,7 +157,7 @@ void Skeleton_blocker_complex<SkeletonBlockerDS>::update_blockers_after_remove_s
}
for (auto blocker_to_update : blockers_to_update) {
- Simplex_handle sub_blocker_to_be_added;
+ Simplex sub_blocker_to_be_added;
bool sub_blocker_need_to_be_added =
(blocker_to_update->dimension() - simplex_to_be_removed.dimension()) >= 2;
if (sub_blocker_need_to_be_added) {
@@ -178,7 +176,7 @@ void Skeleton_blocker_complex<SkeletonBlockerDS>::update_blockers_after_remove_s
*/
template<typename SkeletonBlockerDS>
void Skeleton_blocker_complex<SkeletonBlockerDS>::remove_star(Vertex_handle a, Vertex_handle b) {
- update_blockers_after_remove_star_of_vertex_or_edge(Simplex_handle(a, b));
+ update_blockers_after_remove_star_of_vertex_or_edge(Simplex(a, b));
// we remove the edge
this->remove_edge(a, b);
}
@@ -195,7 +193,7 @@ void Skeleton_blocker_complex<SkeletonBlockerDS>::remove_star(Edge_handle e) {
* Remove the star of the simplex 'sigma' which needs to belong to the complex
*/
template<typename SkeletonBlockerDS>
-void Skeleton_blocker_complex<SkeletonBlockerDS>::remove_star(const Simplex_handle& sigma) {
+void Skeleton_blocker_complex<SkeletonBlockerDS>::remove_star(const Simplex& sigma) {
assert(this->contains(sigma));
if (sigma.dimension() == 0) {
remove_star(sigma.first_vertex());
@@ -207,34 +205,39 @@ void Skeleton_blocker_complex<SkeletonBlockerDS>::remove_star(const Simplex_hand
}
}
-/**
- * @brief add a maximal simplex plus all its cofaces. All vertices lower than the higher vertex of
- * sigma must already be present.
- * @details the simplex must have dimension greater than one (otherwise use add_vertex or add_edge).
- */
template<typename SkeletonBlockerDS>
-void Skeleton_blocker_complex<SkeletonBlockerDS>::add_simplex(const Simplex_handle& sigma) {
+void Skeleton_blocker_complex<SkeletonBlockerDS>::add_simplex(const Simplex& sigma) {
+ // to add a simplex s, all blockers included in s are first removed
+ // and then all simplex in the coboundary of s are added as blockers
assert(!this->contains(sigma));
assert(sigma.dimension() > 1);
+ if (!contains_vertices(sigma)) {
+ std::cerr << "add_simplex: Some vertices were not present in the complex, adding them" << std::endl;
+ size_t num_vertices_to_add = sigma.last_vertex() - this->num_vertices() + 1;
+ for (size_t i = 0; i < num_vertices_to_add; ++i)
+ this->add_vertex();
+ }
+ assert(contains_vertices(sigma));
+ if (!contains_edges(sigma))
+ add_edge(sigma);
+ remove_blocker_include_in_simplex(sigma);
+ add_blockers_after_simplex_insertion(sigma);
+}
- int num_vertex_to_add = 0;
- for (auto v : sigma)
- if (!contains_vertex(v)) ++num_vertex_to_add;
- while (num_vertex_to_add--) add_vertex();
+template<typename SkeletonBlockerDS>
+void Skeleton_blocker_complex<SkeletonBlockerDS>::add_blockers_after_simplex_insertion(Simplex sigma) {
+ if (sigma.dimension() < 1) return;
- for (auto u_it = sigma.begin(); u_it != sigma.end(); ++u_it)
- for (auto v_it = u_it; ++v_it != sigma.end(); /**/) {
- // std::cout << "add edge" << *u_it << " " << *v_it << std::endl;
- add_edge(*u_it, *v_it);
- }
- remove_blocker_include_in_simplex(sigma);
+ for (auto s : coboundary_range(sigma)) {
+ this->add_blocker(s);
+ }
}
/**
* remove all blockers that contains sigma
*/
template<typename SkeletonBlockerDS>
-void Skeleton_blocker_complex<SkeletonBlockerDS>::remove_blocker_containing_simplex(const Simplex_handle& sigma) {
+void Skeleton_blocker_complex<SkeletonBlockerDS>::remove_blocker_containing_simplex(const Simplex& sigma) {
std::vector <Blocker_handle> blockers_to_remove;
for (auto blocker : this->blocker_range(sigma.first_vertex())) {
if (blocker->contains(sigma))
@@ -248,14 +251,26 @@ void Skeleton_blocker_complex<SkeletonBlockerDS>::remove_blocker_containing_simp
* remove all blockers that contains sigma
*/
template<typename SkeletonBlockerDS>
-void Skeleton_blocker_complex<SkeletonBlockerDS>::remove_blocker_include_in_simplex(const Simplex_handle& sigma) {
- std::vector <Blocker_handle> blockers_to_remove;
- for (auto blocker : this->blocker_range(sigma.first_vertex())) {
- if (sigma.contains(*blocker))
- blockers_to_remove.push_back(blocker);
+void Skeleton_blocker_complex<SkeletonBlockerDS>::remove_blocker_include_in_simplex(const Simplex& sigma) {
+ // TODO(DS): write efficiently by using only superior blockers
+ // eg for all s, check blockers whose vertices are all greater than s
+ std::set <Blocker_handle> blockers_to_remove;
+ for (auto s : sigma) {
+ for (auto blocker : this->blocker_range(s)) {
+ if (sigma.contains(*blocker))
+ blockers_to_remove.insert(blocker);
+ }
}
- for (auto blocker_to_update : blockers_to_remove)
+ for (auto blocker_to_update : blockers_to_remove) {
+ auto s = *blocker_to_update;
this->delete_blocker(blocker_to_update);
+ // now if there is a vertex v in the link of s
+ // and v is not included in sigma then v.s is a blocker
+ // (all faces of v.s are there since v belongs to the link of s)
+ for (const auto& b : coboundary_range(s))
+ if (!sigma.contains(b))
+ this->add_blocker(b);
+ }
}
/**
@@ -265,21 +280,21 @@ void Skeleton_blocker_complex<SkeletonBlockerDS>::remove_blocker_include_in_simp
*/
template<typename SkeletonBlockerDS>
void Skeleton_blocker_complex<SkeletonBlockerDS>::tip_blockers(Vertex_handle a, Vertex_handle b,
- std::vector<Simplex_handle> & buffer) const {
+ std::vector<Simplex> & buffer) const {
for (auto const & blocker : this->const_blocker_range(a)) {
- Simplex_handle beta = (*blocker);
+ Simplex beta = (*blocker);
beta.remove_vertex(a);
buffer.push_back(beta);
}
- Simplex_handle n;
+ Simplex n;
this->add_neighbours(b, n);
this->remove_neighbours(a, n);
n.remove_vertex(a);
for (Vertex_handle y : n) {
- Simplex_handle beta;
+ Simplex beta;
beta.add_vertex(y);
buffer.push_back(beta);
}
@@ -296,7 +311,7 @@ void Skeleton_blocker_complex<SkeletonBlockerDS>::tip_blockers(Vertex_handle a,
template<typename SkeletonBlockerDS>
void
Skeleton_blocker_complex<SkeletonBlockerDS>::swap_edge(Vertex_handle a, Vertex_handle b, Vertex_handle x) {
- this->add_edge(a, x);
+ this->add_edge_without_blockers(a, x);
if (this->visitor) this->visitor->on_swaped_edge(a, b, x);
this->remove_edge(b, x);
}
@@ -341,13 +356,13 @@ Skeleton_blocker_complex<SkeletonBlockerDS>::contract_edge(Vertex_handle a, Vert
assert(this->contains_vertex(b));
if (this->contains_edge(a, b))
- this->add_edge(a, b);
+ this->add_edge_without_blockers(a, b);
// if some blockers passes through 'ab', we need to remove them.
if (!link_condition(a, b))
delete_blockers_around_edge(a, b);
- std::set<Simplex_handle> blockers_to_add;
+ std::set<Simplex> blockers_to_add;
get_blockers_to_be_added_after_contraction(a, b, blockers_to_add);
@@ -367,9 +382,9 @@ 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_handle>& blockers_to_add) {
+void Skeleton_blocker_complex<SkeletonBlockerDS>::get_blockers_to_be_added_after_contraction(Vertex_handle a,
+ Vertex_handle b,
+ std::set<Simplex>& blockers_to_add) {
blockers_to_add.clear();
typedef Skeleton_blocker_link_complex<Skeleton_blocker_complex<SkeletonBlockerDS> > LinkComplexType;
@@ -377,19 +392,19 @@ Skeleton_blocker_complex<SkeletonBlockerDS>::get_blockers_to_be_added_after_cont
LinkComplexType link_a(*this, a);
LinkComplexType link_b(*this, b);
- std::vector<Simplex_handle> vector_alpha, vector_beta;
+ std::vector<Simplex> vector_alpha, vector_beta;
tip_blockers(a, b, vector_alpha);
tip_blockers(b, a, vector_beta);
for (auto alpha = vector_alpha.begin(); alpha != vector_alpha.end(); ++alpha) {
for (auto beta = vector_beta.begin(); beta != vector_beta.end(); ++beta) {
- Simplex_handle sigma = *alpha;
+ Simplex sigma = *alpha;
sigma.union_vertices(*beta);
Root_simplex_handle sigma_id = this->get_id(sigma);
if (this->contains(sigma) &&
proper_faces_in_union<Skeleton_blocker_complex < SkeletonBlockerDS >> (sigma_id, link_a, link_b)) {
- // Blocker_handle blocker = new Simplex_handle(sigma);
+ // Blocker_handle blocker = new Simplex(sigma);
sigma.add_vertex(a);
blockers_to_add.insert(sigma);
}
@@ -443,7 +458,9 @@ Skeleton_blocker_complex<SkeletonBlockerDS>::notify_changed_edges(Vertex_handle
}
-} // namespace skbl
+} // namespace skeleton_blocker
+
+namespace skbl = skeleton_blocker;
} // namespace Gudhi
diff --git a/src/Skeleton_blocker/test/CMakeLists.txt b/src/Skeleton_blocker/test/CMakeLists.txt
index 8b6fb672..f98517f0 100644
--- a/src/Skeleton_blocker/test/CMakeLists.txt
+++ b/src/Skeleton_blocker/test/CMakeLists.txt
@@ -1,28 +1,35 @@
cmake_minimum_required(VERSION 2.6)
-project(GUDHIskbl)
+project(Skeleton_blocker_tests)
if (GCOVR_PATH)
# for gcovr to make coverage reports - Corbera Jenkins plugin
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
- set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fprofile-arcs -ftest-coverage")
- set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fprofile-arcs -ftest-coverage")
endif()
if (GPROF_PATH)
# for gprof to make coverage reports - Jenkins
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg")
- set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pg")
- set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pg")
endif()
-add_executable(TestSkeletonBlockerComplex TestSkeletonBlockerComplex.cpp)
-add_executable(TestSimplifiable TestSimplifiable.cpp)
-add_executable(TestGeometricComplex TestGeometricComplex.cpp)
+add_executable ( test_skeleton_blocker_complex test_skeleton_blocker_complex.cpp )
+target_link_libraries(test_skeleton_blocker_complex ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+add_executable ( test_skeleton_blocker_geometric_complex test_skeleton_blocker_geometric_complex.cpp )
+target_link_libraries(test_skeleton_blocker_geometric_complex ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+add_executable ( test_skeleton_blocker_simplifiable test_skeleton_blocker_simplifiable.cpp )
+target_link_libraries(test_skeleton_blocker_simplifiable ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
# Do not forget to copy test files in current binary dir
-file(COPY "test.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
file(COPY "test2.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
-add_test(TestSkeletonBlockerComplex ${CMAKE_CURRENT_BINARY_DIR}/TestSkeletonBlockerComplex)
-add_test(TestSimplifiable ${CMAKE_CURRENT_BINARY_DIR}/TestSimplifiable)
-add_test(TestGeometricComplex ${CMAKE_CURRENT_BINARY_DIR}/TestGeometricComplex)
-
+# Unitary tests
+add_test(NAME test_skeleton_blocker_complex
+ COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_skeleton_blocker_complex
+ # XML format for Jenkins xUnit plugin
+ --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/skbl_complexUT.xml --log_level=test_suite --report_level=no)
+add_test(NAME test_skeleton_blocker_geometric_complex
+ COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_skeleton_blocker_geometric_complex
+ # XML format for Jenkins xUnit plugin
+ --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/skbl_geometric_complexUT.xml --log_level=test_suite --report_level=no)
+add_test(NAME test_skeleton_blocker_simplifiable
+ COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_skeleton_blocker_simplifiable
+ # XML format for Jenkins xUnit plugin
+ --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/skbl_simplifiableUT.xml --log_level=test_suite --report_level=no)
diff --git a/src/Skeleton_blocker/test/TestGeometricComplex.cpp b/src/Skeleton_blocker/test/TestGeometricComplex.cpp
deleted file mode 100644
index bd7af89b..00000000
--- a/src/Skeleton_blocker/test/TestGeometricComplex.cpp
+++ /dev/null
@@ -1,120 +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/>.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string>
-#include <fstream>
-#include <sstream>
-#include "gudhi/Test.h"
-#include "gudhi/Skeleton_blocker.h"
-
-
-using namespace std;
-using namespace Gudhi;
-using namespace skbl;
-
-struct Geometry_trait{
- typedef std::vector<double> Point;
-};
-
-typedef Geometry_trait::Point Point;
-typedef Skeleton_blocker_simple_geometric_traits<Geometry_trait> Complex_geometric_traits;
-typedef Skeleton_blocker_geometric_complex< Complex_geometric_traits > Complex;
-typedef Complex::Vertex_handle Vertex_handle;
-
-
-bool test_constructor1(){
- Complex complex;
- Skeleton_blocker_off_reader<Complex> off_reader("test2.off",complex);
- if(!off_reader.is_valid()){
- std::cerr << "Unable to read file"<<std::endl;
- return false;
- }
-
-
- std::cout << "complex has "<<
- complex.num_vertices()<<" vertices, "<<
- complex.num_blockers()<<" blockers, "<<
- complex.num_edges()<<" edges and" <<
- complex.num_triangles()<<" triangles.";
-
- if(complex.num_vertices()!=7 || complex.num_edges()!=12 || complex.num_triangles() !=6)
- return false;
-
- Skeleton_blocker_off_writer<Complex> off_writer("tmp.off",complex);
- Complex same;
- Skeleton_blocker_off_reader<Complex> off_reader2("tmp.off",same);
-
- std::cout<<"\ncomplex:"<<complex.to_string()<<endl;
- std::cout<<"\nsame:"<<same.to_string()<<endl;
-
- return (complex==same);
-}
-
-bool test_constructor2(){
- Complex complex;
- Skeleton_blocker_off_reader<Complex> off_reader("test2.off",complex);
- if(!off_reader.is_valid()){
- std::cerr << "Unable to read file"<<std::endl;
- return false;
- }
- std::cout << "complex has "<<
- complex.num_vertices()<<" vertices, "<<
- complex.num_blockers()<<" blockers, "<<
- complex.num_edges()<<" edges and" <<
- complex.num_triangles()<<" triangles.";
-
- if(complex.num_vertices()!=7 || complex.num_edges()!=12 || complex.num_triangles() !=6)
- return false;
-
- auto link_0 = complex.abstract_link(Vertex_handle(0));
-
-
- std::cout<<"\n link(0):"<<link_0.to_string()<<endl;
-
- auto link_geometric_0 = complex.link(Vertex_handle(0));
-
- auto print_point = [&](Vertex_handle v){for(auto x : link_geometric_0.point(v)) std::cout <<x<<" "; std::cout<<std::endl;};
-
- std::for_each(link_geometric_0.vertex_range().begin(),link_geometric_0.vertex_range().end(),print_point);
-
-// for(auto v : link_geometric_0.vertex_range())
-// std::cout<<"point("<<v<<"):"<<link_geometric_0.point(v)<<std::endl;
-
- return link_0.num_vertices()==2;
-}
-
-
-
-
-int main (int argc, char *argv[])
-{
- Tests tests_geometric_complex;
- tests_geometric_complex.add("Test constructor 1",test_constructor1);
- tests_geometric_complex.add("Test constructor 2",test_constructor2);
-
- if(tests_geometric_complex.run())
- return EXIT_SUCCESS;
- else
- return EXIT_FAILURE;
-}
diff --git a/src/Skeleton_blocker/test/TestSimplifiable.cpp b/src/Skeleton_blocker/test/TestSimplifiable.cpp
deleted file mode 100644
index 09176934..00000000
--- a/src/Skeleton_blocker/test/TestSimplifiable.cpp
+++ /dev/null
@@ -1,356 +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/>.
- */
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string>
-#include <fstream>
-#include <sstream>
-#include "gudhi/Test.h"
-//#include "Skeleton_blocker/Simplex.h"
-#include "gudhi/Skeleton_blocker.h"
-
-
-using namespace std;
-
-using namespace Gudhi;
-
-using namespace skbl;
-
-template<typename ComplexType> class Skeleton_blocker_sub_complex;
-typedef Skeleton_blocker_complex<Skeleton_blocker_simple_traits> Complex;
-typedef Complex::Vertex_handle Vertex_handle;
-typedef Complex::Root_vertex_handle Root_vertex_handle;
-typedef Skeleton_blocker_simplex<Vertex_handle> Simplex_handle;
-// true iff v \in complex
-bool assert_vertex(Complex &complex,Vertex_handle v){
- Simplex_handle simplex(v);
- bool test = complex.contains(simplex);
- assert(test);
- return test;
-}
-
-// true iff the blocker (a,b,c) is in complex
-bool assert_blocker(Complex &complex,Root_vertex_handle a,Root_vertex_handle b,Root_vertex_handle c){
-
- return complex.contains_blocker(Simplex_handle(*complex.get_address(a),*complex.get_address(b),*complex.get_address(c)));
- //return complex.contains_blocker((a),(b),(c));
-}
-
-void build_complete(int n,Complex& complex){
- complex.clear();
- 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(Vertex_handle(i),Vertex_handle(j));
-}
-
-bool test_contraction1(){
- enum { a, b, x, y, z, n };
- Complex complex(n);
- build_complete(n,complex);
- complex.remove_edge(static_cast<Vertex_handle>(b), static_cast<Vertex_handle>(z));
- complex.add_blocker(Simplex_handle(static_cast<Vertex_handle>(a), static_cast<Vertex_handle>(x),
- static_cast<Vertex_handle>(y)));
- complex.add_blocker(Simplex_handle(static_cast<Vertex_handle>(b), static_cast<Vertex_handle>(x),
- static_cast<Vertex_handle>(y)));
-
- // Print result
- cerr << "complex before complex"<< complex.to_string()<<endl;
-
- cerr <<endl<<endl;
- complex.contract_edge(static_cast<Vertex_handle>(a),static_cast<Vertex_handle>(b));
- // Print result
- cerr << "ContractEdge(0,1)\n";
- PRINT(complex.to_string());
-
- // verification
- for (int i=0;i<5;i++)
- if (i!=1) assert_vertex(complex, static_cast<Vertex_handle>(i));
- bool test1 = !complex.contains_edge(static_cast<Vertex_handle>(a),static_cast<Vertex_handle>(b));
- bool test2 = assert_blocker(complex,Root_vertex_handle(a),Root_vertex_handle(x),Root_vertex_handle(y));
- bool test3 = complex.num_edges()==6;
- bool test4 = complex.num_blockers()==1;
- Simplex_handle sigma;
- sigma.add_vertex(static_cast<Vertex_handle>(a));
- sigma.add_vertex(static_cast<Vertex_handle>(x));
- sigma.add_vertex(static_cast<Vertex_handle>(y));
- sigma.add_vertex(static_cast<Vertex_handle>(z));
- bool test5 = !(complex.contains(sigma));
- return test1&&test2&&test3&&test4&&test5;
-}
-
-
-bool test_contraction2(){
- enum { a, b, x, y, z, n };
- Complex complex(n);
- build_complete(n,complex);
- complex.remove_edge(static_cast<Vertex_handle>(b),static_cast<Vertex_handle>(x));
- Simplex_handle blocker;
- blocker.add_vertex(static_cast<Vertex_handle>(a));
- blocker.add_vertex(static_cast<Vertex_handle>(y));
- blocker.add_vertex(static_cast<Vertex_handle>(z));
-
- complex.add_blocker(blocker);
-
- // Print result
- cerr << "complex complex"<< complex.to_string();
- cerr <<endl<<endl;
- complex.contract_edge(static_cast<Vertex_handle>(a),static_cast<Vertex_handle>(b));
-
- cerr << "complex.ContractEdge(a,b)"<< complex.to_string();
-
- cerr <<endl<<endl;
-
- // there should be one blocker (a,c,d,e) in the complex
- bool test ;
- test = complex.contains_blocker(Simplex_handle(static_cast<Vertex_handle>(a), static_cast<Vertex_handle>(x),
- static_cast<Vertex_handle>(y),static_cast<Vertex_handle>(z)));
- test = test && complex.num_blockers()==1;
- return test;
-}
-
-bool test_link_condition1(){
-
- Complex complex(0);
- // Build the complexes
- build_complete(4,complex);
- complex.add_blocker(Simplex_handle(static_cast<Vertex_handle>(0), static_cast<Vertex_handle>(1), static_cast<Vertex_handle>(2)));
-
-
- // Print result
- cerr << "complex complex"<< complex.to_string();
- cerr <<endl<<endl;
-
- bool weak_link_condition = complex.link_condition(Vertex_handle(1),Vertex_handle(2),true);
-
- bool strong_link_condition = complex.link_condition(Vertex_handle(1),Vertex_handle(2),false);
-
- return weak_link_condition && !strong_link_condition;
-}
-
-
-bool test_collapse0(){
- Complex complex(5);
- build_complete(4,complex);
- complex.add_vertex();
- complex.add_edge(static_cast<Vertex_handle>(2), static_cast<Vertex_handle>(4));
- complex.add_edge(static_cast<Vertex_handle>(3), static_cast<Vertex_handle>(4));
- // Print result
- cerr << "initial complex :\n"<< complex.to_string();
- cerr <<endl<<endl;
-
- Simplex_handle simplex_123(static_cast<Vertex_handle>(1), static_cast<Vertex_handle>(2), static_cast<Vertex_handle>(3));
- complex.remove_star(simplex_123);
- cerr << "complex.remove_star(1,2,3):\n"<< complex.to_string();
- cerr <<endl<<endl;
-
- // verification
- bool blocker123_here = complex.contains_blocker(simplex_123);
- cerr <<"----> Ocomplex \n";
- return blocker123_here;
-}
-
-
-bool test_collapse1(){
- Complex complex(5);
- build_complete(4,complex);
- complex.add_blocker(Simplex_handle(Vertex_handle(0),Vertex_handle(1),Vertex_handle(2),Vertex_handle(3)));
- // Print result
- cerr << "initial complex :\n"<< complex.to_string();
- cerr <<endl<<endl;
-
- Simplex_handle simplex_123(Vertex_handle(1),Vertex_handle(2),Vertex_handle(3));
- complex.remove_star(simplex_123);
- cerr << "complex.remove_star(1,2,3):\n"<< complex.to_string();
- cerr <<endl<<endl;
-
- // verification
- bool res = complex.contains_blocker(simplex_123);
- res = res && complex.num_blockers()==1;
- cerr <<"----> Ocomplex \n";
- return res;
-}
-
-bool test_collapse2(){
- Complex complex(5);
- build_complete(4,complex);
- complex.add_vertex();
- complex.add_edge(Vertex_handle(1),Vertex_handle(4));
- complex.add_edge(Vertex_handle(2),Vertex_handle(4));
- complex.add_edge(Vertex_handle(3),Vertex_handle(4));
- complex.add_blocker(Simplex_handle(Vertex_handle(1),Vertex_handle(2),Vertex_handle(3),Vertex_handle(4)));
- // Print result
- cerr << "initial complex :\n"<< complex.to_string();
- cerr <<endl<<endl;
-
- Simplex_handle sigma(Vertex_handle(1),Vertex_handle(2),Vertex_handle(3));
- complex.remove_star(sigma);
- cerr << "complex.remove_star(1,2,3):\n"<< complex.to_string();
- cerr <<endl<<endl;
-
- // verification
- bool blocker_removed = !complex.contains_blocker(Simplex_handle(Vertex_handle(1),Vertex_handle(2),Vertex_handle(3),Vertex_handle(4)));
- bool blocker123_here = complex.contains_blocker(sigma);
- return blocker_removed && blocker123_here;
-}
-
-bool test_collapse3(){
- Complex complex(5);
- build_complete(4,complex);
- complex.add_vertex();
- complex.add_edge(Vertex_handle(1),Vertex_handle(4));
- complex.add_edge(Vertex_handle(2),Vertex_handle(4));
- complex.add_edge(Vertex_handle(3),Vertex_handle(4));
- complex.add_blocker(Simplex_handle(Vertex_handle(1),Vertex_handle(2),Vertex_handle(3),Vertex_handle(4)));
- // Print result
- cerr << "initial complex:\n"<< complex.to_string();
- cerr <<endl<<endl;
-
- complex.remove_star(static_cast<Vertex_handle>(2));
- cerr << "complex after remove star of 2:\n"<< complex.to_string();
-
- bool blocker134_here = complex.contains_blocker(Simplex_handle(Vertex_handle(1),Vertex_handle(3),Vertex_handle(4)));
- bool blocker1234_here = complex.contains_blocker(Simplex_handle(Vertex_handle(1),Vertex_handle(2),Vertex_handle(3),Vertex_handle(4)));
- return blocker134_here && !blocker1234_here;
-}
-
-bool test_add_simplex(){
- Complex complex(5);
- build_complete(4,complex);
- complex.add_blocker(Simplex_handle(Vertex_handle(0),Vertex_handle(1),Vertex_handle(2)));
- // Print result
- cerr << "initial complex:\n"<< complex.to_string();
- cerr <<endl<<endl;
-
- complex.add_simplex(Simplex_handle(Vertex_handle(0),Vertex_handle(1),Vertex_handle(2),Vertex_handle(3)));
- cerr << "complex after add_simplex:\n"<< complex.to_string();
-
- return complex.num_blockers()==0;
-}
-
-bool test_add_simplex2(){
- Complex complex;
- build_complete(4,complex);
- // Print result
- cerr << "initial complex:\n"<< complex.to_string();
- cerr <<endl<<endl;
-
- Complex copy(complex.num_vertices());
-
- std::vector<Simplex_handle> simplices(complex.simplex_range().begin(),complex.simplex_range().end());
- sort(simplices.begin(),simplices.end(),[&](const Simplex_handle& s1,const Simplex_handle& s2){
- return s1.dimension()<s2.dimension();
- });
- for(const auto & simplex : simplices){
- if(!copy.contains(simplex) && simplex.dimension()==1)
- copy.add_edge(simplex.first_vertex(),simplex.last_vertex());
- if(!copy.contains(simplex) && simplex.dimension()>1)
- copy.add_simplex(simplex);
- }
-
-
- cerr << "complex after add_simplex:\n"<< copy.to_string();
-
-
- return complex.num_blockers()==copy.num_blockers() &&
- complex.num_edges()==copy.num_edges() &&
- complex.num_vertices()==copy.num_vertices();
-}
-
-
-
-bool test_remove_popable_blockers(){
- Complex complex;
- build_complete(4,complex);
- complex.add_vertex();
- complex.add_edge(Vertex_handle(3),Vertex_handle(4));
- complex.add_edge(Vertex_handle(2),Vertex_handle(4));
- Simplex_handle sigma1=Simplex_handle(Vertex_handle(1),Vertex_handle(2),Vertex_handle(3));
- Simplex_handle sigma2=Simplex_handle(Vertex_handle(2),Vertex_handle(3),Vertex_handle(4));
-
- complex.add_blocker(sigma1);
- complex.add_blocker(sigma2);
- cerr << "complex complex"<< complex.to_string();
- cerr <<endl<<endl;
- cerr << "complex.RemovePopableBlockers();"<<endl;
- complex.remove_popable_blockers();
- cerr << "complex complex"<< complex.to_string();
- cerr <<endl<<endl;
-
- bool test1 = (complex.num_blockers()==1);
-
-
- // test 2
- complex.clear();
- build_complete(4,complex);
- complex.add_vertex();
- complex.add_vertex();
- complex.add_edge(Vertex_handle(3),Vertex_handle(4));
- complex.add_edge(Vertex_handle(2),Vertex_handle(4));
- complex.add_edge(Vertex_handle(2),Vertex_handle(5));
- complex.add_edge(Vertex_handle(3),Vertex_handle(5));
- complex.add_edge(Vertex_handle(4),Vertex_handle(5));
- sigma1=Simplex_handle(Vertex_handle(1),Vertex_handle(2),Vertex_handle(3));
- sigma2=Simplex_handle(Vertex_handle(2),Vertex_handle(3),Vertex_handle(4));
-
- complex.add_blocker(sigma1);
- complex.add_blocker(sigma2);
- cerr << "complex complex"<< complex.to_string();
- cerr <<endl<<endl; cerr << "complex.RemovePopableBlockers();"<<endl;
- complex.remove_popable_blockers();
- cerr << "complex complex"<< complex.to_string();
-
- cerr <<endl<<endl;
- bool test2 = (complex.num_blockers()==0);
- return test1&&test2;
-}
-
-
-
-int main (int argc, char *argv[])
-{
- Tests tests_simplifiable_complex;
- tests_simplifiable_complex.add("Test contraction 1",test_contraction1);
- tests_simplifiable_complex.add("Test contraction 2",test_contraction2);
- tests_simplifiable_complex.add("Test Link condition 1",test_link_condition1);
- tests_simplifiable_complex.add("Test remove popable blockers",test_remove_popable_blockers);
-
-
- tests_simplifiable_complex.add("Test collapse 0",test_collapse0);
- tests_simplifiable_complex.add("Test collapse 1",test_collapse1);
- tests_simplifiable_complex.add("Test collapse 2",test_collapse2);
- tests_simplifiable_complex.add("Test collapse 3",test_collapse3);
-
- tests_simplifiable_complex.add("Test add simplex",test_add_simplex);
- tests_simplifiable_complex.add("Test add simplex2",test_add_simplex2);
-
-
- tests_simplifiable_complex.run();
-
- if(tests_simplifiable_complex.run())
- return EXIT_SUCCESS;
- else
- return EXIT_FAILURE;
-}
diff --git a/src/Skeleton_blocker/test/TestSkeletonBlockerComplex.cpp b/src/Skeleton_blocker/test/TestSkeletonBlockerComplex.cpp
deleted file mode 100644
index 319e3c43..00000000
--- a/src/Skeleton_blocker/test/TestSkeletonBlockerComplex.cpp
+++ /dev/null
@@ -1,952 +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/>.
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string>
-#include <fstream>
-#include <sstream>
-#include "gudhi/Utils.h"
-#include "gudhi/Test.h"
-#include "gudhi/Skeleton_blocker.h"
-//#include "gudhi/Skeleton_blocker_link_complex.h"
-//#include "gudhi/Skeleton_blocker/Skeleton_blocker_link_superior.h"
-//#include "gudhi/Skeleton_blocker/Skeleton_blocker_simple_traits.h"
-//#include "gudhi/Skeleton_blocker/internal/Trie.h"
-
-using namespace std;
-
-using namespace Gudhi;
-
-using namespace skbl;
-
-
-typedef Skeleton_blocker_complex<Skeleton_blocker_simple_traits> Complex;
-typedef Complex::Vertex_handle Vertex_handle;
-typedef Complex::Root_vertex_handle Root_vertex_handle;
-typedef Complex::Simplex_handle Simplex_handle;
-typedef Complex::Root_simplex_handle Root_simplex_handle;
-typedef Simplex_handle::Simplex_vertex_const_iterator Simplex_vertex_const_iterator;
-typedef Complex::Edge_handle Edge_handle;
-
-// true if v in complex
-bool assert_vertex(Complex &complex,Vertex_handle v){
- //assert(complex.contains(v));
- return complex.contains(static_cast<Simplex_handle>(v));
-}
-
-bool assert_simplex(Complex &complex,Root_vertex_handle a,Root_vertex_handle b,Root_vertex_handle c){
- return true;
- // AddressSimplex simplex((a),(b),(c));
- // return complex.contains(&simplex);
-}
-
-// true iff the blocker (a,b,c) is in complex
-bool assert_blocker(Complex &complex,Root_vertex_handle a,Root_vertex_handle b,Root_vertex_handle c){
- return true;
- //return complex.contains_blocker((a),(b),(c));
-}
-
-// true iff the blocker (a,b,c,d) is in complex
-bool assert_blocker(Complex &complex,Root_vertex_handle a,Root_vertex_handle b,Root_vertex_handle c,Root_vertex_handle d){
- return true;
- //Simplex blocker (a,b,c,d);
- //return complex.contains_blocker(&blocker);
-}
-
-
-
-void build_complete(int n,Complex& complex){
- complex.clear();
- for(int i=0;i<n;i++)
- complex.add_vertex();
-
- // for(int i=n-1;i>=0;i--)
- // for(int j=i-1;j>=0;j--)
- // complex.add_edge(Vertex_handle(i),Vertex_handle(j));
-
- for(int i=0;i<n;i++)
- for(int j=0;j<i;j++)
- complex.add_edge(Vertex_handle(i),Vertex_handle(j));
-}
-
-
-bool test_simplex(){
- // PRINT("test simplex");
- Simplex_handle simplex(Vertex_handle(0),Vertex_handle(1),Vertex_handle(2),Vertex_handle(3));
- for (auto i = simplex.begin() ; i != simplex.end() ; ++i){
- PRINT(*i);
- auto j = i;
- for (++j ;
- j != simplex.end() ;
- ++j){
- PRINT(*j);
- }
- }
- return simplex.dimension()==3;
-}
-
-
-bool test_iterator_vertices1(){
- int n = 10;
- Complex complex(10);
- cerr << "complex.num_vertices():"<<complex.num_vertices()<<endl;
- int num_vertex_seen = 0;
- for(auto vi :complex.vertex_range()){
- cerr << "vertex:"<<vi<<endl;
- ++num_vertex_seen;
- }
- return num_vertex_seen == n;
-}
-
-bool test_iterator_vertices2(){
- int n = 10;
- Complex complex(10);
- build_complete(10,complex);
- cerr << "complex.num_vertices():"<<complex.num_vertices()<<endl;
- cerr << "complex.num_edges():"<<complex.num_edges()<<endl;
- int num_vertex_seen = 0;
- for(auto vi :complex.vertex_range(Vertex_handle(2))){
- cerr << "vertex:"<<vi<<endl;
- ++num_vertex_seen;
- }
- std::cerr<<"num_vertex_seen:"<<num_vertex_seen<<std::endl;
- return num_vertex_seen == (n-1);
-}
-
-
-
-bool test_iterator_edge(){
- const int n = 10;
- Complex complex(n);
- for(int i=0;i<n;i++)
- for(int j=0;j<i;j++)
- complex.add_edge(Vertex_handle(i),Vertex_handle(j));
- complex.remove_edge(Vertex_handle(2),Vertex_handle(3));
- complex.remove_edge(Vertex_handle(3),Vertex_handle(5));
- cerr << "complex.num_edges():"<<complex.num_edges()<<endl;
- int num_edges_seen = 0;
- for(auto edge : complex.edge_range()){
- cerr << "edge :"<<complex[edge]<<endl;
- ++num_edges_seen;
- }
-
- return num_edges_seen == n*(n-1)/2-2;
-}
-
-bool test_iterator_edge2(){
- const int n = 10;
- Complex complex(n);
- for(int i=0;i<n;i++)
- for(int j=0;j<i;j++)
- complex.add_edge(Vertex_handle(i),Vertex_handle(j));
- complex.remove_edge(Vertex_handle(2),Vertex_handle(3));
- complex.remove_edge(Vertex_handle(3),Vertex_handle(5));
- cerr << "complex.num_edges():"<<complex.num_edges()<<endl;
- int num_neigbors_seen = 0;
- for(auto neighbor : complex.vertex_range(Vertex_handle(2))){
- cerr << "neighbor"<<neighbor<<endl;
- ++num_neigbors_seen;
- }
- return num_neigbors_seen==8;
-}
-
-
-
-bool test_iterator_edge3(){
- const int n = 10;
- Complex complex(n);
- for(int i=0;i<n;i++)
- for(int j=0;j<i;j++)
- complex.add_edge(Vertex_handle(i),Vertex_handle(j));
- complex.remove_edge(Vertex_handle(2),Vertex_handle(3));
- complex.remove_edge(Vertex_handle(3),Vertex_handle(5));
- cerr << "complex.num_edges():"<<complex.num_edges()<<endl;
- int num_neigbors_seen = 0;
- for(auto edge : complex.edge_range(Vertex_handle(2))){
- std::cerr << edge<< std::endl;
- ++num_neigbors_seen;
- }
- return num_neigbors_seen==8;
-}
-
-
-
-bool test_iterator_triangles(){
- const int n = 7;
- Complex complex(n);
- //create a "ring" around '0'
- for(int i=1;i<n;i++)
- complex.add_edge(Vertex_handle(0),Vertex_handle(i));
- for(int i=1;i<n-1;i++)
- complex.add_edge(Vertex_handle(i),Vertex_handle(i+1));
- complex.add_edge(Vertex_handle(1),Vertex_handle(6));
-
- PRINT(complex.to_string());
-
- int num_triangles_seen=0;
- //for (auto t : complex.triangle_range(5)){
- TEST("triangles around 5 (should be 2 of them):");
- for (auto t : complex.triangle_range(Vertex_handle(5))){
- PRINT(t);
- ++num_triangles_seen;
- }
- bool test = (num_triangles_seen==2);
-
- num_triangles_seen=0;
- TEST("triangles around 0 (should be 6 of them):");
- for (auto t : complex.triangle_range(Vertex_handle(0))){
- PRINT(t);
- ++num_triangles_seen;
- }
- test = test&&(num_triangles_seen==6);
-
- // we now add another triangle
- complex.add_vertex();
- complex.add_edge(Vertex_handle(4),Vertex_handle(7));
- complex.add_edge(Vertex_handle(3),Vertex_handle(7));
- complex.add_blocker(Simplex_handle(Vertex_handle(0),Vertex_handle(1),Vertex_handle(6)));
- num_triangles_seen=0;
-
- TEST("triangles (should be 6 of them):");
- num_triangles_seen=0;
- for (auto t : complex.triangle_range()){
- PRINT(t);
- ++num_triangles_seen;
- }
- test = test&&(num_triangles_seen==6);
- PRINT(num_triangles_seen);
-
- return test;
-}
-
-
-//#include "combinatorics/Skeleton_blocker/iterators/Skeleton_blockers_simplices_iterators.h"
-
-bool test_iterator_simplices(){
- Complex complex(6);
- complex.add_edge(Vertex_handle(0),Vertex_handle(1));
- complex.add_edge(Vertex_handle(1),Vertex_handle(2));
- complex.add_edge(Vertex_handle(2),Vertex_handle(0));
- complex.add_edge(Vertex_handle(1),Vertex_handle(3));
- complex.add_edge(Vertex_handle(2),Vertex_handle(3));
- complex.add_edge(Vertex_handle(2),Vertex_handle(5));
- complex.add_edge(Vertex_handle(3),Vertex_handle(5));
- complex.add_edge(Vertex_handle(2),Vertex_handle(4));
- complex.add_edge(Vertex_handle(4),Vertex_handle(5));
- complex.add_edge(Vertex_handle(3),Vertex_handle(4));
-
- complex.add_blocker(Simplex_handle(Vertex_handle(2),Vertex_handle(3),Vertex_handle(4),Vertex_handle(5)));
-
- bool correct_number_simplices = true;
-
- std::map<Vertex_handle,unsigned> expected_num_simplices;
-
- expected_num_simplices[Vertex_handle(0)] = 4;
- expected_num_simplices[Vertex_handle(1)] = 6;
- expected_num_simplices[Vertex_handle(2)] = 11;
- expected_num_simplices[Vertex_handle(3)] = 9;
- expected_num_simplices[Vertex_handle(4)] = 7;
- expected_num_simplices[Vertex_handle(5)] = 7;
-
- for(auto pair : expected_num_simplices){
- unsigned num_simplices_around = 0;
- for(const auto& simplex : complex.simplex_range(pair.first)){
- simplex.dimension();
- DBGVALUE(simplex);
- ++num_simplices_around;
- }
-
- correct_number_simplices = correct_number_simplices && (num_simplices_around == pair.second);
-
- DBGMSG("current vertex:",pair.first);
- DBGMSG("expected_num_simplices:",pair.second);
- DBGMSG("found:",num_simplices_around);
- }
- return correct_number_simplices;
-}
-
-
-
-bool test_iterator_simplices2(){
- Complex complex(2);
- complex.add_edge(Vertex_handle(0),Vertex_handle(1));
-
- for(const auto& s:complex.triangle_range()){
- s.dimension();
- return false; // there are no triangles
- }
-
- unsigned num_simplices = 0 ;
-
-
- DBGVALUE(complex.to_string());
-
- for(const auto& simplex : complex.simplex_range(Vertex_handle(0))){
- simplex.dimension();
- DBGVALUE(simplex);
- }
-
-
- for(const auto& simplex : complex.simplex_range()){
- DBGVALUE(simplex);
- simplex.dimension();
- ++num_simplices;
- }
- bool correct_number_simplices = (num_simplices == 3);
- return correct_number_simplices;
-}
-
-
-bool test_iterator_simplices3(){
- Complex complex(3);
- complex.add_edge(Vertex_handle(0),Vertex_handle(1));
- complex.add_edge(Vertex_handle(1),Vertex_handle(2));
- complex.add_edge(Vertex_handle(2),Vertex_handle(0));
- complex.add_blocker(Simplex_handle(Vertex_handle(0),Vertex_handle(1),Vertex_handle(2)));
-
- unsigned num_simplices = 0 ;
-
- for(const auto& simplex : complex.simplex_range(Vertex_handle(0))){
- simplex.dimension();
- DBGVALUE(simplex);
- }
-
-
- for(const auto& simplex : complex.simplex_range()){
- DBGVALUE(simplex);
- simplex.dimension();
- ++num_simplices;
- }
- bool correct_number_simplices = (num_simplices == 6);
- return correct_number_simplices;
-}
-
-bool test_iterator_simplices4(){
- Complex empty_complex;
- for(auto v : empty_complex.vertex_range()){
- (void) v;
- }
- for(auto e : empty_complex.edge_range()){
- empty_complex[e];
- }
- for(auto t : empty_complex.triangle_range()){
- t.dimension();
- }
- for(auto s : empty_complex.simplex_range()){
- s.dimension();
- }
- return true;
-}
-
-
-
-
-
-template<typename Map>
-auto blocker_range(Map map) -> decltype( map | boost::adaptors::map_values){
- return map| boost::adaptors::map_values ;
-}
-
-
-bool test_iterator_blockers(){
- Complex complex;
- Simplex_handle alpha;
- Simplex_handle vertex_set_expected;
- // Build the complexes
- for (int i=0;i<20;i++){
- complex.add_vertex();
- }
- for (int i=10;i<15;i++){
- for (int j=i+1;j<15;j++)
- complex.add_edge(Vertex_handle(i),Vertex_handle(j));
- }
-
- complex.add_blocker(Simplex_handle(Vertex_handle(10),Vertex_handle(11),Vertex_handle(12)));
- complex.add_blocker(Simplex_handle(Vertex_handle(2),Vertex_handle(1),Vertex_handle(10)));
- complex.add_blocker(Simplex_handle(Vertex_handle(10),Vertex_handle(9),Vertex_handle(15)));
- complex.add_blocker(Simplex_handle(Vertex_handle(1),Vertex_handle(9),Vertex_handle(8)));
-
- // Print result
- int num_blockers=0;
- for(auto blockers : complex.blocker_range(Vertex_handle(10))){
- TESTVALUE(*blockers) ;
- num_blockers++;
- }
- bool test = (num_blockers==3);
-
- num_blockers=0;
- for (auto blockers : complex.blocker_range()){
- TESTVALUE(*blockers) ;
- num_blockers++;
- }
- test = test && (num_blockers==4) ;
-
- return test;
-}
-
-
-bool test_link0(){
-
- enum { a, b, c, d, n };
- Complex complex(n);
- complex.add_edge(Vertex_handle(b),Vertex_handle(c));complex.add_edge(Vertex_handle(c),Vertex_handle(d));
- Simplex_handle alpha = Simplex_handle(Vertex_handle(c));
- Skeleton_blocker_link_complex<Complex> L(complex,alpha);
-
- auto L2 = complex.link(alpha);
- if(L!=L2) return false;
-
- PRINT(L.num_vertices());
- PRINT(L.to_string());
-
- bool test1 = L.contains_vertex(*L.get_address(Root_vertex_handle(b)));
- bool test2 = L.contains_vertex(*L.get_address(Root_vertex_handle(d)));
- bool test3 = L.num_edges()==0;
- bool test4 = L.num_blockers()==0;
- return test1&&test2&&test3&&test4;
-
-}
-
-bool test_link1(){
- Complex complex;
-
-
- // Build the complexes
- for (int i=0;i<20;i++){
- complex.add_vertex();
- }
- for (int i=10;i<15;i++){
- for (int j=i+1;j<15;j++)
- complex.add_edge(Vertex_handle(i),Vertex_handle(j));
- }
- Simplex_handle alpha(Vertex_handle(12),Vertex_handle(14));
- Skeleton_blocker_link_complex<Complex> L(complex,alpha);
- // Complexes built
-
- auto L2 = complex.link(alpha);
- if(L!=L2) return false;
-
- // verification
- bool test1 = L.contains_vertex(*L.get_address(Root_vertex_handle(10)));
- bool test2 = L.contains_vertex(*L.get_address(Root_vertex_handle(11)));
- bool test3 = L.contains_vertex(*L.get_address(Root_vertex_handle(13)));
- bool test4 = L.num_edges()==3;
- bool test5 = L.num_blockers()==0;
- Root_simplex_handle simplex;
- simplex.add_vertex(Root_vertex_handle(10));
- simplex.add_vertex(Root_vertex_handle(11));
- simplex.add_vertex(Root_vertex_handle(13));
- bool test6(L.get_simplex_address(simplex));
- bool test7 = L.contains(*(L.get_simplex_address(simplex)));
- cerr <<"----> Ocomplex \n";
- return test1&&test2&&test3&&test4&&test5&&test6&&test7 ;
-
-}
-
-
-bool test_link2(){
- Complex complex;
-
- Simplex_handle alpha;
- Simplex_handle vertex_set_expected;
- // Build the complexes
- for (int i=0;i<20;i++){
- complex.add_vertex();
- }
- for (int i=10;i<15;i++){
- for (int j=i+1;j<15;j++)
- complex.add_edge(Vertex_handle(i),Vertex_handle(j));
- }
- complex.add_blocker(Simplex_handle(Vertex_handle(10),Vertex_handle(11),Vertex_handle(13)));
- alpha = Simplex_handle(Vertex_handle(12),Vertex_handle(14));
- Skeleton_blocker_link_complex<Complex> L(complex,alpha);
- // Complexes built
-
- // Print result
- cerr << "complex complex"<< complex.to_string();
- cerr <<endl<<endl;
- cerr << "L= Link_complex("<<alpha<<") : \n"<<L.to_string();
-
- auto L2 = complex.link(alpha);
- if(L!=L2) return false;
-
-
- // verification
- bool test1 = L.contains_vertex(*L.get_address(Root_vertex_handle(10)));
- bool test2 = L.contains_vertex(*L.get_address(Root_vertex_handle(11)));
- bool test3 = L.contains_vertex(*L.get_address(Root_vertex_handle(13)));
- bool test4 = L.num_edges()==3;
- bool test5 = L.num_blockers()==1;
- Root_simplex_handle simplex;
- simplex.add_vertex(Root_vertex_handle(10));
- simplex.add_vertex(Root_vertex_handle(11));
- simplex.add_vertex(Root_vertex_handle(13));
- bool test6 = L.contains_blocker(*(L.get_simplex_address(simplex)));
- cerr <<"----> Ocomplex \n";
- return test1&&test2&&test3&&test4&&test5&&test6 ;
-}
-
-bool test_link3(){
- Complex complex;
-
- Simplex_handle alpha;
- Simplex_handle vertex_set_expected;
- // Build the complexes
- for (int i=0;i<20;i++){
- complex.add_vertex();
- }
- for (int i=10;i<15;i++){
- for (int j=i+1;j<15;j++)
- complex.add_edge(Vertex_handle(i),Vertex_handle(j));
- }
- complex.add_blocker(Simplex_handle(Vertex_handle(10),Vertex_handle(11),Vertex_handle(12)));
- alpha = Simplex_handle(Vertex_handle(12),Vertex_handle(14));
- Skeleton_blocker_link_complex<Complex> L(complex,alpha);
- // Complexes built
-
- // Print result
- cerr << "complex complex"<< complex.to_string();
- cerr <<endl<<endl;
- cerr << "L= Link_complex("<<alpha<<") : \n"<<L.to_string();
-
- auto L2 = complex.link(alpha);
- if(L!=L2) return false;
-
-
- // verification
- bool test = assert_vertex(L,*L.get_address(Root_vertex_handle(10)));
- test = test&& assert_vertex(L,*L.get_address(Root_vertex_handle(11)));
- test = test&& assert_vertex(L,*L.get_address(Root_vertex_handle(13)));
- test = test&& L.num_edges()==2;
- test = test&&L.contains_edge(*L.get_address(Root_vertex_handle(10)),*L.get_address(Root_vertex_handle(13)));
- test=test&&L.contains_edge(*L.get_address(Root_vertex_handle(13)),*L.get_address(Root_vertex_handle(11)));
- test=test&&L.num_blockers()==0;
- return test;
-}
-
-bool test_link4(){
- Complex complex;
-
- // Build the complexes
- for (int i=0;i<20;i++){
- complex.add_vertex();
- }
- for (int i=10;i<15;i++){
- for (int j=i+1;j<15;j++)
- complex.add_edge(Vertex_handle(i),Vertex_handle(j));
- }
- complex.add_blocker(Simplex_handle(Vertex_handle(10),Vertex_handle(11),Vertex_handle(12),Vertex_handle(13)));
- Simplex_handle alpha(Vertex_handle(12),Vertex_handle(14));
- Skeleton_blocker_link_complex<Complex> L(complex,alpha);
- // Complexes built
-
- // verification
- bool test1 = L.contains_vertex(*L.get_address(Root_vertex_handle(10)));
- bool test2 = L.contains_vertex(*L.get_address(Root_vertex_handle(11)));
- bool test3 = L.contains_vertex(*L.get_address(Root_vertex_handle(13)));
- bool test4 = L.num_edges()==3;
- bool test5 = L.num_blockers()==1;
- Root_simplex_handle simplex;
- simplex.add_vertex(Root_vertex_handle(10));
- simplex.add_vertex(Root_vertex_handle(11));
- simplex.add_vertex(Root_vertex_handle(13));
- bool test6 = L.contains_blocker(*(L.get_simplex_address(simplex)));
- cerr <<"----> Ocomplex \n";
- return test1&&test2&&test3&&test4&&test5&&test6 ;
-
-}
-
-bool test_link5(){
- Complex complex(0,new Print_complex_visitor<Vertex_handle>());
- // Build the complexes
- build_complete(4,complex);
- complex.add_blocker(Simplex_handle(Vertex_handle(0),Vertex_handle(1),Vertex_handle(2),Vertex_handle(3)));
-
- Simplex_handle alpha(Vertex_handle(0),Vertex_handle(1),Vertex_handle(2));
-
-
- Skeleton_blocker_link_complex<Complex> L(complex,alpha); // Complexes built
-
- // Print result
- PRINT(complex.to_string());
- cerr <<endl<<endl;
- PRINT(L.to_string());
-
- // verification
- return L.num_vertices()==0;
-}
-
-bool test_link6(){
- Complex complex(0,new Print_complex_visitor<Vertex_handle>());
- // Build the complexes
- build_complete(4,complex);
- complex.add_blocker(Simplex_handle(Vertex_handle(0),Vertex_handle(1),Vertex_handle(2)));
-
- Simplex_handle alpha(Vertex_handle(0),Vertex_handle(1),Vertex_handle(2));
-
- Skeleton_blocker_link_complex<Complex> link_blocker_alpha;
-
- build_link_of_blocker(complex,alpha,link_blocker_alpha);
-
- // Print result
- PRINT(complex.to_string());
- cerr <<endl<<endl;
- PRINT(link_blocker_alpha.to_string());
-
- // verification
- return link_blocker_alpha.num_vertices()==1;
-}
-
-
-bool test_link7(){
- Complex complex(0,new Print_complex_visitor<Vertex_handle>());
- // Build the complexes
- build_complete(6,complex);
- complex.add_vertex();
- complex.add_vertex();
- for(int i = 3; i<6; ++i){
- complex.add_edge(Vertex_handle(i),Vertex_handle(6));
- complex.add_edge(Vertex_handle(i),Vertex_handle(7));
- }
- complex.add_edge(Vertex_handle(6),Vertex_handle(7));
- complex.add_blocker(Simplex_handle(Vertex_handle(0),Vertex_handle(1),Vertex_handle(2)));
- complex.add_blocker(Simplex_handle(Vertex_handle(3),Vertex_handle(4),Vertex_handle(5)));
-
- Simplex_handle alpha(Vertex_handle(3),Vertex_handle(4),Vertex_handle(5));
-
- Skeleton_blocker_link_complex<Complex> link_blocker_alpha;
-
- build_link_of_blocker(complex,alpha,link_blocker_alpha);
-
- //the result should be the edge {6,7} plus the blocker {0,1,2}
-
- // Print result
- PRINT(complex.to_string());
- cerr <<endl<<endl;
- DBGVALUE(link_blocker_alpha.to_string());
-
- Skeleton_blocker_link_complex<Complex> link_blocker_alpha_cpy = link_blocker_alpha;
-
- DBGVALUE(link_blocker_alpha_cpy.to_string());
-
- bool equal_complexes =
- (link_blocker_alpha.num_vertices() == link_blocker_alpha_cpy.num_vertices())
- &&(link_blocker_alpha.num_blockers() == link_blocker_alpha_cpy.num_blockers())
- &&(link_blocker_alpha.num_edges() == link_blocker_alpha_cpy.num_edges())
- ;
- DBGVALUE((link_blocker_alpha.num_blockers() == link_blocker_alpha_cpy.num_blockers()));
- DBGVALUE((link_blocker_alpha.num_blockers() ));
- DBGVALUE(( link_blocker_alpha_cpy.num_blockers()));
-
- DBGVALUE(equal_complexes);
-
- // verification
- return link_blocker_alpha.num_vertices()==5 && link_blocker_alpha.num_edges()==4 && link_blocker_alpha.num_blockers()==1 && equal_complexes;
-}
-
-
-
-
-
-
-
-
-template<typename SimplexHandle>
-void add_triangle_edges(int a,int b,int c,list<SimplexHandle>& simplices){
- typedef SimplexHandle Simplex_handle;
- typedef typename SimplexHandle::Vertex_handle Vertex_handle;
-
- simplices.push_back(Simplex_handle(Vertex_handle(a),Vertex_handle(b) ));
- simplices.push_back(Simplex_handle(Vertex_handle(b),Vertex_handle(c) ));
- simplices.push_back(Simplex_handle(Vertex_handle(c),Vertex_handle(a) ));
-}
-
-template<typename SimplexHandle>
-void add_triangle(int a,int b,int c,list<SimplexHandle>& simplices){
- typedef SimplexHandle Simplex_handle;
- typedef typename SimplexHandle::Vertex_handle Vertex_handle;
- simplices.push_back(Simplex_handle(Vertex_handle(a),Vertex_handle(b),Vertex_handle(c)));
-}
-
-bool test_constructor(){
- list <Simplex_handle> simplices;
-
- simplices.push_back(Simplex_handle(Vertex_handle(0)));
- simplices.push_back(Simplex_handle(Vertex_handle(1)));
- simplices.push_back(Simplex_handle(Vertex_handle(2)));
- simplices.push_back(Simplex_handle(Vertex_handle(3)));
- simplices.push_back(Simplex_handle(Vertex_handle(4)));
- simplices.push_back(Simplex_handle(Vertex_handle(5)));
-
- simplices.push_back(Simplex_handle(Vertex_handle(3),Vertex_handle(5) ));
-
- add_triangle_edges(0,1,5,simplices);
- add_triangle_edges(1,2,3,simplices);
- add_triangle_edges(2,3,4,simplices);
- add_triangle_edges(1,3,4,simplices);
- add_triangle_edges(1,2,4,simplices);
-
-
- add_triangle(0,1,5,simplices);
- add_triangle(1,2,3,simplices);
- add_triangle(1,3,4,simplices);
- add_triangle(1,2,4,simplices);
- add_triangle(2,3,4,simplices);
-
- Complex complex(simplices.begin(),simplices.end());
-
- PRINT(complex.to_string());
-
- return ( complex.num_vertices()==6&&complex.num_edges()==10&& complex.num_blockers()==2);
-}
-
-
-list<Simplex_handle> subfaces(Simplex_handle top_face){
- list<Simplex_handle> res;
- if(top_face.dimension()==-1) return res;
- if(top_face.dimension()==0) {
- res.push_back(top_face);
- return res;
- }
- else{
- Vertex_handle first_vertex = top_face.first_vertex();
- top_face.remove_vertex(first_vertex);
- res = subfaces(top_face);
- list<Simplex_handle> copy = res;
- for(auto& simplex : copy){
- simplex.add_vertex(first_vertex);
- }
- res.push_back(Simplex_handle(first_vertex));
- res.splice(res.end(),copy);
- return res;
- }
-}
-
-
-bool test_constructor2(){
- Simplex_handle simplex;
- for(int i =0 ; i < 5;++i)
- simplex.add_vertex(static_cast<Vertex_handle>(i));
-
- list <Simplex_handle> simplices(subfaces(simplex));
- simplices.remove(simplex);
-
- Complex complex(simplices.begin(),simplices.end());
-
- PRINT(complex.to_string());
-
- for(auto b : complex.const_blocker_range()){
- cout << "b:"<<b<<endl;
- }
-
- return ( complex.num_vertices()==5&&complex.num_edges()==10&& complex.num_blockers()==1);
-}
-
-
-bool test_constructor3(){
- typedef Vertex_handle Vh;
- typedef Simplex_handle Sh;
- std::vector<Simplex_handle> simplices;
- auto subf(subfaces(Sh(Vh(0),Vh(1),Vh(2))));
- subf.pop_back(); //remove max face -> now a blocker 012
- simplices.insert(simplices.begin(),subf.begin(),subf.end());
- DBGCONT(simplices);
- Complex complex(simplices.begin(),simplices.end());
-
- DBGVALUE(complex.to_string());
-
- if(complex.num_blockers()!=1) return false;
- Sh expected_blocker(Vh(0),Vh(1),Vh(2));
- for(auto b : complex.const_blocker_range())
- if(*b!=expected_blocker) return false;
-
-
- return complex.num_vertices()==3 && complex.num_blockers()==1;
-}
-
-bool test_constructor4(){
- typedef Vertex_handle Vh;
- typedef Simplex_handle Sh;
- std::vector<Simplex_handle> simplices;
- auto subf(subfaces(Sh(Vh(0),Vh(1),Vh(2),Vh(3))));
- simplices.insert(simplices.begin(),subf.begin(),subf.end());
-
- simplices.push_back(Sh(Vh(4)));
- simplices.push_back(Sh(Vh(4),Vh(1)));
- simplices.push_back(Sh(Vh(4),Vh(0)));
-
- DBGCONT(simplices);
- Complex complex(simplices.begin(),simplices.end());
-
- DBGVALUE(complex.to_string());
- if(complex.num_blockers()!=1) return false;
- Sh expected_blocker(Vh(0),Vh(1),Vh(4));
- for(auto b : complex.const_blocker_range())
- if(*b!=expected_blocker) return false;
-
- return complex.num_vertices()==5 && complex.num_blockers()==1 && complex.num_edges()==8;
-}
-
-
-
-bool test_constructor5(){
- typedef Vertex_handle Vh;
- typedef Simplex_handle Sh;
- std::vector<Simplex_handle> simplices;
- auto subf(subfaces(Sh(Vh(0),Vh(1),Vh(2))));
- simplices.insert(simplices.begin(),subf.begin(),subf.end());
-
- simplices.push_back(Sh(Vh(3)));
- simplices.push_back(Sh(Vh(3),Vh(1)));
- simplices.push_back(Sh(Vh(3),Vh(2)));
- simplices.push_back(Sh(Vh(4)));
- simplices.push_back(Sh(Vh(4),Vh(1)));
- simplices.push_back(Sh(Vh(4),Vh(0)));
- simplices.push_back(Sh(Vh(5)));
- simplices.push_back(Sh(Vh(5),Vh(2)));
- simplices.push_back(Sh(Vh(5),Vh(0)));
-
- DBGCONT(simplices);
- Complex complex(simplices.begin(),simplices.end());
-
- DBGVALUE(complex.to_string());
-
- return complex.num_vertices()==6 && complex.num_blockers()==3 && complex.num_edges()==9;
-}
-
-
-bool test_constructor6(){
- typedef Vertex_handle Vh;
- typedef Simplex_handle Sh;
- std::vector<Simplex_handle> simplices;
- auto subf(subfaces(Sh(Vh(0),Vh(1),Vh(2),Vh(3))));
- for(auto s:subf){
- Sh s1(Vh(0),Vh(1),Vh(2),Vh(3));
- Sh s2(Vh(1),Vh(2),Vh(3));
- if(s!=s1 && s!=s2) simplices.push_back(s);
- }
-
- DBGCONT(simplices);
- Complex complex(simplices.begin(),simplices.end());
-
- DBGVALUE(complex.to_string());
-
- if(complex.num_blockers()!=1) return false;
- Sh expected_blocker(Vh(1),Vh(2),Vh(3));
- for(auto b : complex.const_blocker_range())
- if(*b!=expected_blocker) return false;
- return complex.num_vertices()==4 && complex.num_blockers()==1 && complex.num_edges()==6;
-}
-
-
-bool test_constructor7(){
- typedef Vertex_handle Vh;
- typedef Simplex_handle Sh;
- std::vector<Simplex_handle> simplices;
- simplices.push_back(Sh(Vh(0),Vh(1),Vh(2)));
- simplices.push_back(Sh(Vh(1),Vh(2),Vh(3)));
- simplices.push_back(Sh(Vh(3),Vh(0),Vh(2)));
- simplices.push_back(Sh(Vh(3),Vh(0),Vh(1)));
-
- //get complex from top faces
- Complex complex(make_complex_from_top_faces<Complex>(simplices.begin(),simplices.end()));
-
- DBGVALUE(complex.to_string());
-
- if(complex.num_blockers()!=1) return false;
- Sh expected_blocker(Vh(0),Vh(1),Vh(2),Vh(3));
- for(auto b : complex.const_blocker_range())
- if(*b!=expected_blocker) return false;
- return complex.num_vertices()==4 && complex.num_blockers()==1 && complex.num_edges()==6;
-}
-
-
-bool test_constructor8(){
- typedef Vertex_handle Vh;
- typedef Simplex_handle Sh;
- std::vector<Simplex_handle> simplices;
- simplices.push_back(Sh(Vh(0),Vh(1)));
- simplices.push_back(Sh(Vh(2),Vh(1)));
- simplices.push_back(Sh(Vh(0),Vh(2)));
- simplices.push_back(Sh(Vh(3),Vh(1)));
- simplices.push_back(Sh(Vh(2),Vh(3)));
-
- //get complex from top faces
- Complex complex(make_complex_from_top_faces<Complex>(simplices.begin(),simplices.end()));
-
- DBGVALUE(complex.to_string());
-
- return complex.num_vertices()==4 && complex.num_blockers()==2 && complex.num_edges()==5;
-}
-
-
-
-
-
-int main (int argc, char *argv[])
-{
- Tests tests_complex;
- tests_complex.add("test simplex",test_simplex);
- tests_complex.add("test_link0",test_link0);
- tests_complex.add("test_link1",test_link1);
- tests_complex.add("test_link2",test_link2);
- tests_complex.add("test_link3",test_link3);
- tests_complex.add("test_link4",test_link4);
- tests_complex.add("test_link5",test_link5);
- tests_complex.add("test_link6",test_link6);
- tests_complex.add("test_link7",test_link7);
-
- tests_complex.add("test iterator vertices 1",test_iterator_vertices1);
- tests_complex.add("test iterator vertices 2",test_iterator_vertices2);
- tests_complex.add("test iterator edges",test_iterator_edge);
- tests_complex.add("test iterator edges 2",test_iterator_edge2);
- tests_complex.add("test iterator edges 3",test_iterator_edge3);
-
- tests_complex.add("test iterator simplices",test_iterator_simplices);
- tests_complex.add("test iterator simplices2",test_iterator_simplices2);
- tests_complex.add("test iterator simplices3",test_iterator_simplices3);
- tests_complex.add("test iterator simplices4",test_iterator_simplices4);
-
-
- tests_complex.add("test iterator blockers",test_iterator_blockers);
- tests_complex.add("test_iterator_triangles",test_iterator_triangles);
-
- tests_complex.add("test_constructor_list_simplices",test_constructor);
- tests_complex.add("test_constructor_list_simplices2",test_constructor2);
- tests_complex.add("test_constructor_list_simplices3",test_constructor3);
- tests_complex.add("test_constructor_list_simplices4",test_constructor4);
- tests_complex.add("test_constructor_list_simplices5",test_constructor5);
- tests_complex.add("test_constructor_list_simplices6",test_constructor6);
- tests_complex.add("test_constructor_list_simplices7",test_constructor7);
- tests_complex.add("test_constructor_list_simplices8",test_constructor8);
-
-
- if(tests_complex.run()){
- return EXIT_SUCCESS;
- }
- else{
- return EXIT_FAILURE;
- }
-
- // test_iterator_simplices();
-}
-
diff --git a/src/Skeleton_blocker/test/test_skeleton_blocker_complex.cpp b/src/Skeleton_blocker/test/test_skeleton_blocker_complex.cpp
new file mode 100644
index 00000000..4f9888ba
--- /dev/null
+++ b/src/Skeleton_blocker/test/test_skeleton_blocker_complex.cpp
@@ -0,0 +1,837 @@
+/* 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/>.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+#include <fstream>
+#include <sstream>
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE "skeleton_blocker_complex"
+#include <boost/test/unit_test.hpp>
+#include <boost/mpl/list.hpp>
+
+#include <gudhi/Skeleton_blocker.h>
+
+template<typename ComplexType> class Skeleton_blocker_sub_complex;
+typedef Gudhi::skeleton_blocker::Skeleton_blocker_simple_traits Traits;
+typedef Gudhi::skeleton_blocker::Skeleton_blocker_complex<Traits> Complex;
+typedef Gudhi::skeleton_blocker::Skeleton_blocker_link_complex<Complex> Skeleton_blocker_link_complex;
+typedef Complex::Vertex_handle Vertex_handle;
+typedef Complex::Root_vertex_handle Root_vertex_handle;
+typedef Complex::Simplex Simplex;
+typedef Complex::Root_simplex_handle Root_simplex_handle;
+typedef Simplex::Simplex_vertex_const_iterator Simplex_vertex_const_iterator;
+typedef Complex::Edge_handle Edge_handle;
+
+bool assert_vertex(Complex &complex, Vertex_handle v) {
+ //assert(complex.contains(v));
+ return complex.contains(static_cast<Simplex> (v));
+}
+
+bool assert_simplex(Complex &complex, Root_vertex_handle a, Root_vertex_handle b, Root_vertex_handle c) {
+ return true;
+ // AddressSimplex simplex((a),(b),(c));
+ // return complex.contains(&simplex);
+}
+
+// true iff the blocker (a,b,c) is in complex
+
+bool assert_blocker(Complex &complex, Root_vertex_handle a, Root_vertex_handle b, Root_vertex_handle c) {
+ return true;
+ //return complex.contains_blocker((a),(b),(c));
+}
+
+// true iff the blocker (a,b,c,d) is in complex
+
+bool assert_blocker(Complex &complex, Root_vertex_handle a, Root_vertex_handle b, Root_vertex_handle c, Root_vertex_handle d) {
+ return true;
+ //Simplex blocker (a,b,c,d);
+ //return complex.contains_blocker(&blocker);
+}
+
+void build_complete(int n, Complex& complex) {
+ complex.clear();
+ 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));
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_simplex) {
+ Simplex simplex(Vertex_handle(0), Vertex_handle(1), Vertex_handle(2), Vertex_handle(3));
+ BOOST_CHECK(simplex.dimension() == 3);
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_num_simplices) {
+ int n = 4;
+ Complex complex;
+ build_complete(n, complex);
+ size_t sum = 0;
+ for (int i = 0; i < n; i++) {
+ sum += complex.num_simplices(i);
+ }
+ BOOST_CHECK(complex.num_vertices() == n);
+ BOOST_CHECK(complex.num_edges() == 6);
+ BOOST_CHECK(sum == 15);
+ BOOST_CHECK(complex.num_simplices() == 15);
+}
+
+
+BOOST_AUTO_TEST_CASE(test_skeleton_iterator_vertices1) {
+ int n = 10;
+ Complex complex(10);
+ std::cout << "complex.num_vertices():" << complex.num_vertices() << std::endl;
+ int num_vertex_seen = 0;
+ for (auto vi : complex.vertex_range()) {
+ std::cout << "vertex:" << vi << std::endl;
+ ++num_vertex_seen;
+ }
+ BOOST_CHECK(num_vertex_seen == n);
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_iterator_vertices2) {
+ int n = 10;
+ Complex complex;
+ build_complete(10, complex);
+ std::cout << "complex.num_vertices():" << complex.num_vertices() << std::endl;
+ std::cout << "complex.num_edges():" << complex.num_edges() << std::endl;
+ int num_vertex_seen = 0;
+ for (auto vi : complex.vertex_range(Vertex_handle(2))) {
+ std::cout << "vertex:" << vi << std::endl;
+ ++num_vertex_seen;
+ }
+ std::cout << "num_vertex_seen:" << num_vertex_seen << std::endl;
+ BOOST_CHECK(num_vertex_seen == (n -1));
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_iterator_edge) {
+ const int n = 10;
+ Complex complex(n);
+ 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));
+ complex.remove_edge(Vertex_handle(2), Vertex_handle(3));
+ complex.remove_edge(Vertex_handle(3), Vertex_handle(5));
+ std::cout << "complex.num_edges():" << complex.num_edges() << std::endl;
+ int num_edges_seen = 0;
+ for (auto edge : complex.edge_range()) {
+ std::cout << "edge :" << complex[edge] << std::endl;
+ ++num_edges_seen;
+ }
+
+ BOOST_CHECK(num_edges_seen == n * (n - 1) / 2 - 2);
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_iterator_edge2) {
+ const int n = 10;
+ Complex complex(n);
+ 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));
+ complex.remove_edge(Vertex_handle(2), Vertex_handle(3));
+ complex.remove_edge(Vertex_handle(3), Vertex_handle(5));
+ std::cout << "complex.num_edges():" << complex.num_edges() << std::endl;
+ int num_neigbors_seen = 0;
+ for (auto neighbor : complex.vertex_range(Vertex_handle(2))) {
+ std::cout << "neighbor" << neighbor << std::endl;
+ ++num_neigbors_seen;
+ }
+ BOOST_CHECK(num_neigbors_seen == 8);
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_iterator_triangles) {
+ const int n = 7;
+ Complex complex(n);
+ //create a "ring" around '0'
+ for (int i = 1; i < n; i++)
+ complex.add_edge_without_blockers(Vertex_handle(0), Vertex_handle(i));
+ for (int i = 1; i < n - 1; i++)
+ complex.add_edge_without_blockers(Vertex_handle(i), Vertex_handle(i + 1));
+ complex.add_edge_without_blockers(Vertex_handle(1), Vertex_handle(6));
+
+ std::cout << complex.to_string() << std::endl;
+
+ int num_triangles_seen = 0;
+ //for (auto t : complex.triangle_range(5)){
+ for (auto t : complex.triangle_range(Vertex_handle(5))) {
+ ++num_triangles_seen;
+ }
+ BOOST_CHECK(num_triangles_seen == 2);
+
+ num_triangles_seen = 0;
+ for (auto t : complex.triangle_range(Vertex_handle(0))) {
+ ++num_triangles_seen;
+ }
+ BOOST_CHECK(num_triangles_seen == 6);
+
+ // we now add another triangle
+ complex.add_vertex();
+ complex.add_edge_without_blockers(Vertex_handle(4), Vertex_handle(7));
+ complex.add_edge_without_blockers(Vertex_handle(3), Vertex_handle(7));
+ complex.add_blocker(Simplex(Vertex_handle(0), Vertex_handle(1), Vertex_handle(6)));
+ num_triangles_seen = 0;
+
+ num_triangles_seen = 0;
+ for (auto t : complex.triangle_range()) {
+ ++num_triangles_seen;
+ }
+ BOOST_CHECK(num_triangles_seen == 6);
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_iterator_simplices) {
+ Complex complex(6);
+ complex.add_edge_without_blockers(Vertex_handle(0), Vertex_handle(1));
+ complex.add_edge_without_blockers(Vertex_handle(1), Vertex_handle(2));
+ complex.add_edge_without_blockers(Vertex_handle(2), Vertex_handle(0));
+ complex.add_edge_without_blockers(Vertex_handle(1), Vertex_handle(3));
+ complex.add_edge_without_blockers(Vertex_handle(2), Vertex_handle(3));
+ complex.add_edge_without_blockers(Vertex_handle(2), Vertex_handle(5));
+ complex.add_edge_without_blockers(Vertex_handle(3), Vertex_handle(5));
+ complex.add_edge_without_blockers(Vertex_handle(2), Vertex_handle(4));
+ complex.add_edge_without_blockers(Vertex_handle(4), Vertex_handle(5));
+ complex.add_edge_without_blockers(Vertex_handle(3), Vertex_handle(4));
+
+ complex.add_blocker(Simplex(Vertex_handle(2), Vertex_handle(3), Vertex_handle(4), Vertex_handle(5)));
+
+ std::map<Vertex_handle, unsigned> expected_num_simplices;
+
+ expected_num_simplices[Vertex_handle(0)] = 4;
+ expected_num_simplices[Vertex_handle(1)] = 6;
+ expected_num_simplices[Vertex_handle(2)] = 11;
+ expected_num_simplices[Vertex_handle(3)] = 9;
+ expected_num_simplices[Vertex_handle(4)] = 7;
+ expected_num_simplices[Vertex_handle(5)] = 7;
+
+ for (auto pair : expected_num_simplices) {
+ std::cout << "found list: ";
+ unsigned num_simplices_around = 0;
+ for (const auto& simplex : complex.star_simplex_range(pair.first)) {
+ simplex.dimension();
+ std::cout << simplex << " - ";
+ ++num_simplices_around;
+ }
+
+ BOOST_CHECK(num_simplices_around == pair.second);
+
+ std::cout << std::endl << "current vertex:" << pair.first << " - ";
+ std::cout << "expected_num_simplices:" << pair.second << " - ";
+ std::cout << "found:" << num_simplices_around << std::endl;
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_iterator_simplices2) {
+ Complex complex(2);
+ complex.add_edge_without_blockers(Vertex_handle(0), Vertex_handle(1));
+
+ // Check there is no triangle
+ BOOST_CHECK(std::distance(complex.triangle_range().begin(), complex.triangle_range().end()) == 0);
+
+ // Star(0) is [{0},{0,1}]
+ BOOST_CHECK(std::distance(complex.star_simplex_range(Vertex_handle(0)).begin(),
+ complex.star_simplex_range(Vertex_handle(0)).end()) == 2);
+
+ // No blocker
+ BOOST_CHECK(std::distance(complex.blocker_range(Vertex_handle(0)).begin(),
+ complex.blocker_range(Vertex_handle(0)).end()) == 0);
+
+ // Complex is [{0},{0,1},{1}]
+ BOOST_CHECK(std::distance(complex.complex_simplex_range().begin(),
+ complex.complex_simplex_range().end()) == 3);
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_iterator_simplices3) {
+ Complex complex(3);
+ complex.add_edge_without_blockers(Vertex_handle(0), Vertex_handle(1));
+ complex.add_edge_without_blockers(Vertex_handle(1), Vertex_handle(2));
+ complex.add_edge_without_blockers(Vertex_handle(2), Vertex_handle(0));
+ complex.add_blocker(Simplex(Vertex_handle(0), Vertex_handle(1), Vertex_handle(2)));
+
+ // Check there is no triangle
+ BOOST_CHECK(std::distance(complex.triangle_range().begin(), complex.triangle_range().end()) == 0);
+
+ // Star(0) is [{0},{0,1},{0,2}]
+ BOOST_CHECK(std::distance(complex.star_simplex_range(Vertex_handle(0)).begin(),
+ complex.star_simplex_range(Vertex_handle(0)).end()) == 3);
+
+ // blocker(0) is [{0,1,2}]
+ BOOST_CHECK(std::distance(complex.blocker_range(Vertex_handle(0)).begin(),
+ complex.blocker_range(Vertex_handle(0)).end()) == 1);
+
+ // Complex is [{0},{0,1},{0,2},{1},{1,2},{2}]
+ BOOST_CHECK(std::distance(complex.complex_simplex_range().begin(),
+ complex.complex_simplex_range().end()) == 6);
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_iterator_simplices4) {
+ Complex empty_complex;
+ for (auto v : empty_complex.vertex_range()) {
+ std::cout << v;
+ BOOST_CHECK(false);
+ }
+ for (auto e : empty_complex.edge_range()) {
+ std::cout << e;
+ BOOST_CHECK(false);
+ }
+ for (auto t : empty_complex.triangle_range()) {
+ std::cout << t;
+ BOOST_CHECK(false);
+ }
+ for (auto s : empty_complex.complex_simplex_range()) {
+ std::cout << s;
+ BOOST_CHECK(false);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_iterator_coboundary) {
+ Complex c;
+ build_complete(4, c);
+ c.remove_edge(Vertex_handle(1), Vertex_handle(3));
+ std::cout << c.to_string();
+ Simplex s02(Vertex_handle(0), Vertex_handle(2));
+ int n = 0;
+ std::set<Simplex> expected;
+ expected.insert(Simplex(Vertex_handle(0), Vertex_handle(1), Vertex_handle(2)));
+ expected.insert(Simplex(Vertex_handle(0), Vertex_handle(2), Vertex_handle(3)));
+ for (const auto & s : c.coboundary_range(s02)) {
+ BOOST_CHECK(expected.find(s) != expected.end());
+ ++n;
+ }
+ BOOST_CHECK(n == 2);
+}
+
+template<typename Map>
+auto blocker_range(Map map) -> decltype(map | boost::adaptors::map_values) {
+ return map | boost::adaptors::map_values;
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_iterator_blockers) {
+ Complex complex;
+ Simplex alpha;
+ Simplex vertex_set_expected;
+ // Build the complexes
+ for (int i = 0; i < 20; i++) {
+ complex.add_vertex();
+ }
+ for (int i = 10; i < 15; i++) {
+ for (int j = i + 1; j < 15; j++)
+ complex.add_edge_without_blockers(Vertex_handle(i), Vertex_handle(j));
+ }
+
+ std::vector<Simplex> myBlockers;
+ myBlockers.push_back(Simplex(Vertex_handle(10), Vertex_handle(11), Vertex_handle(12)));
+ myBlockers.push_back(Simplex(Vertex_handle(2), Vertex_handle(1), Vertex_handle(10)));
+ myBlockers.push_back(Simplex(Vertex_handle(10), Vertex_handle(9), Vertex_handle(15)));
+ myBlockers.push_back(Simplex(Vertex_handle(1), Vertex_handle(9), Vertex_handle(8)));
+
+ for (auto blocker : myBlockers)
+ complex.add_blocker(blocker);
+
+ int num_blockers = 0;
+ for (auto blockers : complex.blocker_range(Vertex_handle(10))) {
+ // Only the first 3 blockers contain vertex 10
+ BOOST_CHECK(*blockers == myBlockers[num_blockers]);
+ num_blockers++;
+ }
+ BOOST_CHECK(num_blockers == 3);
+
+ num_blockers = 0;
+ for (auto blockers : complex.blocker_range()) {
+// If not windows - _WIN32 is for windows 32 and 64 bits
+#ifndef _WIN32
+ for (auto block_ptr = myBlockers.begin(); block_ptr < myBlockers.end(); block_ptr++)
+ if (*block_ptr == *blockers)
+ myBlockers.erase(block_ptr);
+#endif
+ num_blockers++;
+ }
+ BOOST_CHECK(num_blockers == 4);
+// If not windows - _WIN32 is for windows 32 and 64 bits
+#ifndef _WIN32
+ BOOST_CHECK(myBlockers.empty());
+#endif
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_complex_link0) {
+ enum { a, b, c, d, n };
+ Complex complex(n);
+ complex.add_edge_without_blockers(Vertex_handle(b), Vertex_handle(c));
+ complex.add_edge_without_blockers(Vertex_handle(c), Vertex_handle(d));
+ Simplex alpha = Simplex(Vertex_handle(c));
+ Skeleton_blocker_link_complex L(complex, alpha);
+
+ auto L2 = complex.link(alpha);
+ BOOST_CHECK(L == L2);
+
+ std::cout << L.to_string();
+
+ BOOST_CHECK(L.contains_vertex(*L.get_address(Root_vertex_handle(b))));
+ BOOST_CHECK(L.contains_vertex(*L.get_address(Root_vertex_handle(d))));
+ BOOST_CHECK(L.num_edges() == 0);
+ BOOST_CHECK(L.num_blockers() == 0);
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_complex_link1) {
+ Complex complex;
+
+ // Build the complexes
+ for (int i = 0; i < 20; i++) {
+ complex.add_vertex();
+ }
+ for (int i = 10; i < 15; i++) {
+ for (int j = i + 1; j < 15; j++)
+ complex.add_edge_without_blockers(Vertex_handle(i), Vertex_handle(j));
+ }
+ Simplex alpha(Vertex_handle(12), Vertex_handle(14));
+ Skeleton_blocker_link_complex L(complex, alpha);
+ // Complexes built
+
+ auto L2 = complex.link(alpha);
+ BOOST_CHECK(L == L2);
+
+ // verification
+ BOOST_CHECK(L.contains_vertex(*L.get_address(Root_vertex_handle(10))));
+ BOOST_CHECK(L.contains_vertex(*L.get_address(Root_vertex_handle(11))));
+ BOOST_CHECK(L.contains_vertex(*L.get_address(Root_vertex_handle(13))));
+ BOOST_CHECK(L.num_edges() == 3);
+ BOOST_CHECK(L.num_blockers() == 0);
+ Root_simplex_handle simplex;
+ simplex.add_vertex(Root_vertex_handle(10));
+ simplex.add_vertex(Root_vertex_handle(11));
+ simplex.add_vertex(Root_vertex_handle(13));
+ BOOST_CHECK(L.get_simplex_address(simplex));
+ BOOST_CHECK(L.contains(*(L.get_simplex_address(simplex))));
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_complex_link2) {
+ Complex complex;
+
+ Simplex alpha;
+ Simplex vertex_set_expected;
+ // Build the complexes
+ for (int i = 0; i < 20; i++) {
+ complex.add_vertex();
+ }
+ for (int i = 10; i < 15; i++) {
+ for (int j = i + 1; j < 15; j++)
+ complex.add_edge_without_blockers(Vertex_handle(i), Vertex_handle(j));
+ }
+ complex.add_blocker(Simplex(Vertex_handle(10), Vertex_handle(11), Vertex_handle(13)));
+ alpha = Simplex(Vertex_handle(12), Vertex_handle(14));
+ Skeleton_blocker_link_complex L(complex, alpha);
+ // Complexes built
+
+ // Print result
+ std::cout << "complex complex" << complex.to_string();
+ std::cout << std::endl << std::endl;
+ std::cout << "L= Link_complex(" << alpha << ") : \n" << L.to_string();
+
+ auto L2 = complex.link(alpha);
+ BOOST_CHECK(L == L2);
+
+
+ // verification
+ BOOST_CHECK(L.contains_vertex(*L.get_address(Root_vertex_handle(10))));
+ BOOST_CHECK(L.contains_vertex(*L.get_address(Root_vertex_handle(11))));
+ BOOST_CHECK(L.contains_vertex(*L.get_address(Root_vertex_handle(13))));
+ BOOST_CHECK(L.num_edges() == 3);
+ BOOST_CHECK(L.num_blockers() == 1);
+ Root_simplex_handle simplex;
+ simplex.add_vertex(Root_vertex_handle(10));
+ simplex.add_vertex(Root_vertex_handle(11));
+ simplex.add_vertex(Root_vertex_handle(13));
+ BOOST_CHECK(L.contains_blocker(*(L.get_simplex_address(simplex))));
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_complex_link3) {
+ Complex complex;
+
+ Simplex alpha;
+ Simplex vertex_set_expected;
+ // Build the complexes
+ for (int i = 0; i < 20; i++) {
+ complex.add_vertex();
+ }
+ for (int i = 10; i < 15; i++) {
+ for (int j = i + 1; j < 15; j++)
+ complex.add_edge_without_blockers(Vertex_handle(i), Vertex_handle(j));
+ }
+ complex.add_blocker(Simplex(Vertex_handle(10), Vertex_handle(11), Vertex_handle(12)));
+ alpha = Simplex(Vertex_handle(12), Vertex_handle(14));
+ Skeleton_blocker_link_complex L(complex, alpha);
+ // Complexes built
+
+ // Print result
+ std::cout << "complex complex" << complex.to_string();
+ std::cout << std::endl << std::endl;
+ std::cout << "L= Link_complex(" << alpha << ") : \n" << L.to_string();
+
+ auto L2 = complex.link(alpha);
+ BOOST_CHECK(L == L2);
+
+ // verification
+ BOOST_CHECK(L.contains(static_cast<Simplex> (*L.get_address(Root_vertex_handle(10)))));
+ BOOST_CHECK(L.contains(static_cast<Simplex> (*L.get_address(Root_vertex_handle(11)))));
+ BOOST_CHECK(L.contains(static_cast<Simplex> (*L.get_address(Root_vertex_handle(13)))));
+ BOOST_CHECK(L.num_edges() == 2);
+ BOOST_CHECK(L.contains_edge(*L.get_address(Root_vertex_handle(10)), *L.get_address(Root_vertex_handle(13))));
+ BOOST_CHECK(L.contains_edge(*L.get_address(Root_vertex_handle(13)), *L.get_address(Root_vertex_handle(11))));
+ BOOST_CHECK(L.num_blockers() == 0);
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_complex_link4) {
+ Complex complex;
+
+ // Build the complexes
+ for (int i = 0; i < 20; i++) {
+ complex.add_vertex();
+ }
+ for (int i = 10; i < 15; i++) {
+ for (int j = i + 1; j < 15; j++)
+ complex.add_edge_without_blockers(Vertex_handle(i), Vertex_handle(j));
+ }
+ complex.add_blocker(Simplex(Vertex_handle(10), Vertex_handle(11), Vertex_handle(12), Vertex_handle(13)));
+ Simplex alpha(Vertex_handle(12), Vertex_handle(14));
+ Skeleton_blocker_link_complex L(complex, alpha);
+ // Complexes built
+
+ // verification
+ BOOST_CHECK(L.contains_vertex(*L.get_address(Root_vertex_handle(10))));
+ BOOST_CHECK(L.contains_vertex(*L.get_address(Root_vertex_handle(11))));
+ BOOST_CHECK(L.contains_vertex(*L.get_address(Root_vertex_handle(13))));
+ BOOST_CHECK(L.num_edges() == 3);
+ BOOST_CHECK(L.num_blockers() == 1);
+ Root_simplex_handle simplex;
+ simplex.add_vertex(Root_vertex_handle(10));
+ simplex.add_vertex(Root_vertex_handle(11));
+ simplex.add_vertex(Root_vertex_handle(13));
+ BOOST_CHECK(L.contains_blocker(*(L.get_simplex_address(simplex))));
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_complex_link5) {
+ Complex complex(0);
+ // Build the complexes
+ build_complete(4, complex);
+ complex.add_blocker(Simplex(Vertex_handle(0), Vertex_handle(1), Vertex_handle(2), Vertex_handle(3)));
+
+ Simplex alpha(Vertex_handle(0), Vertex_handle(1), Vertex_handle(2));
+ Skeleton_blocker_link_complex L(complex, alpha);
+ // Complexes built
+
+ // Print result
+ std::cout << "Complex: " << complex.to_string()<< std::endl << std::endl;
+ std::cout << "Link: " << L.to_string() << std::endl;
+
+ // verification
+ BOOST_CHECK(L.num_vertices() == 0);
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_complex_link6) {
+ Complex complex(0);
+ // Build the complexes
+ build_complete(4, complex);
+ complex.add_blocker(Simplex(Vertex_handle(0), Vertex_handle(1), Vertex_handle(2)));
+
+ Simplex alpha(Vertex_handle(0), Vertex_handle(1), Vertex_handle(2));
+
+ Skeleton_blocker_link_complex link_blocker_alpha;
+
+ build_link_of_blocker(complex, alpha, link_blocker_alpha);
+
+ // Print result
+ std::cout << "Complex: " << complex.to_string()<< std::endl << std::endl;
+ std::cout << "Link: " << link_blocker_alpha.to_string() << std::endl;
+
+ // verification
+ BOOST_CHECK(link_blocker_alpha.num_vertices() == 1);
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_complex_link7) {
+ Complex complex(0);
+ // Build the complexes
+ build_complete(6, complex);
+ complex.add_vertex();
+ complex.add_vertex();
+ for (int i = 3; i < 6; ++i) {
+ complex.add_edge_without_blockers(Vertex_handle(i), Vertex_handle(6));
+ complex.add_edge_without_blockers(Vertex_handle(i), Vertex_handle(7));
+ }
+ complex.add_edge_without_blockers(Vertex_handle(6), Vertex_handle(7));
+ complex.add_blocker(Simplex(Vertex_handle(0), Vertex_handle(1), Vertex_handle(2)));
+ complex.add_blocker(Simplex(Vertex_handle(3), Vertex_handle(4), Vertex_handle(5)));
+
+ Simplex alpha(Vertex_handle(3), Vertex_handle(4), Vertex_handle(5));
+
+ Skeleton_blocker_link_complex link_blocker_alpha;
+
+ build_link_of_blocker(complex, alpha, link_blocker_alpha);
+
+ //the result should be the edge {6,7} plus the blocker {0,1,2}
+
+ // Print result
+ std::cout << "Complex: " << complex.to_string()<< std::endl << std::endl;
+ std::cout << "Link: " << link_blocker_alpha.to_string() << std::endl;
+
+ Skeleton_blocker_link_complex link_blocker_alpha_cpy = link_blocker_alpha;
+
+ std::cout << "Link copy: " << link_blocker_alpha_cpy.to_string() << std::endl;
+
+ BOOST_CHECK(link_blocker_alpha.num_vertices() == link_blocker_alpha_cpy.num_vertices());
+ BOOST_CHECK(link_blocker_alpha.num_blockers() == link_blocker_alpha_cpy.num_blockers());
+ BOOST_CHECK(link_blocker_alpha.num_edges() == link_blocker_alpha_cpy.num_edges());
+ BOOST_CHECK((link_blocker_alpha.num_blockers() == link_blocker_alpha_cpy.num_blockers()));
+
+ // verification
+ BOOST_CHECK(link_blocker_alpha.num_vertices() == 5);
+ BOOST_CHECK(link_blocker_alpha.num_edges() == 4);
+ BOOST_CHECK(link_blocker_alpha.num_blockers() == 1);
+}
+
+template<typename SimplexHandle>
+void add_triangle_edges(int a, int b, int c, std::list<SimplexHandle>& simplices) {
+ typedef SimplexHandle Simplex;
+ typedef typename SimplexHandle::Vertex_handle Vertex_handle;
+
+ simplices.push_back(Simplex(Vertex_handle(a), Vertex_handle(b)));
+ simplices.push_back(Simplex(Vertex_handle(b), Vertex_handle(c)));
+ simplices.push_back(Simplex(Vertex_handle(c), Vertex_handle(a)));
+}
+
+template<typename SimplexHandle>
+void add_triangle(int a, int b, int c, std::list<SimplexHandle>& simplices) {
+ typedef SimplexHandle Simplex;
+ typedef typename SimplexHandle::Vertex_handle Vertex_handle;
+ simplices.push_back(Simplex(Vertex_handle(a), Vertex_handle(b), Vertex_handle(c)));
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_complex_constructor) {
+ std::list <Simplex> simplices;
+
+ 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(3)));
+ simplices.push_back(Simplex(Vertex_handle(4)));
+ simplices.push_back(Simplex(Vertex_handle(5)));
+
+ simplices.push_back(Simplex(Vertex_handle(3), Vertex_handle(5)));
+
+ add_triangle_edges(0, 1, 5, simplices);
+ add_triangle_edges(1, 2, 3, simplices);
+ add_triangle_edges(2, 3, 4, simplices);
+ add_triangle_edges(1, 3, 4, simplices);
+ add_triangle_edges(1, 2, 4, simplices);
+
+ add_triangle(0, 1, 5, simplices);
+ add_triangle(1, 2, 3, simplices);
+ add_triangle(1, 3, 4, simplices);
+ add_triangle(1, 2, 4, simplices);
+ add_triangle(2, 3, 4, simplices);
+
+ Complex complex(simplices.begin(), simplices.end());
+
+ std::cout << "Constructor 1:\n" << complex.to_string();
+
+ BOOST_CHECK(complex.num_vertices() == 6);
+ BOOST_CHECK(complex.num_edges() == 10);
+ BOOST_CHECK(complex.num_blockers() == 2);
+}
+
+std::list<Simplex> subfaces(Simplex top_face) {
+ std::list<Simplex> res;
+ if (top_face.dimension() == -1) return res;
+ if (top_face.dimension() == 0) {
+ res.push_back(top_face);
+ return res;
+ } else {
+ Vertex_handle first_vertex = top_face.first_vertex();
+ top_face.remove_vertex(first_vertex);
+ res = subfaces(top_face);
+ std::list<Simplex> copy = res;
+ for (auto& simplex : copy) {
+ simplex.add_vertex(first_vertex);
+ }
+ res.push_back(Simplex(first_vertex));
+ res.splice(res.end(), copy);
+ return res;
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_complex_constructor2) {
+ Simplex simplex;
+ for (int i = 0; i < 5; ++i)
+ simplex.add_vertex(static_cast<Vertex_handle> (i));
+
+ std::list <Simplex> simplices(subfaces(simplex));
+ simplices.remove(simplex);
+
+ Complex complex(simplices.begin(), simplices.end());
+
+ std::cout << "Constructor 2:\n" << complex.to_string();
+
+ for (auto b : complex.const_blocker_range()) {
+ std::cout << "b:" << b << std::endl;
+ }
+
+ BOOST_CHECK(complex.num_vertices() == 5);
+ BOOST_CHECK(complex.num_edges() == 10);
+ BOOST_CHECK(complex.num_blockers() == 1);
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_complex_constructor3) {
+ typedef Vertex_handle Vh;
+ typedef Simplex Sh;
+ std::vector<Simplex> simplices;
+ auto subf(subfaces(Sh(Vh(0), Vh(1), Vh(2))));
+ subf.pop_back(); //remove max face -> now a blocker 012
+ simplices.insert(simplices.begin(), subf.begin(), subf.end());
+
+ Complex complex(simplices.begin(), simplices.end());
+
+ std::cout << "Constructor 3:\n" << complex.to_string();
+
+ BOOST_CHECK(complex.num_blockers() == 1);
+ Sh expected_blocker(Vh(0), Vh(1), Vh(2));
+ for (auto b : complex.const_blocker_range())
+ BOOST_CHECK(*b == expected_blocker);
+
+
+ BOOST_CHECK(complex.num_vertices() == 3);
+ BOOST_CHECK(complex.num_blockers() == 1);
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_complex_constructor4) {
+ typedef Vertex_handle Vh;
+ typedef Simplex Sh;
+ std::vector<Simplex> simplices;
+ auto subf(subfaces(Sh(Vh(0), Vh(1), Vh(2), Vh(3))));
+ simplices.insert(simplices.begin(), subf.begin(), subf.end());
+
+ simplices.push_back(Sh(Vh(4)));
+ simplices.push_back(Sh(Vh(4), Vh(1)));
+ simplices.push_back(Sh(Vh(4), Vh(0)));
+
+ Complex complex(simplices.begin(), simplices.end());
+
+ std::cout << "Constructor 4:\n" << complex.to_string();
+ BOOST_CHECK(complex.num_blockers() == 1);
+ Sh expected_blocker(Vh(0), Vh(1), Vh(4));
+ for (auto b : complex.const_blocker_range())
+ BOOST_CHECK(*b == expected_blocker);
+
+ BOOST_CHECK(complex.num_vertices() == 5);
+ BOOST_CHECK(complex.num_blockers() == 1);
+ BOOST_CHECK(complex.num_edges() == 8);
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_complex_constructor5) {
+ typedef Vertex_handle Vh;
+ typedef Simplex Sh;
+ std::vector<Simplex> simplices;
+ auto subf(subfaces(Sh(Vh(0), Vh(1), Vh(2))));
+ simplices.insert(simplices.begin(), subf.begin(), subf.end());
+
+ simplices.push_back(Sh(Vh(3)));
+ simplices.push_back(Sh(Vh(3), Vh(1)));
+ simplices.push_back(Sh(Vh(3), Vh(2)));
+ simplices.push_back(Sh(Vh(4)));
+ simplices.push_back(Sh(Vh(4), Vh(1)));
+ simplices.push_back(Sh(Vh(4), Vh(0)));
+ simplices.push_back(Sh(Vh(5)));
+ simplices.push_back(Sh(Vh(5), Vh(2)));
+ simplices.push_back(Sh(Vh(5), Vh(0)));
+
+ Complex complex(simplices.begin(), simplices.end());
+
+ std::cout << "Constructor 5:\n" << complex.to_string();
+
+ BOOST_CHECK(complex.num_vertices() == 6);
+ BOOST_CHECK(complex.num_blockers() == 3);
+ BOOST_CHECK(complex.num_edges() == 9);
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_complex_constructor6) {
+ typedef Vertex_handle Vh;
+ typedef Simplex Sh;
+ std::vector<Simplex> simplices;
+ auto subf(subfaces(Sh(Vh(0), Vh(1), Vh(2), Vh(3))));
+ for (auto s : subf) {
+ Sh s1(Vh(0), Vh(1), Vh(2), Vh(3));
+ Sh s2(Vh(1), Vh(2), Vh(3));
+ if (s != s1 && s != s2) simplices.push_back(s);
+ }
+
+ Complex complex(simplices.begin(), simplices.end());
+
+ std::cout << "Constructor 6:\n" << complex.to_string();
+
+ BOOST_CHECK(complex.num_vertices() == 4);
+ BOOST_CHECK(complex.num_blockers() == 1);
+ BOOST_CHECK(complex.num_edges() == 6);
+ Sh expected_blocker(Vh(1), Vh(2), Vh(3));
+ for (auto b : complex.const_blocker_range())
+ BOOST_CHECK(*b == expected_blocker);
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_complex_constructor7) {
+ typedef Vertex_handle Vh;
+ typedef Simplex Sh;
+ std::vector<Simplex> simplices;
+ simplices.push_back(Sh(Vh(0), Vh(1), Vh(2)));
+ simplices.push_back(Sh(Vh(1), Vh(2), Vh(3)));
+ simplices.push_back(Sh(Vh(3), Vh(0), Vh(2)));
+ simplices.push_back(Sh(Vh(3), Vh(0), Vh(1)));
+
+ //get complex from top faces
+ Complex complex(Gudhi::skeleton_blocker::make_complex_from_top_faces<Complex>(simplices.begin(), simplices.end()));
+
+ std::cout << "Constructor 7:\n" << complex.to_string();
+
+ BOOST_CHECK(complex.num_vertices() == 4);
+ BOOST_CHECK(complex.num_blockers() == 1);
+ BOOST_CHECK(complex.num_edges() == 6);
+ Sh expected_blocker(Vh(0), Vh(1), Vh(2), Vh(3));
+ for (auto b : complex.const_blocker_range())
+ BOOST_CHECK(*b == expected_blocker);
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_complex_constructor8) {
+ typedef Vertex_handle Vh;
+ typedef Simplex Sh;
+ std::vector<Simplex> simplices;
+ simplices.push_back(Sh(Vh(0), Vh(1)));
+ simplices.push_back(Sh(Vh(2), Vh(1)));
+ simplices.push_back(Sh(Vh(0), Vh(2)));
+ simplices.push_back(Sh(Vh(3), Vh(1)));
+ simplices.push_back(Sh(Vh(2), Vh(3)));
+
+ //get complex from top faces
+ Complex complex(Gudhi::skeleton_blocker::make_complex_from_top_faces<Complex>(simplices.begin(), simplices.end()));
+
+ std::cout << "Constructor 8:\n" << complex.to_string();
+
+ BOOST_CHECK(complex.num_vertices() == 4);
+ BOOST_CHECK(complex.num_blockers() == 2);
+ BOOST_CHECK(complex.num_edges() == 5);
+}
diff --git a/src/Skeleton_blocker/test/test_skeleton_blocker_geometric_complex.cpp b/src/Skeleton_blocker/test/test_skeleton_blocker_geometric_complex.cpp
new file mode 100644
index 00000000..d035b2c3
--- /dev/null
+++ b/src/Skeleton_blocker/test/test_skeleton_blocker_geometric_complex.cpp
@@ -0,0 +1,125 @@
+/* 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/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+#include <fstream>
+#include <sstream>
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE "skeleton_blocker_geometric_complex"
+#include <boost/test/unit_test.hpp>
+#include <boost/mpl/list.hpp>
+
+#include <gudhi/Skeleton_blocker.h>
+
+struct Geometry_trait {
+ typedef std::vector<double> Point;
+};
+
+typedef Geometry_trait::Point Point;
+typedef Gudhi::skeleton_blocker::Skeleton_blocker_simple_geometric_traits<Geometry_trait> Complex_geometric_traits;
+typedef Gudhi::skeleton_blocker::Skeleton_blocker_geometric_complex< Complex_geometric_traits > Complex;
+typedef Complex::Vertex_handle Vertex_handle;
+typedef Complex_geometric_traits::Root_vertex_handle Root_vertex_handle;
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_off_reader_writer) {
+ Complex complex;
+ Gudhi::skeleton_blocker::Skeleton_blocker_off_reader<Complex> off_reader("test2.off", complex);
+ BOOST_CHECK(off_reader.is_valid());
+
+ std::cout << "complex has " <<
+ complex.num_vertices() << " vertices, " <<
+ complex.num_blockers() << " blockers, " <<
+ complex.num_edges() << " edges and " <<
+ complex.num_triangles() << " triangles.";
+
+ BOOST_CHECK(complex.num_vertices() == 7);
+ BOOST_CHECK(complex.num_edges() == 12);
+ BOOST_CHECK(complex.num_triangles() == 6);
+
+ Gudhi::skeleton_blocker::Skeleton_blocker_off_writer<Complex> off_writer("tmp.off", complex);
+ Complex same;
+ Gudhi::skeleton_blocker::Skeleton_blocker_off_reader<Complex> off_reader2("tmp.off", same);
+
+ std::cout << "\ncomplex:" << complex.to_string() << std::endl;
+ std::cout << "\nsame:" << same.to_string() << std::endl;
+
+ BOOST_CHECK(complex == same);
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_abstract_link) {
+ Complex complex;
+ Gudhi::skeleton_blocker::Skeleton_blocker_off_reader<Complex> off_reader("test2.off", complex);
+ BOOST_CHECK(off_reader.is_valid());
+
+ std::cout << "complex has " <<
+ complex.num_vertices() << " vertices, " <<
+ complex.num_blockers() << " blockers, " <<
+ complex.num_edges() << " edges and " <<
+ complex.num_triangles() << " triangles.";
+
+ BOOST_CHECK(complex.num_vertices() == 7);
+ BOOST_CHECK(complex.num_edges() == 12);
+ BOOST_CHECK(complex.num_triangles() == 6);
+
+ auto link_0 = complex.abstract_link(Vertex_handle(0));
+
+ std::cout << "\n link(0):" << link_0.to_string() << std::endl;
+
+ BOOST_CHECK(link_0.num_vertices() == 2);
+ BOOST_CHECK(link_0.num_edges() == 1);
+ BOOST_CHECK(link_0.num_blockers() == 0);
+
+ // Check the 2 link vertices
+ auto vertex_handle = link_0.vertex_range().begin();
+ BOOST_CHECK(link_0[*vertex_handle].get_id() == Root_vertex_handle(1));
+ vertex_handle++;
+ BOOST_CHECK(link_0[*(vertex_handle)].get_id() == Root_vertex_handle(4));
+
+ // Check the lonely link edge
+ auto edge_handle = link_0.edge_range().begin();
+ BOOST_CHECK(link_0[*edge_handle].first() == Root_vertex_handle(1));
+ BOOST_CHECK(link_0[*(edge_handle)].second() == Root_vertex_handle(4));
+
+ auto link_geometric_0 = complex.link(Vertex_handle(0));
+ std::cout << "\n link_geometric(0):" << link_geometric_0.to_string() << std::endl;
+
+ BOOST_CHECK(link_0 == link_geometric_0);
+
+ auto print_point = [&](Vertex_handle v) {
+ for (auto x : link_geometric_0.point(v)) std::cout << x << " ";
+ std::cout << std::endl;
+ };
+
+ std::for_each(link_geometric_0.vertex_range().begin(), link_geometric_0.vertex_range().end(), print_point);
+
+ // Check the 2 link vertices
+ vertex_handle = link_geometric_0.vertex_range().begin();
+ std::vector<double> point_1 = {0,2,0};
+ std::vector<double> point_4 = {-1,1,0};
+ BOOST_CHECK(link_geometric_0.point(*vertex_handle) == point_1);
+ vertex_handle++;
+ BOOST_CHECK(link_geometric_0.point(*vertex_handle) == point_4);
+
+}
diff --git a/src/Skeleton_blocker/test/test_skeleton_blocker_simplifiable.cpp b/src/Skeleton_blocker/test/test_skeleton_blocker_simplifiable.cpp
new file mode 100644
index 00000000..360b91db
--- /dev/null
+++ b/src/Skeleton_blocker/test/test_skeleton_blocker_simplifiable.cpp
@@ -0,0 +1,360 @@
+/* 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/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+#include <fstream>
+#include <sstream>
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE "skeleton_blocker_simplifiable"
+#include <boost/test/unit_test.hpp>
+#include <boost/mpl/list.hpp>
+
+#include <gudhi/Skeleton_blocker.h>
+
+template<typename ComplexType> class Skeleton_blocker_sub_complex;
+typedef Gudhi::skeleton_blocker::Skeleton_blocker_simple_traits Traits;
+typedef Gudhi::skeleton_blocker::Skeleton_blocker_complex<Traits> Complex;
+typedef Complex::Vertex_handle Vertex_handle;
+typedef Complex::Root_vertex_handle Root_vertex_handle;
+typedef Gudhi::skeleton_blocker::Skeleton_blocker_simplex<Vertex_handle> Simplex;
+
+
+void build_complete(int n, Complex& complex) {
+ complex.clear();
+ 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));
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_simplifiable_contraction1) {
+ enum { a, b, x, y, z, n };
+ Complex complex(n);
+ build_complete(n, complex);
+ complex.remove_edge(static_cast<Vertex_handle> (b), static_cast<Vertex_handle> (z));
+ complex.add_blocker(Simplex(static_cast<Vertex_handle> (a), static_cast<Vertex_handle> (x),
+ static_cast<Vertex_handle> (y)));
+ complex.add_blocker(Simplex(static_cast<Vertex_handle> (b), static_cast<Vertex_handle> (x),
+ static_cast<Vertex_handle> (y)));
+
+ // Print result
+ std::cout << "complex before complex" << complex.to_string() << std::endl;
+
+ std::cout << std::endl << std::endl;
+ complex.contract_edge(static_cast<Vertex_handle> (a), static_cast<Vertex_handle> (b));
+ // Print result
+ std::cout << "ContractEdge(0,1)\n";
+ PRINT(complex.to_string());
+
+ // verification
+ for (int i = 0; i < 5; i++)
+ if (i != 1) BOOST_CHECK(complex.contains(Simplex(static_cast<Vertex_handle> (i))));
+ BOOST_CHECK(!complex.contains_edge(static_cast<Vertex_handle> (a), static_cast<Vertex_handle> (b)));
+
+ BOOST_CHECK(complex.contains_blocker(Simplex(*complex.get_address(Root_vertex_handle(a)),
+ *complex.get_address(Root_vertex_handle(x)),
+ *complex.get_address(Root_vertex_handle(y)))));
+
+ BOOST_CHECK(complex.num_edges() == 6);
+ BOOST_CHECK(complex.num_blockers() == 1);
+ Simplex sigma;
+ sigma.add_vertex(static_cast<Vertex_handle> (a));
+ sigma.add_vertex(static_cast<Vertex_handle> (x));
+ sigma.add_vertex(static_cast<Vertex_handle> (y));
+ sigma.add_vertex(static_cast<Vertex_handle> (z));
+ BOOST_CHECK(!(complex.contains(sigma)));
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_simplifiable_contraction2) {
+ enum { a, b, x, y, z, n };
+ Complex complex(n);
+ build_complete(n, complex);
+ complex.remove_edge(static_cast<Vertex_handle> (b), static_cast<Vertex_handle> (x));
+ Simplex blocker;
+ blocker.add_vertex(static_cast<Vertex_handle> (a));
+ blocker.add_vertex(static_cast<Vertex_handle> (y));
+ blocker.add_vertex(static_cast<Vertex_handle> (z));
+
+ complex.add_blocker(blocker);
+
+ // Print result
+ std::cout << "complex complex" << complex.to_string();
+ std::cout << std::endl << std::endl;
+ complex.contract_edge(static_cast<Vertex_handle> (a), static_cast<Vertex_handle> (b));
+
+ std::cout << "complex.ContractEdge(a,b)" << complex.to_string();
+
+ std::cout << std::endl << std::endl;
+
+ // there should be one blocker (a,c,d,e) in the complex
+ BOOST_CHECK(complex.contains_blocker(Simplex(static_cast<Vertex_handle> (a), static_cast<Vertex_handle> (x),
+ static_cast<Vertex_handle> (y), static_cast<Vertex_handle> (z))));
+ BOOST_CHECK(complex.num_blockers() == 1);
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_simplifiable_link_condition1) {
+ Complex complex(0);
+ // Build the complexes
+ build_complete(4, complex);
+ complex.add_blocker(Simplex(static_cast<Vertex_handle> (0), static_cast<Vertex_handle> (1), static_cast<Vertex_handle> (2)));
+
+ // Print result
+ std::cout << "complex complex" << complex.to_string();
+ std::cout << std::endl << std::endl;
+
+ BOOST_CHECK(complex.link_condition(Vertex_handle(1), Vertex_handle(2), true));
+
+ BOOST_CHECK(!complex.link_condition(Vertex_handle(1), Vertex_handle(2), false));
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_simplifiable_collapse0) {
+ Complex complex(5);
+ build_complete(4, complex);
+ complex.add_vertex();
+ complex.add_edge_without_blockers(static_cast<Vertex_handle> (2), static_cast<Vertex_handle> (4));
+ complex.add_edge_without_blockers(static_cast<Vertex_handle> (3), static_cast<Vertex_handle> (4));
+ // Print result
+ std::cout << "initial complex :\n" << complex.to_string();
+ std::cout << std::endl << std::endl;
+
+ Simplex simplex_123(static_cast<Vertex_handle> (1), static_cast<Vertex_handle> (2), static_cast<Vertex_handle> (3));
+ complex.remove_star(simplex_123);
+ std::cout << "complex.remove_star(1,2,3):\n" << complex.to_string();
+ std::cout << std::endl << std::endl;
+
+ // verification
+ BOOST_CHECK(complex.contains_blocker(simplex_123));
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_simplifiable_collapse1) {
+ Complex complex(5);
+ build_complete(4, complex);
+ complex.add_blocker(Simplex(Vertex_handle(0), Vertex_handle(1), Vertex_handle(2), Vertex_handle(3)));
+ // Print result
+ std::cout << "initial complex :\n" << complex.to_string();
+ std::cout << std::endl << std::endl;
+
+ Simplex simplex_123(Vertex_handle(1), Vertex_handle(2), Vertex_handle(3));
+ complex.remove_star(simplex_123);
+ std::cout << "complex.remove_star(1,2,3):\n" << complex.to_string();
+ std::cout << std::endl << std::endl;
+
+ // verification
+ BOOST_CHECK(complex.contains_blocker(simplex_123));
+ BOOST_CHECK(complex.num_blockers() == 1);
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_simplifiable_collapse2) {
+ Complex complex(5);
+ build_complete(4, complex);
+ complex.add_vertex();
+ complex.add_edge_without_blockers(Vertex_handle(1), Vertex_handle(4));
+ complex.add_edge_without_blockers(Vertex_handle(2), Vertex_handle(4));
+ complex.add_edge_without_blockers(Vertex_handle(3), Vertex_handle(4));
+ complex.add_blocker(Simplex(Vertex_handle(1), Vertex_handle(2), Vertex_handle(3), Vertex_handle(4)));
+ // Print result
+ std::cout << "initial complex :\n" << complex.to_string();
+ std::cout << std::endl << std::endl;
+
+ Simplex sigma(Vertex_handle(1), Vertex_handle(2), Vertex_handle(3));
+ complex.remove_star(sigma);
+ std::cout << "complex.remove_star(1,2,3):\n" << complex.to_string();
+ std::cout << std::endl << std::endl;
+
+ // verification
+ BOOST_CHECK(!complex.contains_blocker(Simplex(Vertex_handle(1), Vertex_handle(2),
+ Vertex_handle(3), Vertex_handle(4))));
+ BOOST_CHECK(complex.contains_blocker(sigma));
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_simplifiable_collapse3) {
+ Complex complex(5);
+ build_complete(4, complex);
+ complex.add_vertex();
+ complex.add_edge_without_blockers(Vertex_handle(1), Vertex_handle(4));
+ complex.add_edge_without_blockers(Vertex_handle(2), Vertex_handle(4));
+ complex.add_edge_without_blockers(Vertex_handle(3), Vertex_handle(4));
+ complex.add_blocker(Simplex(Vertex_handle(1), Vertex_handle(2), Vertex_handle(3), Vertex_handle(4)));
+ // Print result
+ std::cout << "initial complex:\n" << complex.to_string();
+ std::cout << std::endl << std::endl;
+
+ complex.remove_star(static_cast<Vertex_handle> (2));
+ std::cout << "complex after remove star of 2:\n" << complex.to_string();
+
+ BOOST_CHECK(complex.contains_blocker(Simplex(Vertex_handle(1), Vertex_handle(3), Vertex_handle(4))));
+ BOOST_CHECK(!complex.contains_blocker(Simplex(Vertex_handle(1), Vertex_handle(2),
+ Vertex_handle(3), Vertex_handle(4))));
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_simplifiable_add_simplex) {
+ Complex complex(4);
+ build_complete(4, complex);
+ complex.add_blocker(Simplex(Vertex_handle(0), Vertex_handle(1), Vertex_handle(3)));
+ std::cout << "initial complex:\n" << complex.to_string();
+ std::cout << std::endl << std::endl;
+
+ complex.add_simplex(Simplex(Vertex_handle(0), Vertex_handle(1), Vertex_handle(3)));
+ std::cout << "complex after add_simplex:\n" << complex.to_string();
+ BOOST_CHECK(complex.num_blockers() == 1);
+ BOOST_CHECK(complex.contains_blocker(Simplex(Vertex_handle(0), Vertex_handle(1),
+ Vertex_handle(2), Vertex_handle(3))));
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_simplifiable_add_simplex2) {
+ Complex complex;
+ build_complete(4, complex);
+ // Print result
+ std::cout << "initial complex:\n" << complex.to_string();
+ std::cout << std::endl << std::endl;
+
+ Complex copy(complex.num_vertices());
+
+ std::vector<Simplex> simplices(complex.complex_simplex_range().begin(), complex.complex_simplex_range().end());
+ sort(simplices.begin(), simplices.end(), [&](const Simplex& s1, const Simplex & s2) {
+ return s1.dimension() < s2.dimension();
+ });
+ for (const auto & simplex : simplices) {
+ if (!copy.contains(simplex) && simplex.dimension() == 1)
+ copy.add_edge_without_blockers(simplex.first_vertex(), simplex.last_vertex());
+ if (!copy.contains(simplex) && simplex.dimension() > 1)
+ copy.add_simplex(simplex);
+ }
+
+ std::cout << "complex after add_simplex:\n" << copy.to_string();
+
+ BOOST_CHECK(complex.num_blockers() == copy.num_blockers());
+ BOOST_CHECK(complex.num_edges() == copy.num_edges());
+ BOOST_CHECK(complex.num_vertices() == copy.num_vertices());
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_simplifiable_add_simplex3) {
+ Complex complex(5);
+ build_complete(5, complex);
+ complex.remove_edge(Vertex_handle(3), Vertex_handle(4));
+ Simplex sigma(Vertex_handle(0), Vertex_handle(1), Vertex_handle(2));
+ complex.add_blocker(sigma);
+ // Print result
+ std::cout << "initial complex:\n" << complex.to_string();
+ std::cout << std::endl << std::endl;
+ complex.add_simplex(sigma);
+ //should create two blockers 0123 and 0124
+ std::cout << "complex after adding simplex 012:\n" << complex.to_string();
+ BOOST_CHECK(complex.num_blockers() == 2);
+ BOOST_CHECK(complex.contains_blocker(Simplex(Vertex_handle(0), Vertex_handle(1),
+ Vertex_handle(2), Vertex_handle(3))));
+ BOOST_CHECK(complex.contains_blocker(Simplex(Vertex_handle(0), Vertex_handle(1),
+ Vertex_handle(2), Vertex_handle(4))));
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_simplifiable_add_simplex4) {
+ int n = 6;
+ Complex complex(n);
+
+ // add all simplex 0..n without i
+ for (int i = 0; i < n; i++) {
+ Simplex s;
+ for (int k = 0; k < n; k++)
+ s.add_vertex(Vertex_handle(k));
+ s.remove_vertex(Vertex_handle(i));
+ complex.add_simplex(s);
+
+ //at step i there is only blocker 0..i
+ BOOST_CHECK(!(i < 2 && complex.num_blockers() > 0));
+ if (i >= 2 && complex.num_blockers() != 1) {
+ Simplex b;
+ for (int k = 0; k < i; k++)
+ b.add_vertex(Vertex_handle(i));
+ BOOST_CHECK(complex.contains_blocker(b));
+ }
+ }
+ Simplex s;
+ for (int k = 0; k < n; k++)
+ s.add_vertex(Vertex_handle(k));
+ BOOST_CHECK(complex.num_blockers() == 1);
+ BOOST_CHECK(complex.contains_blocker(s));
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_simplifiable_add_edge) {
+ Complex complex(4);
+ for (unsigned i = 0u; i < 4; i++)
+ complex.add_edge(Vertex_handle(i), Vertex_handle((i + 1) % 4));
+
+ // Print result
+ std::cout << "initial complex:\n" << complex.to_string();
+ std::cout << std::endl << std::endl;
+ complex.add_edge(Vertex_handle(1), Vertex_handle(3));
+ //should create two blockers 013 and 012
+ std::cout << "complex after adding edge 13:\n" << complex.to_string();
+ BOOST_CHECK(complex.num_blockers() == 2);
+ BOOST_CHECK(complex.contains_blocker(Simplex(Vertex_handle(0), Vertex_handle(1), Vertex_handle(3))));
+ BOOST_CHECK(complex.contains_blocker(Simplex(Vertex_handle(1), Vertex_handle(2), Vertex_handle(3))));
+}
+
+BOOST_AUTO_TEST_CASE(test_skeleton_blocker_simplifiable_remove_popable_blockers) {
+ Complex complex;
+ build_complete(4, complex);
+ complex.add_vertex();
+ complex.add_edge_without_blockers(Vertex_handle(3), Vertex_handle(4));
+ complex.add_edge_without_blockers(Vertex_handle(2), Vertex_handle(4));
+ Simplex sigma1 = Simplex(Vertex_handle(1), Vertex_handle(2), Vertex_handle(3));
+ Simplex sigma2 = Simplex(Vertex_handle(2), Vertex_handle(3), Vertex_handle(4));
+
+ complex.add_blocker(sigma1);
+ complex.add_blocker(sigma2);
+ std::cout << "complex complex" << complex.to_string();
+ std::cout << std::endl << std::endl;
+ std::cout << "complex.RemovePopableBlockers();" << std::endl;
+ complex.remove_popable_blockers();
+ std::cout << "complex complex" << complex.to_string();
+ std::cout << std::endl << std::endl;
+
+ BOOST_CHECK(complex.num_blockers() == 1);
+
+ // test 2
+ complex.clear();
+ build_complete(4, complex);
+ complex.add_vertex();
+ complex.add_vertex();
+ complex.add_edge_without_blockers(Vertex_handle(3), Vertex_handle(4));
+ complex.add_edge_without_blockers(Vertex_handle(2), Vertex_handle(4));
+ complex.add_edge_without_blockers(Vertex_handle(2), Vertex_handle(5));
+ complex.add_edge_without_blockers(Vertex_handle(3), Vertex_handle(5));
+ complex.add_edge_without_blockers(Vertex_handle(4), Vertex_handle(5));
+ sigma1 = Simplex(Vertex_handle(1), Vertex_handle(2), Vertex_handle(3));
+ sigma2 = Simplex(Vertex_handle(2), Vertex_handle(3), Vertex_handle(4));
+
+ complex.add_blocker(sigma1);
+ complex.add_blocker(sigma2);
+ std::cout << "complex complex" << complex.to_string();
+ std::cout << std::endl << std::endl;
+ std::cout << "complex.RemovePopableBlockers();" << std::endl;
+ complex.remove_popable_blockers();
+ std::cout << "complex complex" << complex.to_string();
+
+ std::cout << std::endl << std::endl;
+ BOOST_CHECK(complex.num_blockers() == 0);
+}
diff --git a/src/Spatial_searching/doc/Intro_spatial_searching.h b/src/Spatial_searching/doc/Intro_spatial_searching.h
new file mode 100644
index 00000000..23705378
--- /dev/null
+++ b/src/Spatial_searching/doc/Intro_spatial_searching.h
@@ -0,0 +1,62 @@
+/* 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 DOC_SPATIAL_SEARCHING_INTRO_SPATIAL_SEARCHING_H_
+#define DOC_SPATIAL_SEARCHING_INTRO_SPATIAL_SEARCHING_H_
+
+// needs namespaces for Doxygen to link on classes
+namespace Gudhi {
+namespace spatial_searching {
+
+/** \defgroup spatial_searching Spatial_searching
+ *
+ * \author Cl&eacute;ment Jamin
+ *
+ * @{
+ *
+ * \section introduction Introduction
+ *
+ * This Gudhi component is a wrapper around
+ * <a target="_blank" href="http://doc.cgal.org/latest/Spatial_searching/index.html">CGAL dD spatial searching algorithms</a>.
+ * It provides a simplified API to perform (approximate) neighbor searches. Contrary to CGAL default behavior, the tree
+ * does not store the points themselves, but stores indices.
+ *
+ * For more details about the data structure or the algorithms, or for more advanced usages, reading
+ * <a target="_blank" href="http://doc.cgal.org/latest/Spatial_searching/index.html">CGAL documentation</a>
+ * is highly recommended.
+ *
+ * \section spatial_searching_examples Example
+ *
+ * This example generates 500 random points, then performs queries for nearest and farthest points using different methods.
+ *
+ * \include Spatial_searching/example_spatial_searching.cpp
+ *
+ * \copyright GNU General Public License v3.
+ * \verbatim Contact: gudhi-users@lists.gforge.inria.fr \endverbatim
+ */
+/** @} */ // end defgroup spatial_searching
+
+} // namespace spatial_searching
+
+} // namespace Gudhi
+
+#endif // DOC_SPATIAL_SEARCHING_INTRO_SPATIAL_SEARCHING_H_
diff --git a/src/Spatial_searching/example/CMakeLists.txt b/src/Spatial_searching/example/CMakeLists.txt
new file mode 100644
index 00000000..e73b201c
--- /dev/null
+++ b/src/Spatial_searching/example/CMakeLists.txt
@@ -0,0 +1,13 @@
+cmake_minimum_required(VERSION 2.6)
+project(Spatial_searching_examples)
+
+if(CGAL_FOUND)
+ if (NOT CGAL_VERSION VERSION_LESS 4.9.0)
+ if (EIGEN3_FOUND)
+ add_executable( Spatial_searching_example_spatial_searching example_spatial_searching.cpp )
+ target_link_libraries(Spatial_searching_example_spatial_searching ${CGAL_LIBRARY})
+ add_test(Spatial_searching_example_spatial_searching
+ ${CMAKE_CURRENT_BINARY_DIR}/Spatial_searching_example_spatial_searching)
+ endif()
+ endif()
+endif()
diff --git a/src/Spatial_searching/example/example_spatial_searching.cpp b/src/Spatial_searching/example/example_spatial_searching.cpp
new file mode 100644
index 00000000..14b324ae
--- /dev/null
+++ b/src/Spatial_searching/example/example_spatial_searching.cpp
@@ -0,0 +1,52 @@
+#include <gudhi/Kd_tree_search.h>
+
+#include <CGAL/Epick_d.h>
+#include <CGAL/Random.h>
+
+#include <vector>
+
+namespace gss = Gudhi::spatial_searching;
+
+int main(void) {
+ typedef CGAL::Epick_d<CGAL::Dimension_tag<4> > K;
+ typedef typename K::Point_d Point;
+ typedef std::vector<Point> Points;
+
+ typedef gss::Kd_tree_search<K, Points> Points_ds;
+
+ CGAL::Random rd;
+
+ Points points;
+ for (int i = 0; i < 500; ++i)
+ points.push_back(Point(rd.get_double(-1., 1), rd.get_double(-1., 1), rd.get_double(-1., 1), rd.get_double(-1., 1)));
+
+ Points_ds points_ds(points);
+
+ // 10-nearest neighbor query
+ std::cout << "10 nearest neighbors from points[20]:\n";
+ auto knn_range = points_ds.query_k_nearest_neighbors(points[20], 10, true);
+ for (auto const& nghb : knn_range)
+ std::cout << nghb.first << " (sq. dist. = " << nghb.second << ")\n";
+
+ // Incremental nearest neighbor query
+ std::cout << "Incremental nearest neighbors:\n";
+ auto inn_range = points_ds.query_incremental_nearest_neighbors(points[45]);
+ // Get the neighbors in distance order until we hit the first point
+ for (auto ins_iterator = inn_range.begin(); ins_iterator->first != 0; ++ins_iterator)
+ std::cout << ins_iterator->first << " (sq. dist. = " << ins_iterator->second << ")\n";
+
+ // 10-farthest neighbor query
+ std::cout << "10 farthest neighbors from points[20]:\n";
+ auto kfn_range = points_ds.query_k_farthest_neighbors(points[20], 10, true);
+ for (auto const& nghb : kfn_range)
+ std::cout << nghb.first << " (sq. dist. = " << nghb.second << ")\n";
+
+ // Incremental farthest neighbor query
+ std::cout << "Incremental farthest neighbors:\n";
+ auto ifn_range = points_ds.query_incremental_farthest_neighbors(points[45]);
+ // Get the neighbors in distance reverse order until we hit the first point
+ for (auto ifs_iterator = ifn_range.begin(); ifs_iterator->first != 0; ++ifs_iterator)
+ std::cout << ifs_iterator->first << " (sq. dist. = " << ifs_iterator->second << ")\n";
+
+ return 0;
+}
diff --git a/src/Spatial_searching/include/gudhi/Kd_tree_search.h b/src/Spatial_searching/include/gudhi/Kd_tree_search.h
new file mode 100644
index 00000000..6728d56e
--- /dev/null
+++ b/src/Spatial_searching/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/src/Spatial_searching/test/CMakeLists.txt b/src/Spatial_searching/test/CMakeLists.txt
new file mode 100644
index 00000000..7f443b79
--- /dev/null
+++ b/src/Spatial_searching/test/CMakeLists.txt
@@ -0,0 +1,25 @@
+cmake_minimum_required(VERSION 2.6)
+project(Spatial_searching_tests)
+
+if (GCOVR_PATH)
+ # for gcovr to make coverage reports - Corbera Jenkins plugin
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
+endif()
+if (GPROF_PATH)
+ # for gprof to make coverage reports - Jenkins
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg")
+endif()
+
+if(CGAL_FOUND)
+ if (NOT CGAL_VERSION VERSION_LESS 4.9.0)
+ if (EIGEN3_FOUND)
+ add_executable( Spatial_searching_test_Kd_tree_search test_Kd_tree_search.cpp )
+ target_link_libraries(Spatial_searching_test_Kd_tree_search
+ ${CGAL_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+
+ add_test(Spatial_searching_test_Kd_tree_search ${CMAKE_CURRENT_BINARY_DIR}/Spatial_searching_test_Kd_tree_search
+ # XML format for Jenkins xUnit plugin
+ --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/Spatial_searching_UT.xml --log_level=test_suite --report_level=no)
+ endif()
+ endif ()
+endif()
diff --git a/src/Spatial_searching/test/test_Kd_tree_search.cpp b/src/Spatial_searching/test/test_Kd_tree_search.cpp
new file mode 100644
index 00000000..0ef22023
--- /dev/null
+++ b/src/Spatial_searching/test/test_Kd_tree_search.cpp
@@ -0,0 +1,112 @@
+/* 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/>.
+ */
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE Spatial_searching - test Kd_tree_search
+#include <boost/test/unit_test.hpp>
+
+#include <gudhi/Kd_tree_search.h>
+
+#include <CGAL/Epick_d.h>
+#include <CGAL/Random.h>
+
+#include <vector>
+
+BOOST_AUTO_TEST_CASE(test_Kd_tree_search) {
+ typedef CGAL::Epick_d<CGAL::Dimension_tag<4> > K;
+ typedef K::FT FT;
+ typedef K::Point_d Point;
+ typedef std::vector<Point> Points;
+
+ typedef Gudhi::spatial_searching::Kd_tree_search<
+ K, Points> Points_ds;
+
+ CGAL::Random rd;
+
+ Points points;
+ for (int i = 0; i < 500; ++i)
+ points.push_back(Point(rd.get_double(-1., 1), rd.get_double(-1., 1), rd.get_double(-1., 1), rd.get_double(-1., 1)));
+
+ Points_ds points_ds(points);
+
+ // Test query_k_nearest_neighbors
+ std::size_t closest_pt_index =
+ points_ds.query_k_nearest_neighbors(points[10], 1, false).begin()->first;
+ BOOST_CHECK(closest_pt_index == 10);
+
+ auto kns_range = points_ds.query_k_nearest_neighbors(points[20], 10, true);
+
+ std::vector<std::size_t> knn_result;
+ FT last_dist = -1.;
+ for (auto const& nghb : kns_range) {
+ BOOST_CHECK(nghb.second > last_dist);
+ knn_result.push_back(nghb.second);
+ last_dist = nghb.second;
+ }
+
+ // Test query_incremental_nearest_neighbors
+ closest_pt_index =
+ points_ds.query_incremental_nearest_neighbors(points[10]).begin()->first;
+ BOOST_CHECK(closest_pt_index == 10);
+
+ auto inn_range = points_ds.query_incremental_nearest_neighbors(points[20]);
+
+ std::vector<std::size_t> inn_result;
+ last_dist = -1.;
+ auto inn_it = inn_range.begin();
+ for (int i = 0; i < 10; ++inn_it, ++i) {
+ auto const& nghb = *inn_it;
+ BOOST_CHECK(nghb.second > last_dist);
+ inn_result.push_back(nghb.second);
+ last_dist = nghb.second;
+ }
+
+ // Same result for KNN and INN?
+ BOOST_CHECK(knn_result == inn_result);
+
+ // Test query_k_farthest_neighbors
+ auto kfn_range = points_ds.query_k_farthest_neighbors(points[20], 10, true);
+
+ std::vector<std::size_t> kfn_result;
+ last_dist = kfn_range.begin()->second;
+ for (auto const& nghb : kfn_range) {
+ BOOST_CHECK(nghb.second <= last_dist);
+ kfn_result.push_back(nghb.second);
+ last_dist = nghb.second;
+ }
+
+ // Test query_k_farthest_neighbors
+ auto ifn_range = points_ds.query_incremental_farthest_neighbors(points[20]);
+
+ std::vector<std::size_t> ifn_result;
+ last_dist = ifn_range.begin()->second;
+ auto ifn_it = ifn_range.begin();
+ for (int i = 0; i < 10; ++ifn_it, ++i) {
+ auto const& nghb = *ifn_it;
+ BOOST_CHECK(nghb.second <= last_dist);
+ ifn_result.push_back(nghb.second);
+ last_dist = nghb.second;
+ }
+
+ // Same result for KFN and IFN?
+ BOOST_CHECK(kfn_result == ifn_result);
+}
diff --git a/src/Subsampling/doc/Intro_subsampling.h b/src/Subsampling/doc/Intro_subsampling.h
new file mode 100644
index 00000000..c84616dd
--- /dev/null
+++ b/src/Subsampling/doc/Intro_subsampling.h
@@ -0,0 +1,70 @@
+/* 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 DOC_SUBSAMPLING_INTRO_SUBSAMPLING_H_
+#define DOC_SUBSAMPLING_INTRO_SUBSAMPLING_H_
+
+// needs namespace for Doxygen to link on classes
+namespace Gudhi {
+// needs namespace for Doxygen to link on classes
+namespace subsampling {
+
+/** \defgroup subsampling Subsampling
+ *
+ * \author Cl&eacute;ment Jamin, Siargey Kachanovich
+ *
+ * @{
+ *
+ * \section subsamplingintroduction Introduction
+ *
+ * This Gudhi component offers methods to subsample a set of points.
+ *
+ * \section sparsifyexamples Example: sparsify_point_set
+ *
+ * This example outputs a subset of the input points so that the
+ * squared distance between any two points
+ * is greater than or equal to 0.4.
+ *
+ * \include Subsampling/example_sparsify_point_set.cpp
+ *
+ * \section farthestpointexamples Example: choose_n_farthest_points
+ *
+ * This example outputs a subset of 100 points obtained by Gonz&aacute;lez algorithm,
+ * starting with a random point.
+ *
+ * \include Subsampling/example_choose_n_farthest_points.cpp
+ *
+ * \section randompointexamples Example: pick_n_random_points
+ *
+ * This example outputs a subset of 100 points picked randomly.
+ *
+ * \include Subsampling/example_pick_n_random_points.cpp
+ * \copyright GNU General Public License v3.
+ * \verbatim Contact: gudhi-users@lists.gforge.inria.fr \endverbatim
+ */
+/** @} */ // end defgroup subsampling
+
+} // namespace subsampling
+
+} // namespace Gudhi
+
+#endif // DOC_SUBSAMPLING_INTRO_SUBSAMPLING_H_
diff --git a/src/Subsampling/example/CMakeLists.txt b/src/Subsampling/example/CMakeLists.txt
new file mode 100644
index 00000000..54349f0c
--- /dev/null
+++ b/src/Subsampling/example/CMakeLists.txt
@@ -0,0 +1,20 @@
+cmake_minimum_required(VERSION 2.6)
+project(Subsampling_examples)
+
+if(CGAL_FOUND)
+ if (NOT CGAL_VERSION VERSION_LESS 4.8.1)
+ if (EIGEN3_FOUND)
+ add_executable(Subsampling_example_pick_n_random_points example_pick_n_random_points.cpp)
+ add_executable(Subsampling_example_choose_n_farthest_points example_choose_n_farthest_points.cpp)
+ add_executable(Subsampling_example_sparsify_point_set example_sparsify_point_set.cpp)
+ target_link_libraries(Subsampling_example_sparsify_point_set ${CGAL_LIBRARY})
+
+ add_test(Subsampling_example_pick_n_random_points
+ ${CMAKE_CURRENT_BINARY_DIR}/Subsampling_example_pick_n_random_points)
+ add_test(Subsampling_example_choose_n_farthest_points
+ ${CMAKE_CURRENT_BINARY_DIR}/Subsampling_example_choose_n_farthest_points)
+ add_test(Subsampling_example_sparsify_point_set
+ ${CMAKE_CURRENT_BINARY_DIR}/Subsampling_example_sparsify_point_set)
+ endif()
+ endif ()
+endif()
diff --git a/src/Subsampling/example/example_choose_n_farthest_points.cpp b/src/Subsampling/example/example_choose_n_farthest_points.cpp
new file mode 100644
index 00000000..533aba74
--- /dev/null
+++ b/src/Subsampling/example/example_choose_n_farthest_points.cpp
@@ -0,0 +1,27 @@
+#include <gudhi/choose_n_farthest_points.h>
+
+#include <CGAL/Epick_d.h>
+#include <CGAL/Random.h>
+
+#include <vector>
+#include <iterator>
+
+int main(void) {
+ typedef CGAL::Epick_d<CGAL::Dimension_tag<4> > K;
+ typedef typename K::Point_d Point_d;
+
+ CGAL::Random rd;
+
+ std::vector<Point_d> points;
+ for (int i = 0; i < 500; ++i)
+ points.push_back(Point_d(rd.get_double(-1., 1), rd.get_double(-1., 1),
+ rd.get_double(-1., 1), rd.get_double(-1., 1)));
+
+ K k;
+ std::vector<Point_d> results;
+ Gudhi::subsampling::choose_n_farthest_points(k, points, 100, std::back_inserter(results));
+ std::cout << "Before sparsification: " << points.size() << " points.\n";
+ std::cout << "After sparsification: " << results.size() << " points.\n";
+
+ return 0;
+}
diff --git a/src/Subsampling/example/example_pick_n_random_points.cpp b/src/Subsampling/example/example_pick_n_random_points.cpp
new file mode 100644
index 00000000..1e38e405
--- /dev/null
+++ b/src/Subsampling/example/example_pick_n_random_points.cpp
@@ -0,0 +1,27 @@
+#include <gudhi/pick_n_random_points.h>
+
+#include <CGAL/Epick_d.h>
+#include <CGAL/Random.h>
+
+#include <vector>
+#include <iterator>
+
+int main(void) {
+ typedef CGAL::Epick_d<CGAL::Dimension_tag<4> > K;
+ typedef typename K::Point_d Point_d;
+
+ CGAL::Random rd;
+
+ std::vector<Point_d> points;
+ for (int i = 0; i < 500; ++i)
+ points.push_back(Point_d(rd.get_double(-1., 1), rd.get_double(-1., 1),
+ rd.get_double(-1., 1), rd.get_double(-1., 1)));
+
+ K k;
+ std::vector<Point_d> results;
+ Gudhi::subsampling::pick_n_random_points(points, 100, std::back_inserter(results));
+ std::cout << "Before sparsification: " << points.size() << " points.\n";
+ std::cout << "After sparsification: " << results.size() << " points.\n";
+
+ return 0;
+}
diff --git a/src/Subsampling/example/example_sparsify_point_set.cpp b/src/Subsampling/example/example_sparsify_point_set.cpp
new file mode 100644
index 00000000..b35a18d9
--- /dev/null
+++ b/src/Subsampling/example/example_sparsify_point_set.cpp
@@ -0,0 +1,27 @@
+#include <gudhi/sparsify_point_set.h>
+
+#include <CGAL/Epick_d.h>
+#include <CGAL/Random.h>
+
+#include <vector>
+#include <iterator>
+
+int main(void) {
+ typedef CGAL::Epick_d<CGAL::Dimension_tag<4> > K;
+ typedef typename K::Point_d Point_d;
+
+ CGAL::Random rd;
+
+ std::vector<Point_d> points;
+ for (int i = 0; i < 500; ++i)
+ points.push_back(Point_d(rd.get_double(-1., 1), rd.get_double(-1., 1),
+ rd.get_double(-1., 1), rd.get_double(-1., 1)));
+
+ K k;
+ std::vector<Point_d> results;
+ Gudhi::subsampling::sparsify_point_set(k, points, 0.4, std::back_inserter(results));
+ std::cout << "Before sparsification: " << points.size() << " points.\n";
+ std::cout << "After sparsification: " << results.size() << " points.\n";
+
+ return 0;
+}
diff --git a/src/Subsampling/include/gudhi/choose_n_farthest_points.h b/src/Subsampling/include/gudhi/choose_n_farthest_points.h
new file mode 100644
index 00000000..9b45c640
--- /dev/null
+++ b/src/Subsampling/include/gudhi/choose_n_farthest_points.h
@@ -0,0 +1,132 @@
+/* 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/Kd_tree_search.h>
+
+#include <gudhi/Clock.h>
+
+#include <CGAL/Search_traits.h>
+#include <CGAL/Search_traits_adapter.h>
+#include <CGAL/Fuzzy_sphere.h>
+
+#include <iterator>
+#include <algorithm> // for sort
+#include <vector>
+#include <random>
+#include <limits> // for numeric_limits<>
+
+namespace Gudhi {
+
+namespace subsampling {
+
+/**
+ * \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`.
+ * \details It chooses `final_size` points from a random access range `input_pts` and
+ * outputs it in the output iterator `output_it`.
+ *
+ */
+template < typename Kernel,
+typename Point_container,
+typename OutputIterator>
+void choose_n_farthest_points(Kernel const &k,
+ Point_container const &input_pts,
+ std::size_t final_size,
+ std::size_t starting_point,
+ OutputIterator output_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;
+
+ 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];
+ 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;
+ }
+ }
+}
+
+/**
+ * \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 a random landmark.
+ * \details It chooses `final_size` points from a random access range `input_pts` and
+ * outputs it in the output iterator `output_it`.
+ *
+ */
+template < typename Kernel,
+typename Point_container,
+typename OutputIterator>
+void choose_n_farthest_points(Kernel const& k,
+ Point_container const &input_pts,
+ unsigned final_size,
+ OutputIterator output_it) {
+ // Tests to the limit
+ if ((final_size < 1) || (input_pts.size() == 0))
+ return;
+
+ // Choose randomly the first landmark
+ std::random_device rd;
+ std::mt19937 gen(rd());
+ std::uniform_int_distribution<> dis(0, (input_pts.size() - 1));
+ std::size_t starting_point = dis(gen);
+
+ choose_n_farthest_points(k, input_pts, final_size, starting_point, output_it);
+}
+
+} // namespace subsampling
+
+} // namespace Gudhi
+
+#endif // CHOOSE_N_FARTHEST_POINTS_H_
diff --git a/src/Subsampling/include/gudhi/pick_n_random_points.h b/src/Subsampling/include/gudhi/pick_n_random_points.h
new file mode 100644
index 00000000..e89b2b2d
--- /dev/null
+++ b/src/Subsampling/include/gudhi/pick_n_random_points.h
@@ -0,0 +1,84 @@
+/* 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);
+ assert(nbP >= final_size);
+ 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/src/Subsampling/include/gudhi/sparsify_point_set.h b/src/Subsampling/include/gudhi/sparsify_point_set.h
new file mode 100644
index 00000000..7ff11b4c
--- /dev/null
+++ b/src/Subsampling/include/gudhi/sparsify_point_set.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(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;
+
+ typename Kernel::Squared_distance_d sqdist = k.squared_distance_d_object();
+
+#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/src/Subsampling/test/CMakeLists.txt b/src/Subsampling/test/CMakeLists.txt
new file mode 100644
index 00000000..3a2fb649
--- /dev/null
+++ b/src/Subsampling/test/CMakeLists.txt
@@ -0,0 +1,38 @@
+cmake_minimum_required(VERSION 2.6)
+project(Subsampling_tests)
+
+if (GCOVR_PATH)
+ # for gcovr to make coverage reports - Corbera Jenkins plugin
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
+endif()
+if (GPROF_PATH)
+ # for gprof to make coverage reports - Jenkins
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg")
+endif()
+
+if(CGAL_FOUND)
+ if (NOT CGAL_VERSION VERSION_LESS 4.8.1)
+ if (EIGEN3_FOUND)
+ add_executable( Subsampling_test_pick_n_random_points test_pick_n_random_points.cpp )
+ target_link_libraries(Subsampling_test_pick_n_random_points ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+
+ add_executable( Subsampling_test_choose_n_farthest_points test_choose_n_farthest_points.cpp )
+ target_link_libraries(Subsampling_test_choose_n_farthest_points ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+
+ add_executable(Subsampling_test_sparsify_point_set test_sparsify_point_set.cpp)
+ target_link_libraries(Subsampling_test_sparsify_point_set ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+
+ add_test(Subsampling_test_pick_n_random_points ${CMAKE_CURRENT_BINARY_DIR}/Subsampling_test_pick_n_random_points
+ # XML format for Jenkins xUnit plugin
+ --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/Subsampling_test_pick_n_random_points_UT.xml --log_level=test_suite --report_level=no)
+
+ add_test(Subsampling_test_choose_n_farthest_points ${CMAKE_CURRENT_BINARY_DIR}/Subsampling_test_choose_n_farthest_points
+ # XML format for Jenkins xUnit plugin
+ --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/Subsampling_test_choose_n_farthest_points_UT.xml --log_level=test_suite --report_level=no)
+
+ add_test(Subsampling_test_sparsify_point_set ${CMAKE_CURRENT_BINARY_DIR}/Subsampling_test_sparsify_point_set
+ # XML format for Jenkins xUnit plugin
+ --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/Subsampling_test_sparsify_point_set_UT.xml --log_level=test_suite --report_level=no)
+ endif()
+ endif ()
+endif()
diff --git a/src/Subsampling/test/test_choose_n_farthest_points.cpp b/src/Subsampling/test/test_choose_n_farthest_points.cpp
new file mode 100644
index 00000000..0bc0dff4
--- /dev/null
+++ b/src/Subsampling/test/test_choose_n_farthest_points.cpp
@@ -0,0 +1,103 @@
+/* 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/>.
+ */
+
+// #ifdef _DEBUG
+// # define TBB_USE_THREADING_TOOL
+// #endif
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE "witness_complex_points"
+#include <boost/test/unit_test.hpp>
+#include <boost/mpl/list.hpp>
+
+#include <gudhi/choose_n_farthest_points.h>
+#include <vector>
+#include <iterator>
+
+#include <CGAL/Epick_d.h>
+
+typedef CGAL::Epick_d<CGAL::Dynamic_dimension_tag> K;
+typedef typename K::FT FT;
+typedef typename K::Point_d Point_d;
+
+typedef boost::mpl::list<CGAL::Epick_d<CGAL::Dynamic_dimension_tag>, CGAL::Epick_d<CGAL::Dimension_tag<4>>> list_of_tested_kernels;
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(test_choose_farthest_point, Kernel, list_of_tested_kernels) {
+ typedef typename Kernel::FT FT;
+ typedef typename Kernel::Point_d Point_d;
+ std::vector< Point_d > points, landmarks;
+ // Add grid points (625 points)
+ for (FT i = 0; i < 5; i += 1.0)
+ for (FT j = 0; j < 5; j += 1.0)
+ for (FT k = 0; k < 5; k += 1.0)
+ for (FT l = 0; l < 5; l += 1.0) {
+ std::vector<FT> point({i, j, k, l});
+ points.push_back(Point_d(point.begin(), point.end()));
+ }
+
+ landmarks.clear();
+ Kernel k;
+ Gudhi::subsampling::choose_n_farthest_points(k, points, 100, std::back_inserter(landmarks));
+
+ BOOST_CHECK(landmarks.size() == 100);
+ for (auto landmark : landmarks)
+ {
+ // Check all landmarks are in points
+ BOOST_CHECK(std::find (points.begin(), points.end(), landmark) != points.end());
+ }
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(test_choose_farthest_point_limits, Kernel, list_of_tested_kernels) {
+ typedef typename Kernel::FT FT;
+ typedef typename Kernel::Point_d Point_d;
+ std::vector< Point_d > points, landmarks;
+ landmarks.clear();
+ Kernel k;
+ // Choose -1 farthest points in an empty point cloud
+ Gudhi::subsampling::choose_n_farthest_points(k, points, -1, std::back_inserter(landmarks));
+ BOOST_CHECK(landmarks.size() == 0);
+ landmarks.clear();
+ // Choose 0 farthest points in an empty point cloud
+ Gudhi::subsampling::choose_n_farthest_points(k, points, 0, std::back_inserter(landmarks));
+ BOOST_CHECK(landmarks.size() == 0);
+ landmarks.clear();
+ // Choose 1 farthest points in an empty point cloud
+ Gudhi::subsampling::choose_n_farthest_points(k, points, 1, std::back_inserter(landmarks));
+ BOOST_CHECK(landmarks.size() == 0);
+ landmarks.clear();
+
+ std::vector<FT> point({0.0, 0.0, 0.0, 0.0});
+ points.push_back(Point_d(point.begin(), point.end()));
+ // Choose -1 farthest points in an empty point cloud
+ Gudhi::subsampling::choose_n_farthest_points(k, points, -1, std::back_inserter(landmarks));
+ BOOST_CHECK(landmarks.size() == 1);
+ landmarks.clear();
+ // Choose 0 farthest points in a one point cloud
+ Gudhi::subsampling::choose_n_farthest_points(k, points, 0, std::back_inserter(landmarks));
+ BOOST_CHECK(landmarks.size() == 0);
+ landmarks.clear();
+ // Choose 1 farthest points in a one point cloud
+ Gudhi::subsampling::choose_n_farthest_points(k, points, 1, std::back_inserter(landmarks));
+ BOOST_CHECK(landmarks.size() == 1);
+ landmarks.clear();
+
+}
diff --git a/src/Subsampling/test/test_pick_n_random_points.cpp b/src/Subsampling/test/test_pick_n_random_points.cpp
new file mode 100644
index 00000000..6c8dbea2
--- /dev/null
+++ b/src/Subsampling/test/test_pick_n_random_points.cpp
@@ -0,0 +1,69 @@
+/* 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/>.
+ */
+
+// #ifdef _DEBUG
+// # define TBB_USE_THREADING_TOOL
+// #endif
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE Subsampling - test pick_n_random_points
+#include <boost/test/unit_test.hpp>
+
+#include <gudhi/pick_n_random_points.h>
+#include <vector>
+#include <iterator>
+
+#include <CGAL/Epick_d.h>
+
+
+BOOST_AUTO_TEST_CASE(test_pick_n_random_points)
+{
+ typedef CGAL::Epick_d<CGAL::Dynamic_dimension_tag> K;
+ typedef typename K::FT FT;
+ typedef typename K::Point_d Point_d;
+
+ std::vector<Point_d> vect;
+ vect.push_back(Point_d(std::vector<FT>({0,0,0,0})));
+ vect.push_back(Point_d(std::vector<FT>({0,0,0,1})));
+ vect.push_back(Point_d(std::vector<FT>({0,0,1,0})));
+ vect.push_back(Point_d(std::vector<FT>({0,0,1,1})));
+ vect.push_back(Point_d(std::vector<FT>({0,1,0,0})));
+ vect.push_back(Point_d(std::vector<FT>({0,1,0,1})));
+ vect.push_back(Point_d(std::vector<FT>({0,1,1,0})));
+ vect.push_back(Point_d(std::vector<FT>({0,1,1,1})));
+ vect.push_back(Point_d(std::vector<FT>({1,0,0,0})));
+ vect.push_back(Point_d(std::vector<FT>({1,0,0,1})));
+ vect.push_back(Point_d(std::vector<FT>({1,0,1,0})));
+ vect.push_back(Point_d(std::vector<FT>({1,0,1,1})));
+ vect.push_back(Point_d(std::vector<FT>({1,1,0,0})));
+ vect.push_back(Point_d(std::vector<FT>({1,1,0,1})));
+ vect.push_back(Point_d(std::vector<FT>({1,1,1,0})));
+ vect.push_back(Point_d(std::vector<FT>({1,1,1,1})));
+
+ std::vector<Point_d> results;
+ Gudhi::subsampling::pick_n_random_points(vect, 5, std::back_inserter(results));
+ std::cout << "landmark vector contains: ";
+ for (auto l: results)
+ std::cout << l << "\n";
+
+ BOOST_CHECK(results.size() == 5);
+}
diff --git a/src/Subsampling/test/test_sparsify_point_set.cpp b/src/Subsampling/test/test_sparsify_point_set.cpp
new file mode 100644
index 00000000..f993d6d6
--- /dev/null
+++ b/src/Subsampling/test/test_sparsify_point_set.cpp
@@ -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): 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/>.
+ */
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE Subsampling - test sparsify_point_set
+#include <boost/test/unit_test.hpp>
+
+#include <gudhi/sparsify_point_set.h>
+
+#include <CGAL/Epick_d.h>
+#include <CGAL/Random.h>
+
+#include <vector>
+#include <iterator>
+
+BOOST_AUTO_TEST_CASE(test_sparsify_point_set)
+{
+ typedef CGAL::Epick_d<CGAL::Dimension_tag<4> > K;
+ typedef typename K::Point_d Point_d;
+
+ CGAL::Random rd;
+
+ std::vector<Point_d> points;
+ for (int i = 0 ; i < 500 ; ++i)
+ points.push_back(Point_d(rd.get_double(-1.,1),rd.get_double(-1.,1),rd.get_double(-1.,1),rd.get_double(-1.,1)));
+
+ K k;
+ std::vector<Point_d> results;
+ Gudhi::subsampling::sparsify_point_set(k, points, 0.5, std::back_inserter(results));
+ std::cout << "Before sparsification: " << points.size() << " points.\n";
+ std::cout << "After sparsification: " << results.size() << " points.\n";
+ //for (auto p : results)
+ // std::cout << p << "\n";
+
+ BOOST_CHECK(points.size() > results.size());
+}
diff --git a/src/Tangential_complex/benchmark/CMakeLists.txt b/src/Tangential_complex/benchmark/CMakeLists.txt
new file mode 100644
index 00000000..56dd8128
--- /dev/null
+++ b/src/Tangential_complex/benchmark/CMakeLists.txt
@@ -0,0 +1,26 @@
+cmake_minimum_required(VERSION 2.6)
+project(Tangential_complex_benchmark)
+
+if (GCOVR_PATH)
+ # for gcovr to make coverage reports - Corbera Jenkins plugin
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
+endif()
+if (GPROF_PATH)
+ # for gprof to make coverage reports - Jenkins
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg")
+endif()
+
+# need CGAL 4.8
+if(CGAL_FOUND)
+ if (NOT CGAL_VERSION VERSION_LESS 4.8.0)
+ if (EIGEN3_FOUND)
+ add_executable(Tangential_complex_benchmark benchmark_tc.cpp)
+ target_link_libraries(Tangential_complex_benchmark
+ ${Boost_DATE_TIME_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY})
+ if (TBB_FOUND)
+ target_link_libraries(Tangential_complex_benchmark ${TBB_LIBRARIES})
+ endif(TBB_FOUND)
+ endif(EIGEN3_FOUND)
+ endif (NOT CGAL_VERSION VERSION_LESS 4.8.0)
+endif(CGAL_FOUND)
+
diff --git a/src/Tangential_complex/benchmark/RIB_exporter.h b/src/Tangential_complex/benchmark/RIB_exporter.h
new file mode 100644
index 00000000..73c14041
--- /dev/null
+++ b/src/Tangential_complex/benchmark/RIB_exporter.h
@@ -0,0 +1,269 @@
+/* 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 GUDHI_TC_RIB_EXPORTER_H
+#define GUDHI_TC_RIB_EXPORTER_H
+
+#include <gudhi/Tangential_complex/utilities.h>
+
+#include <tuple>
+#include <string>
+
+template <typename PointRandomAccessRange, typename SimplexRange>
+class RIB_exporter {
+ typedef typename PointRandomAccessRange::value_type Point;
+ typedef typename SimplexRange::value_type Simplex;
+ public:
+
+ typedef std::tuple<double, double, double, double> Color; // RGBA
+ typedef std::tuple<int, int, int> Coords_choice;
+
+ // Constructor
+ RIB_exporter(
+ PointRandomAccessRange const& points,
+ SimplexRange const& simplices,
+ std::ofstream &out,
+ std::string const& rendered_image_filename = "export.tif",
+ bool is_preview = false, // low-quality
+ Coords_choice coords_choice = std::make_tuple(0, 1, 2),
+ int image_width = 1920,
+ int image_height = 1080,
+ Color const& triangle_color = std::make_tuple(1., 1., 1., 1.),
+ bool ambient_light = true,
+ double ambient_intensity = 0.3,
+ bool shadow = true,
+ double shadow_intensity = 0.85,
+ double point_sphere_radius = 0.003)
+ : m_points(points),
+ m_simplices(simplices),
+ m_out(out),
+ m_rendered_image_filename(rendered_image_filename),
+ m_is_preview(is_preview),
+ m_coords_choice(coords_choice),
+ m_image_width(image_width),
+ m_image_height(image_height),
+ m_current_color(0., 0., 0., 0.),
+ m_current_alpha(1),
+ m_triangle_color(triangle_color),
+ m_ambient_light(ambient_light),
+ m_ambient_intensity(ambient_intensity),
+ m_shadow(shadow),
+ m_shadow_intensity(shadow_intensity),
+ m_point_sphere_radius(point_sphere_radius) {
+ m_out.precision(8);
+ }
+
+ void write_file() {
+ write_header();
+ write_lights();
+ /*if (m_point_sphere_radius != 0.)
+ write_point_spheres();*/
+ write_triangles();
+
+ m_out << "WorldEnd\n";
+ }
+
+ private:
+
+ void write_header() {
+ m_out << "Option \"searchpath\" \"shader\" "
+ "\".:./shaders:%PIXIE_SHADERS%:%PIXIEHOME%/shaders\"\n";
+
+ if (m_is_preview) {
+ m_out << "Attribute \"visibility\" \"specular\" 1\n"
+ << "Attribute \"visibility\" \"transmission\" 1\n\n";
+ }
+
+ m_out << "Display \"" << m_rendered_image_filename << "\" \"file\" \"rgb\"\n";
+
+ if (!m_is_preview) {
+ m_out << "Format " << m_image_width << " " << m_image_height << " 1\n";
+ } else {
+ double ratio = double(m_image_height) / double(m_image_width);
+
+ int width = (ratio < 1.) ? 300 : int(300. / ratio);
+ int height = (ratio < 1.) ? int(ratio * 300.) : 300;
+
+ m_out << "Format " << width << " " << height << " 1\n";
+ }
+
+
+ if (m_image_width > m_image_height) {
+ double ratio = double(m_image_height) / double(m_image_width);
+ m_out << "ScreenWindow -1 1 " << -ratio << " " << ratio << "\n";
+ } else if (m_image_height > m_image_width) {
+ double ratio = double(m_image_width) / double(m_image_height);
+ m_out << "ScreenWindow " << -ratio << " " << ratio << " -1 1\n";
+ }
+
+ m_out << "Projection \"perspective\" \"fov\" 45\n"
+ << "Translate 0 0 3\n"
+ << "PixelSamples 4 4\n"
+ << "PixelFilter \"catmull-rom\" 3 3\n"
+ << "ShadingInterpolation \"smooth\"\n"
+ << "Rotate -10 20 0 1\n"
+ << "WorldBegin\n";
+ }
+
+ void write_lights() {
+ if (!m_is_preview) {
+ // ShadowLight
+ m_out << "LightSource \"shadowdistant\" 1 \"from\" [0 0 0] \"to\" [0 0 1]"
+ << " \"shadowname\" \"raytrace\" \"intensity\" "
+ << m_shadow_intensity << "\n";
+
+ // Ambient light
+ m_out << "LightSource \"ambientlight\" 2 \"intensity\" "
+ << m_ambient_intensity << "\n";
+ } else {
+ m_out << "LightSource \"distantLight\" 1 \"from\" [0 0 0] \"to\" [0 0 1]"
+ << " \"intensity\" " << m_shadow_intensity << "\n";
+
+ // Ambient light
+ m_out << "LightSource \"ambientlight\" 2 \"intensity\" "
+ << m_ambient_intensity << "\n";
+ }
+
+ // Background light
+ m_out << "LightSource \"ambientlight\" 99 \"intensity\" 1\n";
+
+ // Turn background light OFF
+ turn_background_light(false);
+ }
+
+ void turn_background_light(bool turn_on) {
+ if (!turn_on) {
+ m_out << "Illuminate 1 1" << std::endl;
+ if (!m_is_preview)
+ m_out << "Illuminate 2 1" << std::endl;
+ m_out << "Illuminate 99 0" << std::endl;
+ } else {
+ m_out << "Illuminate 1 0" << std::endl;
+ if (!m_is_preview)
+ m_out << "Illuminate 2 0" << std::endl;
+ m_out << "Illuminate 99 1" << std::endl;
+ }
+ }
+
+ void write_color(Color const& color, bool use_transparency) {
+ if (m_current_color == color)
+ return;
+
+ m_current_color = color;
+
+ // Write opacity data
+ if (use_transparency)
+ write_opacity(std::get<3>(color));
+
+ // Write color data
+ m_out << "Color [ " << std::get<0>(color) << " " << std::get<1>(color)
+ << " " << std::get<2>(color) << " ]\n";
+ }
+
+ void write_opacity(const double alpha) {
+ if (m_current_alpha == alpha)
+ return;
+
+ m_current_alpha = alpha;
+
+ // Write opacity data
+ m_out << "Opacity " << alpha << " " << alpha << " " << alpha << std::endl;
+ }
+
+ void write_point(Point const& p) {
+ m_out << " " << p[std::get<0>(m_coords_choice)]
+ << " " << p[std::get<1>(m_coords_choice)]
+ << " " << p[std::get<2>(m_coords_choice)] << " ";
+ }
+
+ void write_triangles() {
+ m_out << "Surface \"plastic\" \"Ka\" 0.65 \"Kd\" 0.85 \"Ks\" 0.25 \"roughness\" 0.1" << std::endl;
+
+ for (auto const& simplex : m_simplices) {
+ std::vector<Simplex> triangles;
+ // Get the triangles composing the simplex
+ combinations(simplex, 3, std::back_inserter(triangles));
+ for (auto const& t : triangles)
+ write_triangle(t);
+ }
+ }
+
+ template <typename PointIndexRange>
+ void write_triangle(PointIndexRange const& t) {
+ // Color
+ write_color(m_triangle_color, true);
+
+ // Triangle
+ m_out << "Polygon \"P\" [";
+ for (auto idx : t)
+ write_point(m_points[idx]);
+ m_out << "]" << std::endl;
+
+ // Edges (will be drawn later on)
+ /*add_edge(p, q, edge_color);
+ add_edge(p, r, edge_color);
+ add_edge(q, r, edge_color);
+
+ // Vertices (will be drawn later on)
+ add_vertex(p, edge_color);
+ add_vertex(q, edge_color);
+ add_vertex(r, edge_color);*/
+ }
+
+ void write_point_sphere(Point const& p) {
+ if (m_point_sphere_radius == 0.)
+ return;
+
+ m_out << "Translate " << p[0] << " " << p[1] << " " << p[2] << std::endl;
+ // Sphere radius zmin zmax thetamax
+ m_out << "Sphere " << m_point_sphere_radius << " " << -m_point_sphere_radius
+ << " " << m_point_sphere_radius << " 360" << std::endl;
+ m_out << "Identity" << std::endl;
+ }
+
+ void write_point_spheres() {
+ write_color(std::make_tuple(0.7, 0.7, 0.7, 0.5), true);
+ for (auto const& p : m_points)
+ write_point_sphere(p);
+ }
+
+ //===========================================================================
+
+ PointRandomAccessRange const& m_points;
+ SimplexRange const& m_simplices;
+ std::ofstream &m_out;
+ std::string m_rendered_image_filename;
+ bool m_is_preview;
+ Coords_choice m_coords_choice;
+ int m_image_width;
+ int m_image_height;
+ Color m_current_color;
+ Color m_triangle_color;
+ double m_current_alpha;
+ bool m_ambient_light;
+ double m_ambient_intensity;
+ bool m_shadow;
+ double m_shadow_intensity;
+ double m_point_sphere_radius;
+};
+
+#endif // GUDHI_TC_RIB_EXPORTER_H
diff --git a/src/Tangential_complex/benchmark/XML_exporter.h b/src/Tangential_complex/benchmark/XML_exporter.h
new file mode 100644
index 00000000..ed44f90a
--- /dev/null
+++ b/src/Tangential_complex/benchmark/XML_exporter.h
@@ -0,0 +1,207 @@
+/* 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/>.
+ */
+
+#include <string>
+#include <vector>
+#include <iostream>
+#include <fstream>
+#include <ctime>
+
+template<typename value_type = std::string>
+class Simple_XML_exporter {
+ public:
+ typedef value_type Value_type;
+ typedef std::vector<value_type> Element;
+ typedef std::map<std::string, value_type> Element_with_map;
+ typedef std::vector<Element> List_of_elements;
+
+ Simple_XML_exporter(
+ const std::string &list_name,
+ const std::string &element_name,
+ const std::vector<std::string> &subelement_names,
+ bool add_timestamp = true)
+ : m_list_name(list_name),
+ m_element_name(element_name),
+ m_subelement_names(subelement_names),
+ m_add_timestamp(add_timestamp) { }
+
+ bool add_element(const Element &element) {
+ if (element.size() == m_subelement_names.size()) {
+ m_list_of_elements.push_back(element);
+ return true;
+ } else {
+ std::cerr << "ERROR: element.size() == m_subelement_names.size()" << std::endl;
+ return false;
+ }
+ }
+
+ bool add_element(Element_with_map &element) {
+ Element elt;
+
+ std::vector<std::string>::const_iterator
+ it_subelement_name = m_subelement_names.begin();
+ std::vector<std::string>::const_iterator
+ it_subelement_name_end = m_subelement_names.end();
+ for (; it_subelement_name != it_subelement_name_end; ++it_subelement_name) {
+ elt.push_back(element[*it_subelement_name]);
+ }
+
+ return add_element(elt);
+ }
+
+ bool export_to_xml(const std::string &filename) const {
+ std::ofstream xmlfile;
+ xmlfile.open(filename.c_str());
+ xmlfile << "<?xml version='1.0'?>" << std::endl;
+ xmlfile << "<" << m_list_name << ">" << std::endl;
+
+ typename List_of_elements::const_iterator it_element = m_list_of_elements.begin();
+ typename List_of_elements::const_iterator it_element_end = m_list_of_elements.end();
+ for (int id = 1; it_element != it_element_end; ++it_element, ++id) {
+ xmlfile << " <" << m_element_name << ">" << std::endl;
+ std::vector<std::string>::const_iterator
+ it_subelement_name = m_subelement_names.begin();
+ std::vector<std::string>::const_iterator
+ it_subelement_name_end = m_subelement_names.end();
+
+ if (m_add_timestamp)
+ xmlfile << " <id> " << time(NULL) << " </id>" << std::endl;
+
+ for (int i = 0;
+ it_subelement_name != it_subelement_name_end;
+ ++it_subelement_name, ++i) {
+ xmlfile
+ << " <" << *it_subelement_name << "> "
+ << (*it_element)[i]
+ << " </" << *it_subelement_name << ">" << std::endl;
+ }
+ xmlfile << " </" << m_element_name << ">" << std::endl;
+ }
+
+ xmlfile << "</" << m_list_name << ">" << std::endl;
+ xmlfile.close();
+ return 0;
+
+ }
+
+ protected:
+ std::string m_list_name;
+ std::string m_element_name;
+ std::vector<std::string> m_subelement_names;
+ List_of_elements m_list_of_elements;
+ bool m_add_timestamp;
+};
+
+template<typename value_type = std::string>
+class Streaming_XML_exporter {
+ public:
+ typedef value_type Value_type;
+ typedef std::vector<value_type> Element;
+ typedef std::map<std::string, value_type> Element_with_map;
+ typedef std::vector<Element> List_of_elements;
+
+ Streaming_XML_exporter(
+ const std::string &filename,
+ const std::string &list_name,
+ const std::string &element_name,
+ const std::vector<std::string> &subelement_names,
+ bool add_timestamp = true)
+ : m_list_name(list_name),
+ m_element_name(element_name),
+ m_subelement_names(subelement_names),
+ m_add_timestamp(add_timestamp) {
+ m_xml_fstream.open(filename.c_str());
+ if (m_xml_fstream.good()) {
+ m_xml_fstream << "<?xml version='1.0'?>" << std::endl;
+ m_xml_fstream << "<" << m_list_name << ">" << std::endl;
+ } else {
+ std::cerr << "Could not open file '" << filename << "'." << std::endl;
+ }
+ }
+
+ virtual ~Streaming_XML_exporter() {
+ close_file();
+ }
+
+ void close_file() {
+ m_xml_fstream.close();
+ }
+
+ bool add_element(const Element &element) {
+ if (element.size() == m_subelement_names.size()) {
+ m_xml_fstream << " <" << m_element_name << ">" << std::endl;
+ std::vector<std::string>::const_iterator
+ it_subelement_name = m_subelement_names.begin();
+ std::vector<std::string>::const_iterator
+ it_subelement_name_end = m_subelement_names.end();
+
+ if (m_add_timestamp) {
+ m_xml_fstream << " <id> " << time(NULL) << " </id>" << std::endl;
+ }
+
+ for (int i = 0;
+ it_subelement_name != it_subelement_name_end;
+ ++it_subelement_name, ++i) {
+ m_xml_fstream
+ << " <" << *it_subelement_name << "> "
+ << element[i]
+ << " </" << *it_subelement_name << ">" << std::endl;
+ }
+ m_xml_fstream << " </" << m_element_name << ">" << std::endl;
+
+ // Save current pointer position
+ std::ofstream::streampos pos = m_xml_fstream.tellp();
+ // Close the XML file (temporarily) so that the XML file is always correct
+ m_xml_fstream << "</" << m_list_name << ">" << std::endl;
+ // Restore the pointer position so that the next "add_element" will overwrite
+ // the end of the file
+ m_xml_fstream.seekp(pos);
+
+ m_xml_fstream.flush();
+ return true;
+ } else {
+ std::cerr << "ERROR: element.size() == m_subelement_names.size()" << std::endl;
+ return false;
+ }
+ }
+
+ bool add_element(Element_with_map &element) {
+ Element elt;
+
+ std::vector<std::string>::const_iterator
+ it_subelement_name = m_subelement_names.begin();
+ std::vector<std::string>::const_iterator
+ it_subelement_name_end = m_subelement_names.end();
+ for (; it_subelement_name != it_subelement_name_end; ++it_subelement_name) {
+ elt.push_back(element[*it_subelement_name]);
+ }
+
+ return add_element(elt);
+ }
+
+ protected:
+ std::ofstream m_xml_fstream;
+ std::string m_list_name;
+ std::string m_element_name;
+ std::vector<std::string> m_subelement_names;
+ bool m_add_timestamp;
+};
diff --git a/src/Tangential_complex/benchmark/benchmark_script.txt b/src/Tangential_complex/benchmark/benchmark_script.txt
new file mode 100644
index 00000000..f4ddaac3
--- /dev/null
+++ b/src/Tangential_complex/benchmark/benchmark_script.txt
@@ -0,0 +1,221 @@
+#---------------------------------------------------------------------------------------------------------------------------------------------------------
+# Input PARAM1 PARAM2 PARAM3 NUM_P AMB INTR SPARSITY MAX_PERTURB PERTURB ADD_HDIM COLLAPSE FIX_TIME_LIMIT NUM_ITERATIONS
+#---------------------------------------------------------------------------------------------------------------------------------------------------------
+
+#---------------------------------------------------------------- Alpha TC tests ------------------------------------------------------------------------
+#generate_sphere_d 1 0 - 8 2 1 0.01 0.005 N Y N 3 1 #No noise => OK: 6 2d with a perturb sometimes
+#generate_sphere_d 1 0 - 50 2 1 0.01 0.005 N Y N 3 1 #No noise => OK: 49 1d
+#generate_sphere_d 1 1 - 50 2 1 0.01 0.005 N Y N 3 1 #Noise => OK: 45 2d + 3 3d
+#generate_torus_d N - - 15 2 1 0.01 0.05 N Y N 10 1
+#generate_sphere_d 0.302 0 - 8 3 2 0.01 0.005 N Y N 60 1 #No noise => OK: 7 3d with a perturb sometimes
+#generate_sphere_d 0.302 0 - 50 3 2 0.01 0.005 N Y N 60 1 #No noise => no inconsitencies
+#generate_sphere_d 0.302 3 - 50 3 2 0.01 0.005 N Y N 60 1 #Noise => OK: 90 2d + 3 3d
+#generate_sphere_d 1 1 - 500 4 3 0.01 0.005 N Y N 60 1 #Noise 1% => OK: 3113 3d + 35 4d
+#generate_sphere_d 1 2 - 500 4 3 0.01 0.005 N Y N 60 1 #Noise 2% => OK: 2969 3d + 91 4d
+#generate_sphere_d 1 2 - 5000 4 3 0.01 0.005 N Y N 60 1 #Noise 2% => OK: 27905 3d + 2485 4d
+#generate_sphere_d 0.302 2 - 300 2 1 0.01 0.005 N Y N 60 1
+#generate_torus_3D 2 1 N 200 3 2 0.01 0.05 N Y N 600 1 #OK: 1048 3d ~170s
+#generate_torus_3D 2 1 N 2000 3 2 0.01 0.05 N Y N 600 1 #OK: 3545 2d + 27 3d ~35s
+#generate_torus_d N 1 - 50 4 2 0.01 0.05 N Y N 3 1 #OK: 431 4d
+#generate_torus_d N 1 - 500 4 2 0.01 0.05 N Y N 3 1 #OK: 881 2d + 37 3d
+#generate_torus_d Y 1 - 250 4 2 0.01 0.05 N Y N 3 1 #OK: 80 d2 + 185 d3
+#generate_torus_d N - - 50 6 3 0.01 0.05 Y Y N 10 1 #
+#generate_torus_d Y - - 700 6 3 0.01 0.05 Y Y N 100 1 #Grid
+#generate_torus_d N - - 10000 6 3 0.01 0.05 Y Y N 30000 1
+#generate_moment_curve 0 1 - 10 3 1 0.01 0.005 N Y N 60 1
+#generate_two_spheres_d 3 4 - 500 3 2 0.01 0.05 N Y N 10 1 #OK: 320 2d + 1167 3d
+#generate_klein_bottle_4D 40 15 - 500 4 2 0.01 0.2 N Y N 60 1 #OK: 901 d2 + 50 d3 + 1 d4
+#data/SO3_10000.xyz - - - 0 9 3 0.01 0.05 Y Y N 300 1 #Too long. Be careful with the memory consumption!
+#data/buddha_100kv.xyz - - - 0 3 2 0.01 0.005 Y Y N 120 1 #Too long...
+#data/fandisk.xyz - - - 0 3 2 0.01 0.005 Y Y N 5 1 #NOT OK: Tq & V do not intersect
+
+#---------------------------------------------------------- Spatial search benchmarking --------------------------------------------------------------
+#generate_torus_3D 2 1 Y 10000 3 2 0 0 Y N N 600 1
+#data/buddha_100kv.xyz - - - 0 3 2 0 0 N Y N 120 1
+#generate_torus_d N - - 10000 30 15 0 0 Y N N 3600 1
+#generate_torus_d N - - 100000 12 6 0 0 Y N N 3600 1
+#data/SO3_50000.xyz - - - 0 9 3 0 0 Y N N 60 1
+#data/Cy8.xyz - - - 0 24 2 0 0 N Y N 60 1
+#generate_sphere_d 0.5 - - 10000 2 1 0 0 N N Y 60 1
+#generate_sphere_d 0.5 - - 10000 3 2 0 0 N N Y 60 1
+#generate_sphere_d 0.5 - - 10000 4 3 0 0 N N Y 60 1
+#generate_sphere_d 0.5 - - 10000 5 4 0 0 N N Y 60 1
+#generate_sphere_d 0.5 - - 10000 6 5 0 0 N N Y 60 1
+#generate_sphere_d 0.5 - - 10000 7 6 0 0 N N Y 60 1
+
+#---------------------------------------------------------- Very small cases for Debug mode --------------------------------------------------------------
+#generate_sphere_d 4 - - 20 3 2 0.05 0.025 Y N N 60 1
+generate_sphere_d 3 10 - 70 3 2 0.05 0.025 Y N N 60 1
+#generate_sphere_d 3 - - 1000 3 2 0.05 0.025 Y N N 60 1
+#generate_sphere_d 3 - - 10 4 3 0.05 0.025 Y N N 60 1
+#generate_sphere_d 3 - - 70 5 4 0.05 0.025 Y N N 60 1
+#generate_klein_bottle_4D 4 3 - 70 4 2 0.05 0.025 Y N N 3 1
+#generate_klein_bottle_variant_5D 4 3 - 70 5 2 0.05 0.025 Y N N 3 1
+#data/SO3_10000.xyz - - - 0 9 3 0.7 0.35 Y N N 60 1
+#generate_moment_curve 0 1 - 30 3 1 0.005 0.0025 Y N N 60 1
+
+#------------------------------------------------------------------ From files --------------------------------------------------------------------------
+#data/SO3_50000.xyz - - - 0 9 3 0.05 0.05 Y N N 6000 1
+#data/SO3_10000.xyz - - - 0 9 3 0.1 0.1 Y N N 60000 1
+#data/cube3D_eps_0.1.xyz - - - 0 3 2 0.05 0.05 Y N N 3000 1
+#data/cube4D_eps_0.1.xyz - - - 0 4 3 0.05 0.05 N Y N 3000 1
+#data/cube5D_eps_0.1.xyz - - - 0 5 4 0.05 0.05 N Y N 3000 1
+#data/Cy8.xyz - - - 0 24 2 0.1 0.1 N Y N 60 1
+#data/Kl.xyz - - - 0 5 2 0.05 0.05 N Y N 60 1
+#data/S3.xyz - - - 0 4 3 0.05 0.05 N Y N 60 1
+
+#data/Alvarez_variete_k2_D4_29700p.xyz - - - 0 4 2 0.01 0.01 Y N N 60 1 # points on a "grid"
+#data/Alvarez_variete_k2_D4_10k_1x1_v2.xyz - - - 0 4 2 0.001 0.001 Y N N 200 1
+#data/Alvarez_variete_k2_D4_30k_1x1_v2.xyz - - - 0 4 2 0.001 0.001 Y N N 6000 1
+#data/Alvarez_variete_k2_D4_120k_2x2_denser_in_1x1.xyz - - - 0 4 2 0.002 0.002 Y N N 60000 1
+#data/Alvarez_variete_k2_D4_300k_2x2.xyz - - - 0 4 2 0.005 0.005 Y N N 100000 1
+#data/Alvarez_variete_k2_D4_300k_2x2.xyz - - - 0 4 2 0.05 0.05 Y N N 50000 1 # heavy sparsification (e.g. 0.05 => 33k points)
+#data/Alvarez_variete_k2_D4_90k_2x2.xyz - - - 0 4 2 0.003 0.003 Y N N 6000 1
+#data/Alvarez_variete_k2_D4_30k_10x10.xyz - - - 0 4 2 0.01 0.01 Y N N 60 1
+#data/Alvarez_variete_k2_D4_60k_10x10.xyz - - - 0 4 2 0.01 0.01 Y N N 1800 1
+
+#data/Alvarez_variete_k2_D8_9003p.xyz - - - 0 8 2 0.001 0.001 Y N N 60 1
+#data/Alvarez_variete_k2_D8_90K.xyz - - - 0 8 2 0.001 0.001 Y N N 60 1
+#data/Alvarez_variete_k2_D8_300k_10x10.xyz - - - 0 8 2 0.01 0.01 Y N N 60 1 # heavy sparsification
+#data/Alvarez_variete_k2_D8_900k_2x2.xyz - - - 0 8 2 0.01 0.01 Y N N 60 1 # heavy sparsification
+#data/Alvarez_variete_k2_D8_900k_10x10.xyz - - - 0 8 2 0.02 0.02 Y N N 60 1 # heavy sparsification
+
+#data/Alvarez_courbeElliptique_k2_D8_200K_2x2.xyz - - - 0 8 2 0.006 0.006 Y N N 60 1
+
+#data/Alvarez_surface_deg2_k2_D8_6000K_10x10.xyz - - - 0 8 2 0.01 0.01 Y N N 60 1
+#data/Alvarez_surface_deg3_k2_D8_902K.xyz - - - 0 8 2 0.003 0.003 Y N N 3600 1
+#data/Alvarez_surface_deg4_k2_D8_382K.xyz - - - 0 8 2 0.01 0.01 Y N N 60 1
+#data/Alvarez_surface_deg5_k2_D8_112K.xyz - - - 0 8 2 0.001 0.001 Y N N 240 1
+#data/Alvarez_surface_deg6_k2_D8_67K.xyz - - - 0 8 2 0.015 0.015 Y N N 60 1
+#data/Alvarez_surface_deg7_k2_D8_48K.xyz - - - 0 8 2 0.01 0.01 Y N N 60 1
+#data/Alvarez_surface_deg8_k2_D8_41K.xyz - - - 0 8 2 0.025 0.025 Y N N 60 1
+#data/Alvarez_surface_deg9_k2_D8_42K.xyz - - - 0 8 2 0.01 0.01 Y N N 60 1
+#data/Alvarez_surface_deg10_k2_D8_41K.xyz - - - 0 8 2 0.01 0.01 Y N N 60 1
+
+#data/Alvarez_surface_deg8_k2_D8_41K.xyz - - - 0 8 2 0.02 0.02 Y N N 600 1
+#data/sparsified/Alvarez_deg8_k2_D8_32K_sparsified_from_41K_0.01.xyz - - - 0 8 2 0.05 0.05 Y N N 600 1
+
+# PAS VRAIMENT DE DIFFERENCE
+#data/Alvarez_surface_deg3_k2_D8_902K.xyz - - - 0 8 2 0.003 0.007 Y N N 3600 1
+#data/Alvarez_surface_deg3_k2_D8_902K.xyz - - - 0 8 2 0.014 0.007 Y N N 3600 1
+
+# PAS VRAIMENT DE DIFFERENCE
+#data/Alvarez_surface_deg7_k2_D8_48K.xyz - - - 0 8 2 0.01 0.005 Y N N 120 1
+#data/Alvarez_surface_deg7_k2_D8_48K.xyz - - - 0 8 2 0.02 0.005 Y N N 120 1
+
+# PAS VRAIMENT DE DIFFERENCE
+#data/Alvarez_surface_deg3_k2_D8_902K.xyz - - - 0 8 2 0.001 0.01 Y N N 3600 1
+#data/Alvarez_surface_deg3_k2_D8_902K.xyz - - - 0 8 2 0.02 0.01 Y N N 3600 1
+#data/sparsified/Alvarez_deg3_k2_D8_534k_sparsified_from_902K_0.001.xyz - - - 0 8 2 0.01 0.01 Y N N 3600 1
+
+# PAS TRES CLAIR, MAIS DIFFERENCE EN NOMBRE D'ETAPES (>100 vs 15-20) :
+#data/sparsified/Alvarez_deg8_k2_D8_38K_sparsified_from_41K_0.005.xyz - - - 0 8 2 0.02 0.02 Y N N 600 1
+#data/Alvarez_surface_deg8_k2_D8_41K.xyz - - - 0 8 2 0.001 0.02 Y N N 60 1
+#data/Alvarez_surface_deg8_k2_D8_41K.xyz - - - 0 8 2 0.025 0.02 Y N N 60 1
+
+# With pre-computed tangent spaces
+#data/test.pwt - - - 0 4 2 0.01 0.01 N N N 500000 1
+#data/Alvarez_variete_k2_D4_30000p.xyz - - - 0 4 2 0.01 0.01 Y N N 500000 1
+#data/Alvarez_variete_k2_D4_30000p_with_TSB.pwt - - - 0 4 2 0.01 0.01 Y N N 500000 1
+
+#---------------------------------------------------------------------- 3D meshes -----------------------------------------------------------------------
+#data/buddha_100kv.xyz - - - 0 3 2 0.005 0.005 Y N N 3 1
+#data/fandisk.xyz - - - 0 3 2 0.01 0.01 Y N N 3 1
+#data/fertility.xyz - - - 0 3 2 0.4 0.4 Y N N 3 1
+#data/bunny.xyz - - - 0 3 2 0.0006 0.0003 Y N N 3000 1
+#data/blob.xyz - - - 0 3 2 0.01 0.01 Y N N 3 1
+#data/3holes.xyz - - - 0 3 2 0.01 0.01 Y N N 3 1
+#data/785_hand_2500v.xyz - - - 0 3 2 0.01 0.01 Y N N 3 1
+#data/785_hand_50kv.xyz - - - 0 3 2 0.01 0.01 Y N N 3 1
+#data/bumpy_sphere.xyz - - - 0 3 2 0.01 0.01 Y N N 3 1
+#D:\INRIA\Data\_Models\Pointclouds\ajax_jotero.xyz - - - 0 3 2 0.01 0.01 Y N N 3 1
+#D:\INRIA\Data\_Models\Pointclouds\house.xyz - - - 0 3 2 0.01 0.01 Y N N 3 1
+#D:\INRIA\Data\_Models\Pointclouds\lucy_14M.xyz - - - 0 3 2 0.6 0.3 Y N N 3 1
+
+#----------------------------------------------------------- Generated point sets -----------------------------------------------------------------------
+#generate_sphere_d 3 - - 4 3 2 0.05 0.05 Y N N 3000 1
+#generate_sphere_d 3 - - 30000 2 1 0.005 0.005 Y N N 3000 1
+#generate_sphere_d 1 - - 500000 3 2 0.005 0.005 Y N N 3000 1
+#generate_sphere_d 3 - - 30000 4 3 0.05 0.05 Y N N 3000 1
+#generate_sphere_d 3 0 - 300 3 2 0.005 0.005 Y N N 60 1
+#generate_sphere_d 3 4 - 3000 3 2 0.005 0.005 Y N N 60 1
+#generate_sphere_d 3 7 - 3000 3 2 0.005 0.005 Y N N 60 1
+#generate_torus_3D 2 1 N 300 3 2 0.05 0.05 Y N N 600 1
+#generate_torus_d N - - 200 4 2 0.05 0.05 Y N N 600 1
+
+#generate_torus_d Y - - 100 6 3 0.1 0.19 Y N N 600 1
+#generate_torus_d Y - - 1000 6 3 0. 0.19 Y N N 600 1
+#generate_torus_d Y - - 10000 6 3 0. 0.19 Y N N 600 1
+#generate_torus_d Y - - 100000 6 3 0. 0.19 Y N N 600 1
+#generate_plane - - - 30000 3 2 0.005 0.005 Y N N 3000 1
+#generate_moment_curve 0 1 - 30000 6 1 0.005 0.005 Y N N 60 1
+#generate_klein_bottle_4D 4 3 - 700 4 2 0.05 0.05 Y N N 500 20
+#generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 0.05 Y N N 600 1
+#generate_klein_bottle_4D 8 5 - 5000 4 2 0.2 0.2 Y N N 60 1 #Takes forever
+#data/sparsified/Flat_torus_195p_sparsified_0.05_from_200p.xyz N - - 0 4 2 -1 0.2 Y N N 600 1
+
+#----------------------------------------------------------- Performance testing ------------------------------------------------------------------------
+# TC: 5.55 / 1st fix step : 0.2
+#data/fertility.xyz - - - 0 3 2 0.1 0.1 Y N N 10 1
+
+#---------------------------------------------------------- 04/04/2016 - for stats ----------------------------------------------------------
+
+#generate_torus_3D 2 1 N 5000 3 2 0.05 0.05 Y N N 120 1
+#generate_torus_d N - - 500 4 2 0.05 0.05 Y N N 120 1
+#data/Alvarez_variete_k2_D8_900k_2x2.xyz - - - 0 8 2 0.005 0.005 Y N N 120 1
+#data/Alvarez_surface_deg3_k2_D8_902K.xyz - - - 0 8 2 0.01 0.01 Y N N 120 1
+#data/Alvarez_surface_deg7_k2_D8_48K.xyz - - - 0 8 2 0.02 0.02 Y N N 600 10
+#data/Alvarez_surface_deg8_k2_D8_41K.xyz - - - 0 8 2 0.02 0.02 Y N N 120 1
+#data/Alvarez_surface_deg10_k2_D8_41K.xyz - - - 0 8 2 0.02 0.02 Y N N 120 1
+#generate_torus_d N - - 200000 6 3 0.05 0.05 Y N N 1200 1
+
+#---------------------------------------------------------- 14/04/2016 - stats about noise ----------------------------------------------------------
+
+#generate_torus_d Y 0 - 1000 4 2 0.05 0.19 Y N N 120 4
+#generate_torus_d Y 1 - 1000 4 2 0.05 0.19 Y N N 120 4
+#generate_torus_d Y 2 - 1000 4 2 0.05 0.19 Y N N 120 4
+#generate_torus_d Y 3 - 1000 4 2 0.05 0.19 Y N N 120 4
+#generate_torus_d Y 4 - 1000 4 2 0.05 0.19 Y N N 120 4
+#generate_torus_d Y 5 - 1000 4 2 0.05 0.19 Y N N 120 4
+#generate_torus_d Y 6 - 1000 4 2 0.05 0.19 Y N N 120 4
+#generate_torus_d Y 7 - 1000 4 2 0.05 0.19 Y N N 120 4
+#generate_torus_d Y 8 - 1000 4 2 0.05 0.19 Y N N 120 4
+#generate_torus_d Y 9 - 1000 4 2 0.05 0.19 Y N N 120 4
+#generate_torus_d Y 10 - 1000 4 2 0.05 0.19 Y N N 120 4
+
+#generate_sphere_d 3 0 - 1000 4 3 0.05 0.05 Y N N 120 4
+#generate_sphere_d 3 1 - 1000 4 3 0.05 0.05 Y N N 120 4
+#generate_sphere_d 3 2 - 1000 4 3 0.05 0.05 Y N N 120 4
+#generate_sphere_d 3 3 - 1000 4 3 0.05 0.05 Y N N 120 4
+#generate_sphere_d 3 4 - 1000 4 3 0.05 0.05 Y N N 120 4
+#generate_sphere_d 3 5 - 1000 4 3 0.05 0.05 Y N N 120 4
+#generate_sphere_d 3 6 - 1000 4 3 0.05 0.05 Y N N 120 4
+#generate_sphere_d 3 7 - 1000 4 3 0.05 0.05 Y N N 120 4
+#generate_sphere_d 3 8 - 1000 4 3 0.05 0.05 Y N N 120 4
+#generate_sphere_d 3 9 - 1000 4 3 0.05 0.05 Y N N 120 4
+#generate_sphere_d 3 10 - 1000 4 3 0.05 0.05 Y N N 120 4
+
+#generate_klein_bottle_4D 4 3 0 5000 4 2 0.05 0.05 Y N N 120 4
+#generate_klein_bottle_4D 4 3 0.01 5000 4 2 0.05 0.05 Y N N 120 4
+#generate_klein_bottle_4D 4 3 0.02 5000 4 2 0.05 0.05 Y N N 120 4
+#generate_klein_bottle_4D 4 3 0.03 5000 4 2 0.05 0.05 Y N N 120 4
+#generate_klein_bottle_4D 4 3 0.04 5000 4 2 0.05 0.05 Y N N 120 4
+#generate_klein_bottle_4D 4 3 0.05 5000 4 2 0.05 0.05 Y N N 120 4
+#generate_klein_bottle_4D 4 3 0.06 5000 4 2 0.05 0.05 Y N N 120 4
+#generate_klein_bottle_4D 4 3 0.07 5000 4 2 0.05 0.05 Y N N 120 4
+
+#---------------------------------------------------------- 04/2016 - stats with different perturb techniques ----------------------------------------------------------
+
+# Tangential translation
+#data/SO3_50000.xyz - - - 0 9 3 0 0.05 Y N N 500 10
+#data/Alvarez_surface_deg7_k2_D8_48K.xyz - - - 0 8 2 0.02 0.01 Y N N 120 10
+#generate_klein_bottle_4D 4 3 0 5000 4 2 0.05 0.05 Y N N 120 10
+#generate_torus_d Y 0 - 1000 4 2 0.05 0.19 Y N N 120 10
+#generate_sphere_d 3 1 - 1000 4 3 0.05 0.05 Y N N 120 10
+
+# Weight
+#data/SO3_50000.xyz - - - 0 9 3 0.1 0.05 Y N N 500 10
+#data/Alvarez_surface_deg7_k2_D8_48K.xyz - - - 0 8 2 0.02 0.01 Y N N 120 10
+#generate_klein_bottle_4D 4 3 0 5000 4 2 0.05 0.025 Y N N 20000 10
+#generate_torus_d Y 0 - 1000 4 2 0.05 0.025 Y N N 120 10
+#generate_sphere_d 3 1 - 1000 4 3 0.05 0.025 Y N N 12000 10 \ No newline at end of file
diff --git a/src/Tangential_complex/benchmark/benchmark_tc.cpp b/src/Tangential_complex/benchmark/benchmark_tc.cpp
new file mode 100644
index 00000000..943fcb54
--- /dev/null
+++ b/src/Tangential_complex/benchmark/benchmark_tc.cpp
@@ -0,0 +1,785 @@
+/******************************************************************************
+This benchmark allows to compute the Tangential Complex from input files or
+generated point sets.
+
+It reads the benchmark_script.txt file (located in the same folder as this
+file) and compute one or several complexes for each line. Unless TC_NO_EXPORT
+is defined, each complex is exported as an OFF file and/or as a RIB file
+(RenderMan). In addition an XML file is created at each run of the benchmark.
+It contains statistics about the complexes that were created. This XML file
+can be processed in Excel, for example.
+ ******************************************************************************/
+
+// Without TBB_USE_THREADING_TOOL Intel Inspector XE will report false positives in Intel TBB
+// (http://software.intel.com/en-us/articles/compiler-settings-for-threading-error-analysis-in-intel-inspector-xe/)
+#ifdef _DEBUG
+#define TBB_USE_THREADING_TOOL
+#endif
+
+#include <cstddef>
+
+//#define GUDHI_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM
+//#define TC_INPUT_STRIDES 3 // only take one point every TC_INPUT_STRIDES points
+#define TC_NO_EXPORT // do not output OFF files
+//#define TC_EXPORT_TO_RIB //
+//#define GUDHI_TC_EXPORT_SPARSIFIED_POINT_SET
+//#define GUDHI_TC_EXPORT_ALL_COORDS_IN_OFF
+
+const std::size_t ONLY_LOAD_THE_FIRST_N_POINTS = 20000000;
+
+#include <gudhi/Debug_utils.h>
+#include <gudhi/Clock.h>
+#include <gudhi/Tangential_complex.h>
+#include <gudhi/sparsify_point_set.h>
+#include <gudhi/random_point_generators.h>
+#include <gudhi/Tangential_complex/utilities.h>
+
+#include <CGAL/assertions_behaviour.h>
+#include <CGAL/Epick_d.h>
+#include <CGAL/Random.h>
+
+#include <boost/algorithm/string/replace.hpp>
+#include <boost/algorithm/string/trim_all.hpp>
+#include <boost/range/adaptor/strided.hpp>
+
+#include <cstdlib>
+#include <ctime>
+#include <fstream>
+#include <cmath> // for std::sqrt
+
+#ifdef GUDHI_USE_TBB
+#include <tbb/task_scheduler_init.h>
+#endif
+#include "XML_exporter.h"
+#include "RIB_exporter.h"
+#define GUDHI_TC_EXPORT_PERFORMANCE_DATA
+#define GUDHI_TC_SET_PERFORMANCE_DATA(value_name, value) \
+ XML_perf_data::set(value_name, value);
+
+
+namespace subsampl = Gudhi::subsampling;
+namespace tc = Gudhi::tangential_complex;
+
+const char * const BENCHMARK_SCRIPT_FILENAME = "benchmark_script.txt";
+
+typedef CGAL::Epick_d<CGAL::Dynamic_dimension_tag> Kernel;
+typedef Kernel::FT FT;
+typedef Kernel::Point_d Point;
+typedef Kernel::Vector_d Vector;
+typedef tc::Tangential_complex<
+Kernel, CGAL::Dynamic_dimension_tag,
+CGAL::Parallel_tag> TC;
+typedef TC::Simplex Simplex;
+typedef TC::Simplex_set Simplex_set;
+
+class XML_perf_data {
+ public:
+ typedef Streaming_XML_exporter<std::string> XML_exporter;
+
+ XML_perf_data(const std::string &filename)
+ : m_xml(filename, "ContainerPerformance", "Perf",
+ construct_subelements_names()) { }
+
+ virtual ~XML_perf_data() { }
+
+ static XML_perf_data &get() {
+ static XML_perf_data singleton(build_filename());
+ return singleton;
+ }
+
+ template <typename Value_type>
+ static void set(const std::string &name, Value_type value) {
+ get().set_data(name, value);
+ }
+
+ static void commit() {
+ get().commit_current_element();
+ }
+
+ protected:
+
+ static std::string build_filename() {
+ std::stringstream sstr;
+ sstr << "perf_logs/Performance_log_" << time(0) << ".xml";
+ return sstr.str();
+ }
+
+ static std::vector<std::string> construct_subelements_names() {
+ std::vector<std::string> subelements;
+ subelements.push_back("Input");
+ subelements.push_back("Param1");
+ subelements.push_back("Param2");
+ subelements.push_back("Param3");
+ subelements.push_back("Intrinsic_dim");
+ subelements.push_back("Ambient_dim");
+ subelements.push_back("Num_threads");
+ subelements.push_back("Sparsity");
+ subelements.push_back("Max_perturb");
+ subelements.push_back("Num_points_in_input");
+ subelements.push_back("Num_points");
+ subelements.push_back("Perturb_technique");
+ subelements.push_back("Perturb_which_points");
+ subelements.push_back("Initial_num_inconsistent_local_tr");
+ subelements.push_back("Best_num_inconsistent_local_tr");
+ subelements.push_back("Final_num_inconsistent_local_tr");
+ subelements.push_back("Init_time");
+ subelements.push_back("Comput_time");
+ subelements.push_back("Perturb_successful");
+ subelements.push_back("Perturb_time");
+ subelements.push_back("Perturb_steps");
+ subelements.push_back("Result_pure_pseudomanifold");
+ subelements.push_back("Result_num_wrong_dim_simplices");
+ subelements.push_back("Result_num_wrong_number_of_cofaces");
+ subelements.push_back("Result_num_unconnected_stars");
+ subelements.push_back("Info");
+
+ return subelements;
+ }
+
+ void set_data(const std::string &name, const std::string &value) {
+ m_current_element[name] = value;
+ }
+
+ template <typename Value_type>
+ void set_data(const std::string &name, Value_type value) {
+ std::stringstream sstr;
+ sstr << value;
+ set_data(name, sstr.str());
+ }
+
+ void commit_current_element() {
+ m_xml.add_element(m_current_element);
+ m_current_element.clear();
+ }
+
+ XML_exporter m_xml;
+ XML_exporter::Element_with_map m_current_element;
+};
+
+template<
+typename Kernel, typename OutputIteratorPoints>
+bool load_points_from_file(
+ const std::string &filename,
+ OutputIteratorPoints points,
+ std::size_t only_first_n_points = std::numeric_limits<std::size_t>::max()) {
+ typedef typename Kernel::Point_d Point;
+
+ std::ifstream in(filename);
+ if (!in.is_open()) {
+ std::cerr << "Could not open '" << filename << "'" << std::endl;
+ return false;
+ }
+
+ Kernel k;
+ Point p;
+ int num_ppints;
+ in >> num_ppints;
+
+ std::size_t i = 0;
+ while (i < only_first_n_points && in >> p) {
+ *points++ = p;
+ ++i;
+ }
+
+#ifdef DEBUG_TRACES
+ std::cerr << "'" << filename << "' loaded." << std::endl;
+#endif
+
+ return true;
+}
+
+template<
+typename Kernel, typename Tangent_space_basis,
+typename OutputIteratorPoints, typename OutputIteratorTS>
+bool load_points_and_tangent_space_basis_from_file(
+ const std::string &filename,
+ OutputIteratorPoints points,
+ OutputIteratorTS tangent_spaces,
+ int intrinsic_dim,
+ std::size_t only_first_n_points = std::numeric_limits<std::size_t>::max()) {
+ typedef typename Kernel::Point_d Point;
+ typedef typename Kernel::Vector_d Vector;
+
+ std::ifstream in(filename);
+ if (!in.is_open()) {
+ std::cerr << "Could not open '" << filename << "'" << std::endl;
+ return false;
+ }
+
+ Kernel k;
+ Point p;
+ int num_ppints;
+ in >> num_ppints;
+
+ std::size_t i = 0;
+ while (i < only_first_n_points && in >> p) {
+ *points++ = p;
+
+ Tangent_space_basis tsb(i);
+ for (int d = 0; d < intrinsic_dim; ++d) {
+ Vector v;
+ in >> v;
+ tsb.push_back(tc::internal::normalize_vector(v, k));
+ }
+ *tangent_spaces++ = tsb;
+ ++i;
+ }
+
+#ifdef DEBUG_TRACES
+ std::cerr << "'" << filename << "' loaded." << std::endl;
+#endif
+
+ return true;
+}
+
+// color_inconsistencies: only works if p_complex = NULL
+template <typename TC>
+bool export_to_off(
+ TC const& tc,
+ std::string const& input_name_stripped,
+ std::string const& suffix,
+ bool color_inconsistencies = false,
+ typename TC::Simplicial_complex const* p_complex = NULL,
+ 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) {
+#ifdef TC_NO_EXPORT
+ return true;
+#endif
+
+ CGAL::Identity<Point> proj_functor;
+
+ if (tc.intrinsic_dimension() <= 3) {
+ std::stringstream output_filename;
+ output_filename << "output/" << input_name_stripped << "_"
+ << tc.intrinsic_dimension() << "_in_R"
+ << tc.ambient_dimension() << "_"
+ << tc.number_of_vertices() << "v"
+ << suffix << ".off";
+ std::ofstream off_stream(output_filename.str().c_str());
+
+ if (p_complex) {
+#ifndef TC_NO_EXPORT
+ tc.export_to_off(
+ *p_complex, off_stream,
+ p_simpl_to_color_in_red,
+ p_simpl_to_color_in_green,
+ p_simpl_to_color_in_blue,
+ proj_functor);
+#endif
+ } else {
+ tc.export_to_off(
+ off_stream, color_inconsistencies,
+ p_simpl_to_color_in_red,
+ p_simpl_to_color_in_green,
+ p_simpl_to_color_in_blue,
+ NULL,
+ proj_functor);
+ }
+ return true;
+ }
+ return false;
+}
+
+void make_tc(std::vector<Point> &points,
+ TC::TS_container const& tangent_spaces, // can be empty
+ int intrinsic_dim,
+ double sparsity = 0.01,
+ double max_perturb = 0.005,
+ bool perturb = true,
+ bool add_high_dim_simpl = false,
+ bool collapse = false,
+ double time_limit_for_perturb = 0.,
+ const char *input_name = "tc") {
+ Kernel k;
+
+ if (sparsity > 0. && !tangent_spaces.empty()) {
+ std::cerr << "Error: cannot sparsify point set with pre-computed normals.\n";
+ return;
+ }
+
+ //===========================================================================
+ // Init
+ //===========================================================================
+ Gudhi::Clock t;
+
+ // Get input_name_stripped
+ std::string input_name_stripped(input_name);
+ size_t slash_index = input_name_stripped.find_last_of('/');
+ if (slash_index == std::string::npos)
+ slash_index = input_name_stripped.find_last_of('\\');
+ if (slash_index == std::string::npos)
+ slash_index = 0;
+ else
+ ++slash_index;
+ input_name_stripped = input_name_stripped.substr(
+ slash_index, input_name_stripped.find_last_of('.') - slash_index);
+
+ GUDHI_TC_SET_PERFORMANCE_DATA("Num_points_in_input", points.size());
+
+#ifdef GUDHI_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM
+ std::vector<Point> points_not_sparse = points;
+#endif
+
+ //===========================================================================
+ // Sparsify point set if requested
+ //===========================================================================
+ if (sparsity > 0.) {
+ std::size_t num_points_before = points.size();
+ std::vector<Point> sparsified_points;
+ subsampl::sparsify_point_set(k, points, sparsity*sparsity,
+ std::back_inserter(sparsified_points));
+ sparsified_points.swap(points);
+ std::cerr << "Number of points before/after sparsification: "
+ << num_points_before << " / " << points.size() << "\n";
+
+#ifdef GUDHI_TC_EXPORT_SPARSIFIED_POINT_SET
+ std::ofstream ps_stream("output/sparsified_point_set.txt");
+ tc::internal::export_point_set(k, points, ps_stream);
+#endif
+ }
+
+ GUDHI_TC_SET_PERFORMANCE_DATA("Sparsity", sparsity);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Max_perturb", max_perturb);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Num_points", points.size());
+
+ //===========================================================================
+ // Compute Tangential Complex
+ //===========================================================================
+
+ TC tc(
+ points,
+ intrinsic_dim,
+#ifdef GUDHI_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM
+ points_not_sparse.begin(), points_not_sparse.end(),
+#endif
+ k);
+
+ if (!tangent_spaces.empty()) {
+ tc.set_tangent_planes(tangent_spaces);
+ }
+
+ t.end();
+ double init_time = t.num_seconds();
+
+ t.begin();
+ tc.compute_tangential_complex();
+ t.end();
+ double computation_time = t.num_seconds();
+
+ //===========================================================================
+ // Export to OFF
+ //===========================================================================
+
+ // Create complex
+ int max_dim = -1;
+ TC::Simplicial_complex complex;
+ Simplex_set inconsistent_simplices;
+ max_dim = tc.create_complex(complex, true, false, 2, &inconsistent_simplices);
+
+ // TODO(CJ): TEST
+ Gudhi::Simplex_tree<> stree;
+ tc.create_complex(stree, true, false);
+ // std::cerr << stree;
+
+ t.begin();
+ bool ret = export_to_off(
+ tc, input_name_stripped, "_INITIAL_TC", true,
+ &complex, &inconsistent_simplices);
+ t.end();
+ double export_before_time = (ret ? t.num_seconds() : -1);
+
+ unsigned int num_perturb_steps = 0;
+ double perturb_time = -1;
+ double export_after_perturb_time = -1.;
+ bool perturb_success = false;
+ if (perturb) {
+ //=========================================================================
+ // Try to fix inconsistencies by perturbing points
+ //=========================================================================
+ t.begin();
+ auto fix_result =
+ tc.fix_inconsistencies_using_perturbation(max_perturb, time_limit_for_perturb);
+ t.end();
+ perturb_time = t.num_seconds();
+
+ perturb_success = fix_result.success;
+ GUDHI_TC_SET_PERFORMANCE_DATA("Initial_num_inconsistent_local_tr",
+ fix_result.initial_num_inconsistent_stars);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Best_num_inconsistent_local_tr",
+ fix_result.best_num_inconsistent_stars);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Final_num_inconsistent_local_tr",
+ fix_result.final_num_inconsistent_stars);
+
+ //=========================================================================
+ // Export to OFF
+ //=========================================================================
+
+ // Re-build the complex
+ Simplex_set inconsistent_simplices;
+ max_dim = tc.create_complex(complex, true, false, 2, &inconsistent_simplices);
+
+ t.begin();
+ bool exported = export_to_off(
+ tc, input_name_stripped, "_AFTER_FIX", true, &complex,
+ &inconsistent_simplices);
+ t.end();
+ export_after_perturb_time = (exported ? t.num_seconds() : -1);
+
+ //std::string fn = "output/inc_stars/";
+ //fn += input_name_stripped;
+ //tc.export_inconsistent_stars_to_OFF_files(fn);
+
+#if !defined(TC_NO_EXPORT) && defined(TC_EXPORT_TO_RIB)
+ std::ofstream rib(std::string("output/") + input_name_stripped + ".rib");
+ RIB_exporter<TC::Points, TC::Simplicial_complex::Simplex_set> rib_exporter(
+ tc.points(),
+ complex.simplex_range(),
+ rib,
+ input_name_stripped + ".tif",
+ false, // is_preview
+ std::make_tuple(2, 4, 6),
+ 1600, 503 // resolution
+ );
+ rib_exporter.write_file();
+
+ std::ofstream rib_LQ(std::string("output/") + input_name_stripped + "_LQ.rib");
+ RIB_exporter<TC::Points, TC::Simplicial_complex::Simplex_set> rib_exporter_LQ(
+ tc.points(),
+ complex.simplex_range(),
+ rib_LQ,
+ input_name_stripped + "_LQ.tif",
+ true, // is_preview
+ std::make_tuple(0, 4, 5)
+ );
+ rib_exporter_LQ.write_file();
+#endif
+ } else {
+ GUDHI_TC_SET_PERFORMANCE_DATA("Initial_num_inconsistent_local_tr", "N/A");
+ GUDHI_TC_SET_PERFORMANCE_DATA("Best_num_inconsistent_local_tr", "N/A");
+ GUDHI_TC_SET_PERFORMANCE_DATA("Final_num_inconsistent_local_tr", "N/A");
+ }
+
+ max_dim = tc.create_complex(complex, true, false, 2);
+
+ complex.display_stats();
+
+ if (intrinsic_dim == 2)
+ complex.euler_characteristic(true);
+
+ //===========================================================================
+ // Collapse
+ //===========================================================================
+ if (collapse) {
+ complex.collapse(max_dim);
+ complex.display_stats();
+ }
+
+ //===========================================================================
+ // Is the result a pure pseudomanifold?
+ //===========================================================================
+ std::size_t num_wrong_dim_simplices,
+ num_wrong_number_of_cofaces,
+ num_unconnected_stars;
+ Simplex_set wrong_dim_simplices;
+ Simplex_set wrong_number_of_cofaces_simplices;
+ Simplex_set unconnected_stars_simplices;
+ bool is_pure_pseudomanifold = complex.is_pure_pseudomanifold(
+ intrinsic_dim, tc.number_of_vertices(),
+ false, // do NOT allow borders
+ false, 1,
+ &num_wrong_dim_simplices, &num_wrong_number_of_cofaces,
+ &num_unconnected_stars,
+ &wrong_dim_simplices, &wrong_number_of_cofaces_simplices,
+ &unconnected_stars_simplices);
+
+ //===========================================================================
+ // Export to OFF
+ //===========================================================================
+
+ double export_after_collapse_time = -1.;
+ if (collapse) {
+ t.begin();
+ bool exported = export_to_off(
+ tc, input_name_stripped, "_AFTER_COLLAPSE", false, &complex,
+ &wrong_dim_simplices, &wrong_number_of_cofaces_simplices,
+ &unconnected_stars_simplices);
+ t.end();
+ std::cerr
+ << " OFF colors:\n"
+ << " * Red: wrong dim simplices\n"
+ << " * Green: wrong number of cofaces simplices\n"
+ << " * Blue: not-connected stars\n";
+ export_after_collapse_time = (exported ? t.num_seconds() : -1.);
+ }
+
+ //===========================================================================
+ // Display info
+ //===========================================================================
+
+ std::cerr
+ << "\n================================================\n"
+ << "Number of vertices: " << tc.number_of_vertices() << "\n"
+ << "Computation times (seconds): \n"
+ << " * Tangential complex: " << init_time + computation_time << "\n"
+ << " - Init + kd-tree = " << init_time << "\n"
+ << " - TC computation = " << computation_time << "\n"
+ << " * Export to OFF (before perturb): " << export_before_time << "\n"
+ << " * Fix inconsistencies 1: " << perturb_time
+ << " (" << num_perturb_steps << " steps) ==> "
+ << (perturb_success ? "FIXED" : "NOT fixed") << "\n"
+ << " * Export to OFF (after perturb): " << export_after_perturb_time << "\n"
+ << " * Export to OFF (after collapse): "
+ << export_after_collapse_time << "\n"
+ << "================================================\n";
+
+ //===========================================================================
+ // Export info
+ //===========================================================================
+ GUDHI_TC_SET_PERFORMANCE_DATA("Init_time", init_time);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Comput_time", computation_time);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Perturb_successful",
+ (perturb_success ? 1 : 0));
+ GUDHI_TC_SET_PERFORMANCE_DATA("Perturb_time", perturb_time);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Perturb_steps", num_perturb_steps);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Result_pure_pseudomanifold",
+ (is_pure_pseudomanifold ? 1 : 0));
+ GUDHI_TC_SET_PERFORMANCE_DATA("Result_num_wrong_dim_simplices",
+ num_wrong_dim_simplices);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Result_num_wrong_number_of_cofaces",
+ num_wrong_number_of_cofaces);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Result_num_unconnected_stars",
+ num_unconnected_stars);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Info", "");
+}
+
+int main() {
+ CGAL::set_error_behaviour(CGAL::ABORT);
+
+#ifdef GUDHI_USE_TBB
+#ifdef _DEBUG
+ int num_threads = 1;
+#else
+ int num_threads = tbb::task_scheduler_init::default_num_threads() - 4;
+#endif
+#endif
+
+ unsigned int seed = static_cast<unsigned int> (time(NULL));
+ CGAL::default_random = CGAL::Random(seed); // TODO(CJ): use set_default_random
+ std::cerr << "Random seed = " << seed << "\n";
+
+ std::ifstream script_file;
+ script_file.open(BENCHMARK_SCRIPT_FILENAME);
+ // Script?
+ // Script file format: each line gives
+ // - Filename (point set) or "generate_XXX" (point set generation)
+ // - Ambient dim
+ // - Intrinsic dim
+ // - Number of iterations with these parameters
+ if (script_file.is_open()) {
+ int i = 1;
+#ifdef GUDHI_USE_TBB
+#ifdef BENCHMARK_WITH_1_TO_MAX_THREADS
+ for (num_threads = 1;
+ num_threads <= tbb::task_scheduler_init::default_num_threads();
+ ++num_threads)
+#endif
+#endif
+ /*for (Concurrent_mesher_config::get().num_work_items_per_batch = 5 ;
+ Concurrent_mesher_config::get().num_work_items_per_batch < 100 ;
+ Concurrent_mesher_config::get().num_work_items_per_batch += 5)*/ {
+#ifdef GUDHI_USE_TBB
+ tbb::task_scheduler_init init(
+ num_threads > 0 ? num_threads : tbb::task_scheduler_init::automatic);
+#endif
+
+ std::cerr << "Script file '" << BENCHMARK_SCRIPT_FILENAME << "' found.\n";
+ script_file.seekg(0);
+ while (script_file.good()) {
+ std::string line;
+ std::getline(script_file, line);
+ if (line.size() > 1 && line[0] != '#') {
+ boost::replace_all(line, "\t", " ");
+ boost::trim_all(line);
+ std::cerr << "\n\n";
+ std::cerr << "*****************************************\n";
+ std::cerr << "******* " << line << "\n";
+ std::cerr << "*****************************************\n";
+ std::stringstream sstr(line);
+
+ std::string input;
+ std::string param1;
+ std::string param2;
+ std::string param3;
+ std::size_t num_points;
+ int ambient_dim;
+ int intrinsic_dim;
+ double sparsity;
+ double max_perturb;
+ char perturb, add_high_dim_simpl, collapse;
+ double time_limit_for_perturb;
+ int num_iteration;
+ sstr >> input;
+ sstr >> param1;
+ sstr >> param2;
+ sstr >> param3;
+ sstr >> num_points;
+ sstr >> ambient_dim;
+ sstr >> intrinsic_dim;
+ sstr >> sparsity;
+ sstr >> max_perturb;
+ sstr >> perturb;
+ sstr >> add_high_dim_simpl;
+ sstr >> collapse;
+ sstr >> time_limit_for_perturb;
+ sstr >> num_iteration;
+
+ for (int j = 0; j < num_iteration; ++j) {
+ std::string input_stripped = input;
+ size_t slash_index = input_stripped.find_last_of('/');
+ if (slash_index == std::string::npos)
+ slash_index = input_stripped.find_last_of('\\');
+ if (slash_index == std::string::npos)
+ slash_index = 0;
+ else
+ ++slash_index;
+ input_stripped = input_stripped.substr(
+ slash_index, input_stripped.find_last_of('.') - slash_index);
+
+ GUDHI_TC_SET_PERFORMANCE_DATA("Input", input_stripped);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Param1", param1);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Param2", param2);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Param3", param3);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Ambient_dim", ambient_dim);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Intrinsic_dim", intrinsic_dim);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Perturb_technique", "Tangential_translation");
+ GUDHI_TC_SET_PERFORMANCE_DATA("Perturb_which_points", "Center_vertex");
+
+#ifdef GUDHI_USE_TBB
+ GUDHI_TC_SET_PERFORMANCE_DATA(
+ "Num_threads",
+ (num_threads == -1 ? tbb::task_scheduler_init::default_num_threads() : num_threads));
+#else
+ GUDHI_TC_SET_PERFORMANCE_DATA("Num_threads", "N/A");
+#endif
+
+ std::cerr << "\nTC #" << i << "...\n";
+
+#ifdef GUDHI_TC_PROFILING
+ Gudhi::Clock t_gen;
+#endif
+
+ std::vector<Point> points;
+ TC::TS_container tangent_spaces;
+
+ if (input == "generate_moment_curve") {
+ points = Gudhi::generate_points_on_moment_curve<Kernel>(
+ num_points, ambient_dim,
+ std::atof(param1.c_str()), std::atof(param2.c_str()));
+ } else if (input == "generate_plane") {
+ points = Gudhi::generate_points_on_plane<Kernel>(
+ num_points, intrinsic_dim, ambient_dim);
+ } else if (input == "generate_sphere_d") {
+ points = Gudhi::generate_points_on_sphere_d<Kernel>(
+ num_points, ambient_dim,
+ std::atof(param1.c_str()), // radius
+ std::atof(param2.c_str())); // radius_noise_percentage
+ } else if (input == "generate_two_spheres_d") {
+ points = Gudhi::generate_points_on_two_spheres_d<Kernel>(
+ num_points, ambient_dim,
+ std::atof(param1.c_str()),
+ std::atof(param2.c_str()),
+ std::atof(param3.c_str()));
+ } else if (input == "generate_3sphere_and_circle_d") {
+ GUDHI_CHECK(intrinsic_dim == 3,
+ std::logic_error("Intrinsic dim should be 3"));
+ GUDHI_CHECK(ambient_dim == 5,
+ std::logic_error("Ambient dim should be 5"));
+ points = Gudhi::generate_points_on_3sphere_and_circle<Kernel>(
+ num_points,
+ std::atof(param1.c_str()));
+ } else if (input == "generate_torus_3D") {
+ points = Gudhi::generate_points_on_torus_3D<Kernel>(
+ num_points,
+ std::atof(param1.c_str()),
+ std::atof(param2.c_str()),
+ param3 == "Y");
+ } else if (input == "generate_torus_d") {
+ points = Gudhi::generate_points_on_torus_d<Kernel>(
+ num_points,
+ intrinsic_dim,
+ param1 == "Y", // uniform
+ std::atof(param2.c_str())); // radius_noise_percentage
+ } else if (input == "generate_klein_bottle_3D") {
+ points = Gudhi::generate_points_on_klein_bottle_3D<Kernel>(
+ num_points,
+ std::atof(param1.c_str()), std::atof(param2.c_str()));
+ } else if (input == "generate_klein_bottle_4D") {
+ points = Gudhi::generate_points_on_klein_bottle_4D<Kernel>(
+ num_points,
+ std::atof(param1.c_str()), std::atof(param2.c_str()),
+ std::atof(param3.c_str())); // noise
+ } else if (input == "generate_klein_bottle_variant_5D") {
+ points = Gudhi::generate_points_on_klein_bottle_variant_5D<Kernel>(
+ num_points,
+ std::atof(param1.c_str()), std::atof(param2.c_str()));
+ } else {
+ // Contains tangent space basis
+ if (input.substr(input.size() - 3) == "pwt") {
+ load_points_and_tangent_space_basis_from_file
+ <Kernel, typename TC::Tangent_space_basis > (
+ input, std::back_inserter(points),
+ std::back_inserter(tangent_spaces),
+ intrinsic_dim,
+ ONLY_LOAD_THE_FIRST_N_POINTS);
+ } else {
+ load_points_from_file<Kernel>(
+ input, std::back_inserter(points),
+ ONLY_LOAD_THE_FIRST_N_POINTS);
+ }
+ }
+
+#ifdef GUDHI_TC_PROFILING
+ t_gen.end();
+ std::cerr << "Point set generated/loaded in " << t_gen.num_seconds()
+ << " seconds.\n";
+#endif
+
+ if (!points.empty()) {
+#if defined(TC_INPUT_STRIDES) && TC_INPUT_STRIDES > 1
+ auto p = points | boost::adaptors::strided(TC_INPUT_STRIDES);
+ std::vector<Point> points(p.begin(), p.end());
+ std::cerr << "****************************************\n"
+ << "WARNING: taking 1 point every " << TC_INPUT_STRIDES
+ << " points.\n"
+ << "****************************************\n";
+#endif
+
+ make_tc(points, tangent_spaces, intrinsic_dim,
+ sparsity, max_perturb,
+ perturb == 'Y', add_high_dim_simpl == 'Y', collapse == 'Y',
+ time_limit_for_perturb, input.c_str());
+
+ std::cerr << "TC #" << i++ << " done.\n";
+ std::cerr << "\n---------------------------------\n";
+ } else {
+ std::cerr << "TC #" << i++ << ": no points loaded.\n";
+ }
+
+ XML_perf_data::commit();
+ }
+ }
+ }
+ script_file.seekg(0);
+ script_file.clear();
+ }
+
+ script_file.close();
+ } // Or not script?
+ else {
+ std::cerr << "Script file '" << BENCHMARK_SCRIPT_FILENAME << "' NOT found.\n";
+ }
+
+ // system("pause");
+ return 0;
+}
diff --git a/src/Tangential_complex/doc/Intro_tangential_complex.h b/src/Tangential_complex/doc/Intro_tangential_complex.h
new file mode 100644
index 00000000..3d687c1d
--- /dev/null
+++ b/src/Tangential_complex/doc/Intro_tangential_complex.h
@@ -0,0 +1,119 @@
+/* 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 DOC_TANGENTIAL_COMPLEX_INTRO_TANGENTIAL_COMPLEX_H_
+#define DOC_TANGENTIAL_COMPLEX_INTRO_TANGENTIAL_COMPLEX_H_
+
+// needs namespaces for Doxygen to link on classes
+namespace Gudhi {
+namespace tangential_complex {
+
+/** \defgroup tangential_complex Tangential complex
+
+\author Cl&eacute;ment Jamin
+
+@{
+
+\section tangentialdefinition Definition
+
+A Tangential Delaunay complex is a <a target="_blank" href="https://en.wikipedia.org/wiki/Simplicial_complex">simplicial complex</a>
+designed to reconstruct a \f$k\f$-dimensional smooth manifold embedded in \f$d\f$-dimensional Euclidean space.
+The input is a point sample coming from an unknown manifold, which means that the points lie close to a structure of "small" intrinsic dimension.
+The running time depends only linearly on the extrinsic dimension \f$ d \f$
+and exponentially on the intrinsic dimension \f$ k \f$.
+
+An extensive description of the Tangential complex can be found in \cite tangentialcomplex2014.
+
+\subsection whatisthetc What is a Tangential Complex?
+
+Let us start with the description of the Tangential complex of a simple example, with \f$ k=1 \f$ and \f$ d=2 \f$.
+The input data is 4 points \f$ P \f$ located on a curve embedded in 2D.
+\image html "tc_example_01.png" "The input"
+For each point \f$ p \f$, estimate its tangent subspace \f$ T_p \f$ (e.g. using PCA).
+\image html "tc_example_02.png" "The estimated normals"
+Let us add the Voronoi diagram of the points in orange. For each point \f$ p \f$, construct its star in the Delaunay triangulation of \f$ P \f$ restricted to \f$ T_p \f$.
+\image html "tc_example_03.png" "The Voronoi diagram"
+The Tangential Delaunay complex is the union of those stars.
+
+In practice, neither the ambient Voronoi diagram nor the ambient Delaunay triangulation is computed.
+Instead, local \f$ k \f$-dimensional regular triangulations are computed with a limited number of points as we only need the star of each point.
+More details can be found in \cite tangentialcomplex2014.
+
+\subsection inconsistencies Inconsistencies
+
+Inconsistencies between the stars can occur.
+An inconsistency occurs when a simplex is not in the star of all its vertices.
+
+Let us take the same example.
+\image html "tc_example_07_before.png" "Before"
+Let us slightly move the tangent subspace \f$ T_q \f$
+\image html "tc_example_07_after.png" "After"
+Now, the star of \f$ Q \f$ contains \f$ QP \f$, but the star of \f$ P \f$ does not contain \f$ QP \f$. We have an inconsistency.
+\image html "tc_example_08.png" "After"
+
+One way to solve inconsistencies is to randomly perturb the positions of the points involved in an inconsistency.
+In the current implementation, this perturbation is done in the tangent subspace of each point.
+The maximum perturbation radius is given as a parameter to the constructor.
+
+In most cases, we recommend to provide a point set where the minimum distance between any two points
+is not too small. This can be achieved using the functions provided by the Subsampling module. Then, a good value to start with for
+the maximum perturbation radius would be around half the minimum distance between any two points.
+The \ref example_with_perturb below shows an example of such a process.
+
+In most cases, this process is able to dramatically reduce the number of inconsistencies, but is not guaranteed to succeed.
+
+\subsection output Output
+
+The result of the computation is exported as a `Simplex_tree`. It is the union of the stars of all the input points.
+A vertex in the Simplex Tree is the index of the point in the range provided by the user.
+The point corresponding to a vertex can also be obtained through the `Tangential_complex::get_point` function.
+Note that even if the positions of the points are perturbed, their original positions are kept (e.g. `Tangential_complex::get_point` returns the original position of the point).
+
+The result can be obtained after the computation of the Tangential complex itself and/or after the perturbation process.
+
+\section simple_example Simple example
+
+This example builds the Tangential complex of point set.
+Note that the dimension of the kernel here is dynamic, which is slower, but more flexible:
+the intrinsic and ambient dimensions does not have to be known at compile-time.
+
+\include Tangential_complex/example_basic.cpp
+
+\section example_with_perturb Example with perturbation
+
+This example builds the Tangential complex of a point set, then tries to solve inconsistencies
+by perturbing the positions of points involved in inconsistent simplices.
+Note that the dimension of the kernel here is static, which is the best choice when the
+dimensions are known at compile-time.
+
+\include Tangential_complex/example_with_perturb.cpp
+
+\copyright GNU General Public License v3.
+\verbatim Contact: gudhi-users@lists.gforge.inria.fr \endverbatim
+ */
+/** @} */ // end defgroup tangential_complex
+
+} // namespace tangential_complex
+
+} // namespace Gudhi
+
+#endif // DOC_TANGENTIAL_COMPLEX_INTRO_TANGENTIAL_COMPLEX_H_
diff --git a/src/Tangential_complex/doc/tc_example_01.png b/src/Tangential_complex/doc/tc_example_01.png
new file mode 100644
index 00000000..8afe6198
--- /dev/null
+++ b/src/Tangential_complex/doc/tc_example_01.png
Binary files differ
diff --git a/src/Tangential_complex/doc/tc_example_02.png b/src/Tangential_complex/doc/tc_example_02.png
new file mode 100644
index 00000000..01591c1d
--- /dev/null
+++ b/src/Tangential_complex/doc/tc_example_02.png
Binary files differ
diff --git a/src/Tangential_complex/doc/tc_example_03.png b/src/Tangential_complex/doc/tc_example_03.png
new file mode 100644
index 00000000..5de04e01
--- /dev/null
+++ b/src/Tangential_complex/doc/tc_example_03.png
Binary files differ
diff --git a/src/Tangential_complex/doc/tc_example_05.png b/src/Tangential_complex/doc/tc_example_05.png
new file mode 100644
index 00000000..fdd5e5fa
--- /dev/null
+++ b/src/Tangential_complex/doc/tc_example_05.png
Binary files differ
diff --git a/src/Tangential_complex/doc/tc_example_06.png b/src/Tangential_complex/doc/tc_example_06.png
new file mode 100644
index 00000000..31ad3c43
--- /dev/null
+++ b/src/Tangential_complex/doc/tc_example_06.png
Binary files differ
diff --git a/src/Tangential_complex/doc/tc_example_07.png b/src/Tangential_complex/doc/tc_example_07.png
new file mode 100644
index 00000000..47e34de7
--- /dev/null
+++ b/src/Tangential_complex/doc/tc_example_07.png
Binary files differ
diff --git a/src/Tangential_complex/doc/tc_example_07_after.png b/src/Tangential_complex/doc/tc_example_07_after.png
new file mode 100644
index 00000000..981350d2
--- /dev/null
+++ b/src/Tangential_complex/doc/tc_example_07_after.png
Binary files differ
diff --git a/src/Tangential_complex/doc/tc_example_07_before.png b/src/Tangential_complex/doc/tc_example_07_before.png
new file mode 100644
index 00000000..ddc6bc7b
--- /dev/null
+++ b/src/Tangential_complex/doc/tc_example_07_before.png
Binary files differ
diff --git a/src/Tangential_complex/doc/tc_example_08.png b/src/Tangential_complex/doc/tc_example_08.png
new file mode 100644
index 00000000..119a87de
--- /dev/null
+++ b/src/Tangential_complex/doc/tc_example_08.png
Binary files differ
diff --git a/src/Tangential_complex/doc/tc_example_09.png b/src/Tangential_complex/doc/tc_example_09.png
new file mode 100644
index 00000000..31bac1e0
--- /dev/null
+++ b/src/Tangential_complex/doc/tc_example_09.png
Binary files differ
diff --git a/src/Tangential_complex/doc/tc_examples.png b/src/Tangential_complex/doc/tc_examples.png
new file mode 100644
index 00000000..b6544afe
--- /dev/null
+++ b/src/Tangential_complex/doc/tc_examples.png
Binary files differ
diff --git a/src/Tangential_complex/example/CMakeLists.txt b/src/Tangential_complex/example/CMakeLists.txt
new file mode 100644
index 00000000..a75ccd5b
--- /dev/null
+++ b/src/Tangential_complex/example/CMakeLists.txt
@@ -0,0 +1,23 @@
+cmake_minimum_required(VERSION 2.6)
+project(Tangential_complex_examples)
+
+if(CGAL_FOUND)
+ if (NOT CGAL_VERSION VERSION_LESS 4.8.0)
+ if (EIGEN3_FOUND)
+ add_executable( Tangential_complex_example_basic example_basic.cpp )
+ target_link_libraries(Tangential_complex_example_basic ${CGAL_LIBRARY} ${Boost_DATE_TIME_LIBRARY})
+ add_executable( Tangential_complex_example_with_perturb example_with_perturb.cpp )
+ target_link_libraries(Tangential_complex_example_with_perturb ${CGAL_LIBRARY} ${Boost_DATE_TIME_LIBRARY})
+ if (TBB_FOUND)
+ target_link_libraries(Tangential_complex_example_basic ${TBB_LIBRARIES})
+ target_link_libraries(Tangential_complex_example_with_perturb ${TBB_LIBRARIES})
+ endif(TBB_FOUND)
+
+ add_test(Tangential_complex_example_basic
+ ${CMAKE_CURRENT_BINARY_DIR}/Tangential_complex_example_basic)
+
+ add_test(Tangential_complex_example_with_perturb
+ ${CMAKE_CURRENT_BINARY_DIR}/Tangential_complex_example_with_perturb)
+ endif(EIGEN3_FOUND)
+ endif(NOT CGAL_VERSION VERSION_LESS 4.8.0)
+endif(CGAL_FOUND)
diff --git a/src/Tangential_complex/example/example_basic.cpp b/src/Tangential_complex/example/example_basic.cpp
new file mode 100644
index 00000000..4f2b859e
--- /dev/null
+++ b/src/Tangential_complex/example/example_basic.cpp
@@ -0,0 +1,46 @@
+#include <gudhi/Tangential_complex.h>
+#include <gudhi/sparsify_point_set.h>
+
+#include <CGAL/Epick_d.h>
+#include <CGAL/Random.h>
+
+#include <array>
+#include <vector>
+
+namespace tc = Gudhi::tangential_complex;
+
+typedef CGAL::Epick_d<CGAL::Dynamic_dimension_tag> Kernel;
+typedef Kernel::FT FT;
+typedef Kernel::Point_d Point;
+typedef Kernel::Vector_d Vector;
+typedef tc::Tangential_complex<
+Kernel, CGAL::Dynamic_dimension_tag,
+CGAL::Parallel_tag> TC;
+
+int main(void) {
+ const int INTRINSIC_DIM = 2;
+ const int AMBIENT_DIM = 3;
+ const int NUM_POINTS = 1000;
+
+ Kernel k;
+
+ // Generate points on a 2-sphere
+ CGAL::Random_points_on_sphere_d<Point> generator(AMBIENT_DIM, 3.);
+ std::vector<Point> points;
+ points.reserve(NUM_POINTS);
+ for (int i = 0; i < NUM_POINTS; ++i)
+ points.push_back(*generator++);
+
+ // Compute the TC
+ TC tc(points, INTRINSIC_DIM, k);
+ tc.compute_tangential_complex();
+
+ // Export the TC into a Simplex_tree
+ Gudhi::Simplex_tree<> stree;
+ tc.create_complex(stree);
+
+ // Display stats about inconsistencies
+ tc.number_of_inconsistent_simplices(true); // verbose
+
+ return 0;
+}
diff --git a/src/Tangential_complex/example/example_with_perturb.cpp b/src/Tangential_complex/example/example_with_perturb.cpp
new file mode 100644
index 00000000..d0d877ea
--- /dev/null
+++ b/src/Tangential_complex/example/example_with_perturb.cpp
@@ -0,0 +1,53 @@
+#include <gudhi/Tangential_complex.h>
+#include <gudhi/sparsify_point_set.h>
+
+#include <CGAL/Epick_d.h>
+#include <CGAL/Random.h>
+
+#include <array>
+#include <vector>
+
+namespace subsampl = Gudhi::subsampling;
+namespace tc = Gudhi::tangential_complex;
+
+typedef CGAL::Epick_d<CGAL::Dimension_tag < 3 >> Kernel;
+typedef Kernel::FT FT;
+typedef Kernel::Point_d Point;
+typedef Kernel::Vector_d Vector;
+typedef tc::Tangential_complex<
+Kernel, CGAL::Dimension_tag<2>,
+CGAL::Parallel_tag> TC;
+
+int main(void) {
+ const int INTRINSIC_DIM = 2;
+ const int AMBIENT_DIM = 3;
+ const int NUM_POINTS = 50;
+
+ Kernel k;
+
+ // Generate points on a 2-sphere
+ CGAL::Random_points_on_sphere_d<Point> generator(AMBIENT_DIM, 3.);
+ std::vector<Point> points;
+ points.reserve(NUM_POINTS);
+ for (int i = 0; i < NUM_POINTS; ++i)
+ points.push_back(*generator++);
+
+ // Sparsify the point set
+ std::vector<Point> sparsified_points;
+ subsampl::sparsify_point_set(k, points, 0.1 * 0.1,
+ std::back_inserter(sparsified_points));
+ sparsified_points.swap(points);
+
+ // Compute the TC
+ TC tc(points, INTRINSIC_DIM, k);
+ tc.compute_tangential_complex();
+
+ // Try to fix inconsistencies. Give it 10 seconds to succeed
+ tc.fix_inconsistencies_using_perturbation(0.05, 10);
+
+ // Export the TC into a Simplex_tree
+ Gudhi::Simplex_tree<> stree;
+ tc.create_complex(stree);
+
+ return 0;
+}
diff --git a/src/Tangential_complex/include/gudhi/Tangential_complex.h b/src/Tangential_complex/include/gudhi/Tangential_complex.h
new file mode 100644
index 00000000..e748d3b7
--- /dev/null
+++ b/src/Tangential_complex/include/gudhi/Tangential_complex.h
@@ -0,0 +1,2279 @@
+/* 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>
+
+#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()) {
+#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);
+ }
+ 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 = static_cast<unsigned int> (std::pow(GUDHI_TC_BASE_VALUE_FOR_PCA, m_intrinsic_dim));
+
+ // 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();
+
+#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 = static_cast<unsigned int> (std::pow(GUDHI_TC_BASE_VALUE_FOR_PCA, m_intrinsic_dim));
+
+ // 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 == NULL || 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;
+
+ std::size_t num_vertices = 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/src/Tangential_complex/include/gudhi/Tangential_complex/Simplicial_complex.h b/src/Tangential_complex/include/gudhi/Tangential_complex/Simplicial_complex.h
new file mode 100644
index 00000000..65c74ca5
--- /dev/null
+++ b/src/Tangential_complex/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/src/common/include/gudhi/Utils.h b/src/Tangential_complex/include/gudhi/Tangential_complex/config.h
index 43916f11..ffefcd6b 100644
--- a/src/common/include/gudhi/Utils.h
+++ b/src/Tangential_complex/include/gudhi/Tangential_complex/config.h
@@ -2,9 +2,9 @@
* (Geometric Understanding in Higher Dimensions) is a generic C++
* library for computational topology.
*
- * Author(s): David Salinas
+ * Author(s): Clement Jamin
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (France)
+ * 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
@@ -19,28 +19,25 @@
* 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 UTILS_H_
-#define UTILS_H_
+#ifndef TANGENTIAL_COMPLEX_CONFIG_H_
+#define TANGENTIAL_COMPLEX_CONFIG_H_
-#define PRINT(a) std::cerr << #a << ": " << (a) << " (DISP)" << std::endl
+#include <cstddef>
-// #define DBG_VERBOSE
-#ifdef DBG_VERBOSE
-#define DBG(a) std::cerr << "DBG: " << (a) << std::endl
-#define DBGMSG(a, b) std::cerr << "DBG: " << a << b << std::endl
-#define DBGVALUE(a) std::cerr << "DBG: " << #a << ": " << a << std::endl
-#define DBGCONT(a) std::cerr << "DBG: container " << #a << " -> "; for (auto x : a) std::cerr << x << ","; std::cerr <<
-std::endl
-#else
-// #define DBG(a) a
-// #define DBGMSG(a,b) b
-// #define DBGVALUE(a) a
-// #define DBGCONT(a) a
-#define DBG(a)
-#define DBGMSG(a, b)
-#define DBGVALUE(a)
-#define DBGCONT(a)
-#endif
+// ========================= 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
-#endif // UTILS_H_
+// ========================= 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/src/Tangential_complex/include/gudhi/Tangential_complex/utilities.h b/src/Tangential_complex/include/gudhi/Tangential_complex/utilities.h
new file mode 100644
index 00000000..b2d6d674
--- /dev/null
+++ b/src/Tangential_complex/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/src/Tangential_complex/test/CMakeLists.txt b/src/Tangential_complex/test/CMakeLists.txt
new file mode 100644
index 00000000..075028c8
--- /dev/null
+++ b/src/Tangential_complex/test/CMakeLists.txt
@@ -0,0 +1,31 @@
+cmake_minimum_required(VERSION 2.6)
+project(Tangential_complex_tests)
+
+if (GCOVR_PATH)
+ # for gcovr to make coverage reports - Corbera Jenkins plugin
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
+endif()
+if (GPROF_PATH)
+ # for gprof to make coverage reports - Jenkins
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg")
+endif()
+
+if(CGAL_FOUND)
+ if (NOT CGAL_VERSION VERSION_LESS 4.8.0)
+ if (EIGEN3_FOUND)
+ message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.")
+ include( ${EIGEN3_USE_FILE} )
+ include_directories (BEFORE "../../include")
+
+ add_executable( Tangential_complex_test_TC test_tangential_complex.cpp )
+ target_link_libraries(Tangential_complex_test_TC ${CGAL_LIBRARY} ${Boost_DATE_TIME_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+ if (TBB_FOUND)
+ target_link_libraries(Tangential_complex_test_TC ${TBB_LIBRARIES})
+ endif()
+ add_test(Tangential_complex_test_TC ${CMAKE_CURRENT_BINARY_DIR}/Tangential_complex_test_TC
+ # XML format for Jenkins xUnit plugin
+ --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/Tangential_complex_UT.xml --log_level=test_suite --report_level=no)
+
+ endif()
+ endif ()
+endif() \ No newline at end of file
diff --git a/src/Tangential_complex/test/test_tangential_complex.cpp b/src/Tangential_complex/test/test_tangential_complex.cpp
new file mode 100644
index 00000000..f8b0d2fb
--- /dev/null
+++ b/src/Tangential_complex/test/test_tangential_complex.cpp
@@ -0,0 +1,70 @@
+/* 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/>.
+ */
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE Tangential_complex - test tangential complex
+#include <boost/test/unit_test.hpp>
+
+#include <gudhi/Tangential_complex.h>
+#include <gudhi/sparsify_point_set.h>
+
+#include <CGAL/Epick_d.h>
+#include <CGAL/Random.h>
+
+#include <array>
+#include <vector>
+
+namespace tc = Gudhi::tangential_complex;
+
+BOOST_AUTO_TEST_CASE(test_Spatial_tree_data_structure) {
+ typedef CGAL::Epick_d<CGAL::Dynamic_dimension_tag> Kernel;
+ typedef Kernel::Point_d Point;
+ typedef tc::Tangential_complex<
+ Kernel, CGAL::Dynamic_dimension_tag,
+ CGAL::Parallel_tag> TC;
+
+ const int INTRINSIC_DIM = 2;
+ const int AMBIENT_DIM = 3;
+ const int NUM_POINTS = 50;
+
+ Kernel k;
+
+ // Generate points on a 2-sphere
+ CGAL::Random_points_on_sphere_d<Point> generator(AMBIENT_DIM, 3.);
+ std::vector<Point> points;
+ points.reserve(NUM_POINTS);
+ for (int i = 0; i < NUM_POINTS; ++i)
+ points.push_back(*generator++);
+
+ // Compute the TC
+ TC tc(points, INTRINSIC_DIM, k);
+ tc.compute_tangential_complex();
+
+ // Try to fix inconsistencies. Give it 60 seconds to succeed
+ auto perturb_ret = tc.fix_inconsistencies_using_perturbation(0.01, 60);
+
+ BOOST_CHECK(perturb_ret.success);
+
+ // Export the TC into a Simplex_tree
+ Gudhi::Simplex_tree<> stree;
+ tc.create_complex(stree);
+}
diff --git a/src/Witness_complex/concept/Simplicial_complex_for_witness.h b/src/Witness_complex/concept/Simplicial_complex_for_witness.h
new file mode 100644
index 00000000..caaf0db6
--- /dev/null
+++ b/src/Witness_complex/concept/Simplicial_complex_for_witness.h
@@ -0,0 +1,87 @@
+/* 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) 2014 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 CONCEPT_WITNESS_COMPLEX_SIMPLICIAL_COMPLEX_FOR_WITNESS_H_
+#define CONCEPT_WITNESS_COMPLEX_SIMPLICIAL_COMPLEX_FOR_WITNESS_H_
+
+namespace Gudhi {
+
+namespace witness_complex {
+
+/** \brief The concept Simplicial_Complex describes the requirements
+ * for a type to implement a simplicial complex,
+ * used for example to build a 'Witness_complex'.
+ */
+struct SimplicialComplexForWitness {
+ /** Handle to specify a simplex. */
+ typedef unspecified Simplex_handle;
+ /** Handle to specify a vertex. Must be a non-negative integer. */
+ typedef unspecified Vertex_handle;
+
+ /** Returns a Simplex_hanlde that is different from all simplex handles
+ * of the simplices. */
+ Simplex_handle null_simplex();
+
+ /** \brief Iterator over the simplices of the complex,
+ * in an arbitrary order.
+ *
+ * 'value_type' must be 'Simplex_handle'.*/
+ typedef unspecified Complex_simplex_range;
+
+ /**
+ * \brief Returns a range over all the simplices of a
+ * complex.
+ */
+ Complex_simplex_range complex_simplex_range();
+
+ /** \brief Iterator over vertices of a simplex.
+ *
+ * 'value type' must be 'Vertex_handle'.*/
+ typedef unspecified Simplex_vertex_range;
+
+ /** \brief Returns a range over vertices of a given
+ * simplex. */
+ Simplex_vertex_range simplex_vertex_range(Simplex_handle const & simplex);
+
+ /** \brief Return type of an insertion of a simplex
+ */
+ typedef unspecified Insertion_result_type;
+
+ /** \brief Inserts a simplex with vertices from a given range
+ * 'vertex_range' in the simplicial complex.
+ * */
+ template< typedef Input_vertex_range >
+ Insertion_result_type insert_simplex(Input_vertex_range const & vertex_range);
+
+ /** \brief Finds a simplex with vertices given by a range
+ *
+ * If a simplex exists, its Simplex_handle is returned.
+ * Otherwise null_simplex() is returned. */
+ template< typedef Input_vertex_range >
+ Simplex_handle find(Input_vertex_range const & vertex_range);
+};
+
+} // namespace witness_complex
+
+} // namespace Gudhi
+
+#endif // CONCEPT_WITNESS_COMPLEX_SIMPLICIAL_COMPLEX_FOR_WITNESS_H_
diff --git a/src/Witness_complex/doc/Witness_complex_doc.h b/src/Witness_complex/doc/Witness_complex_doc.h
new file mode 100644
index 00000000..60dfd27b
--- /dev/null
+++ b/src/Witness_complex/doc/Witness_complex_doc.h
@@ -0,0 +1,42 @@
+#ifndef WITNESS_COMPLEX_DOC_H_
+#define WITNESS_COMPLEX_DOC_H_
+
+/**
+ \defgroup witness_complex Witness complex
+
+ \author Siargey Kachanovich
+
+ \image html "Witness_complex_representation.png" "Witness complex representation"
+
+ \section Definitions
+
+ Witness complex \f$ Wit(W,L) \f$ is a simplicial complex defined on two sets of points in \f$\mathbb{R}^D\f$:
+
+ \li \f$W\f$ set of **witnesses** and
+ \li \f$L \subseteq W\f$ set of **landmarks**.
+
+ The simplices are based on landmarks
+ and a simplex belongs to the witness complex if and only if it is witnessed, that is:
+
+ \f$ \sigma \subset L \f$ is witnessed if there exists a point \f$w \in W\f$ such that
+ w is closer to the vertices of \f$ \sigma \f$ than other points in \f$ L \f$ and all of its faces are witnessed as well.
+
+ The data structure is described in \cite boissonnatmariasimplextreealgorithmica .
+
+ \section Implementation
+
+ The principal class of this module is Gudhi::Witness_complex.
+
+ In both cases, the constructor for this class takes a {witness}x{closest_landmarks} table, where each row represents a witness and consists of landmarks sorted by distance to this witness.
+ This table can be constructed by two additional classes Landmark_choice_by_furthest_point and Landmark_choice_by_random_point also included in the module.
+
+ *\image html "bench_Cy8.png" "Running time as function on number of landmarks" width=10cm
+ *\image html "bench_sphere.png" "Running time as function on number of witnesses for |L|=300" width=10cm
+
+
+ \copyright GNU General Public License v3.
+
+
+ */
+
+#endif // WITNESS_COMPLEX_DOC_H_
diff --git a/src/Witness_complex/doc/Witness_complex_representation.png b/src/Witness_complex/doc/Witness_complex_representation.png
new file mode 100644
index 00000000..1d31a490
--- /dev/null
+++ b/src/Witness_complex/doc/Witness_complex_representation.png
Binary files differ
diff --git a/src/Witness_complex/doc/bench_Cy8.png b/src/Witness_complex/doc/bench_Cy8.png
new file mode 100644
index 00000000..d9045294
--- /dev/null
+++ b/src/Witness_complex/doc/bench_Cy8.png
Binary files differ
diff --git a/src/Witness_complex/doc/bench_sphere.png b/src/Witness_complex/doc/bench_sphere.png
new file mode 100644
index 00000000..ba6bb381
--- /dev/null
+++ b/src/Witness_complex/doc/bench_sphere.png
Binary files differ
diff --git a/src/Witness_complex/example/CMakeLists.txt b/src/Witness_complex/example/CMakeLists.txt
new file mode 100644
index 00000000..857ec819
--- /dev/null
+++ b/src/Witness_complex/example/CMakeLists.txt
@@ -0,0 +1,17 @@
+cmake_minimum_required(VERSION 2.6)
+project(Witness_complex_examples)
+
+# A simple example
+ add_executable( witness_complex_from_file witness_complex_from_file.cpp )
+ add_test( witness_complex_from_bunny ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_from_file
+ ${CMAKE_SOURCE_DIR}/data/points/bunny_5000.off 100)
+
+if(CGAL_FOUND)
+ if (NOT CGAL_VERSION VERSION_LESS 4.6.0)
+ if (EIGEN3_FOUND)
+ add_executable ( witness_complex_sphere witness_complex_sphere.cpp )
+ target_link_libraries(witness_complex_sphere ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY})
+ add_test( witness_complex_sphere_10 ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_sphere 10)
+ endif(EIGEN3_FOUND)
+ endif (NOT CGAL_VERSION VERSION_LESS 4.6.0)
+endif()
diff --git a/src/Witness_complex/example/generators.h b/src/Witness_complex/example/generators.h
new file mode 100644
index 00000000..ac445261
--- /dev/null
+++ b/src/Witness_complex/example/generators.h
@@ -0,0 +1,147 @@
+/* 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 EXAMPLE_WITNESS_COMPLEX_GENERATORS_H_
+#define EXAMPLE_WITNESS_COMPLEX_GENERATORS_H_
+
+#include <CGAL/Epick_d.h>
+#include <CGAL/point_generators_d.h>
+
+#include <fstream>
+#include <string>
+#include <vector>
+
+typedef CGAL::Epick_d<CGAL::Dynamic_dimension_tag> K;
+typedef K::FT FT;
+typedef K::Point_d Point_d;
+typedef std::vector<Point_d> Point_Vector;
+typedef CGAL::Random_points_in_cube_d<Point_d> Random_cube_iterator;
+typedef CGAL::Random_points_in_ball_d<Point_d> Random_point_iterator;
+
+/**
+ * \brief Rock age method of reading off file
+ *
+ */
+inline void
+off_reader_cust(std::string file_name, std::vector<Point_d> & points) {
+ std::ifstream in_file(file_name.c_str(), std::ios::in);
+ if (!in_file.is_open()) {
+ std::cerr << "Unable to open file " << file_name << std::endl;
+ return;
+ }
+ std::string line;
+ double x;
+ // Line OFF. No need in it
+ if (!getline(in_file, line)) {
+ std::cerr << "No line OFF\n";
+ return;
+ }
+ // Line with 3 numbers. No need
+ if (!getline(in_file, line)) {
+ std::cerr << "No line with 3 numbers\n";
+ return;
+ }
+ // Reading points
+ while (getline(in_file, line)) {
+ std::vector< double > point;
+ std::istringstream iss(line);
+ while (iss >> x) {
+ point.push_back(x);
+ }
+ points.push_back(Point_d(point));
+ }
+ in_file.close();
+}
+
+/**
+ * \brief Customized version of read_points
+ * which takes into account a possible nbP first line
+ *
+ */
+inline void
+read_points_cust(std::string file_name, Point_Vector & points) {
+ std::ifstream in_file(file_name.c_str(), std::ios::in);
+ if (!in_file.is_open()) {
+ std::cerr << "Unable to open file " << file_name << std::endl;
+ return;
+ }
+ std::string line;
+ double x;
+ while (getline(in_file, line)) {
+ std::vector< double > point;
+ std::istringstream iss(line);
+ while (iss >> x) {
+ point.push_back(x);
+ }
+ Point_d p(point.begin(), point.end());
+ if (point.size() != 1)
+ points.push_back(p);
+ }
+ in_file.close();
+}
+
+/** \brief Generate points on a grid in a cube of side 2
+ * having {+-1}^D as vertices and insert them in W.
+ * The grid has "width" points on each side.
+ * If torus is true then it is supposed that the cube represents
+ * a flat torus, hence the opposite borders are associated.
+ * The points on border in this case are not placed twice.
+ */
+void generate_points_grid(Point_Vector& W, int width, int D, bool torus) {
+ int nb_points = 1;
+ for (int i = 0; i < D; ++i)
+ nb_points *= width;
+ for (int i = 0; i < nb_points; ++i) {
+ std::vector<double> point;
+ int cell_i = i;
+ for (int l = 0; l < D; ++l) {
+ if (torus)
+ point.push_back(-1 + (2.0 / (width - 1))*(cell_i % width));
+ else
+ point.push_back(-1 + (2.0 / width)*(cell_i % width));
+ // attention: the bottom and the right are covered too!
+ cell_i /= width;
+ }
+ W.push_back(point);
+ }
+}
+
+/** \brief Generate nbP points uniformly in a cube of side 2
+ * having {+-1}^dim as its vertices and insert them in W.
+ */
+void generate_points_random_box(Point_Vector& W, int nbP, int dim) {
+ Random_cube_iterator rp(dim, 1.0);
+ for (int i = 0; i < nbP; i++) {
+ W.push_back(*rp++);
+ }
+}
+
+/** \brief Generate nbP points uniformly on a (dim-1)-sphere
+ * and insert them in W.
+ */
+void generate_points_sphere(Point_Vector& W, int nbP, int dim) {
+ CGAL::Random_points_on_sphere_d<Point_d> rp(dim, 1);
+ for (int i = 0; i < nbP; i++)
+ W.push_back(*rp++);
+}
+
+#endif // EXAMPLE_WITNESS_COMPLEX_GENERATORS_H_
diff --git a/src/Witness_complex/example/witness_complex_from_file.cpp b/src/Witness_complex/example/witness_complex_from_file.cpp
new file mode 100644
index 00000000..bb641b3c
--- /dev/null
+++ b/src/Witness_complex/example/witness_complex_from_file.cpp
@@ -0,0 +1,83 @@
+/* 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/>.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <gudhi/Points_off_io.h>
+#include <gudhi/Simplex_tree.h>
+#include <gudhi/Witness_complex.h>
+#include <gudhi/Construct_closest_landmark_table.h>
+#include <gudhi/pick_n_random_points.h>
+#include <gudhi/reader_utils.h>
+
+#include <iostream>
+#include <fstream>
+#include <ctime>
+#include <string>
+#include <vector>
+
+typedef std::vector< Vertex_handle > typeVectorVertex;
+typedef std::vector< std::vector <double> > Point_Vector;
+
+int main(int argc, char * const argv[]) {
+ if (argc != 3) {
+ std::cerr << "Usage: " << argv[0]
+ << " path_to_point_file.off nbL \n";
+ return 0;
+ }
+
+ std::string off_file_name = argv[1];
+ int nbL = atoi(argv[2]);
+ clock_t start, end;
+
+ // Construct the Simplex Tree
+ Gudhi::Simplex_tree<> simplex_tree;
+
+ // Read the OFF file (input file name given as parameter) and triangulate points
+ Gudhi::Points_off_reader<std::vector <double>> off_reader(off_file_name);
+ // Check the read operation was correct
+ if (!off_reader.is_valid()) {
+ std::cerr << "Unable to read file " << off_file_name << std::endl;
+ }
+ // Read the point file
+ Point_Vector point_vector = off_reader.get_point_cloud();
+ std::cout << "Successfully read " << point_vector.size() << " points.\n";
+ std::cout << "Ambient dimension is " << point_vector[0].size() << ".\n";
+
+ // Choose landmarks
+ start = clock();
+ std::vector<std::vector< int > > knn;
+ Point_Vector landmarks;
+ Gudhi::subsampling::pick_n_random_points(point_vector, 100, std::back_inserter(landmarks));
+ Gudhi::witness_complex::construct_closest_landmark_table(point_vector, landmarks, knn);
+ end = clock();
+ std::cout << "Landmark choice for " << nbL << " landmarks took "
+ << static_cast<double>(end - start) / CLOCKS_PER_SEC << " s. \n";
+
+ // Compute witness complex
+ start = clock();
+ Gudhi::witness_complex::witness_complex(knn, nbL, point_vector[0].size(), simplex_tree);
+ end = clock();
+ std::cout << "Witness complex took "
+ << static_cast<double>(end - start) / CLOCKS_PER_SEC << " s. \n";
+}
diff --git a/src/Witness_complex/example/witness_complex_sphere.cpp b/src/Witness_complex/example/witness_complex_sphere.cpp
new file mode 100644
index 00000000..e6f88274
--- /dev/null
+++ b/src/Witness_complex/example/witness_complex_sphere.cpp
@@ -0,0 +1,92 @@
+/* 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/>.
+ */
+#define BOOST_PARAMETER_MAX_ARITY 12
+
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <gudhi/Simplex_tree.h>
+#include <gudhi/Witness_complex.h>
+#include <gudhi/Construct_closest_landmark_table.h>
+#include <gudhi/pick_n_random_points.h>
+#include <gudhi/reader_utils.h>
+
+#include <iostream>
+#include <fstream>
+#include <ctime>
+#include <utility>
+#include <string>
+#include <vector>
+
+#include "generators.h"
+
+/** Write a gnuplot readable file.
+ * Data range is a random access range of pairs (arg, value)
+ */
+template < typename Data_range >
+void write_data(Data_range & data, std::string filename) {
+ std::ofstream ofs(filename, std::ofstream::out);
+ for (auto entry : data)
+ ofs << entry.first << ", " << entry.second << "\n";
+ ofs.close();
+}
+
+int main(int argc, char * const argv[]) {
+ if (argc != 2) {
+ std::cerr << "Usage: " << argv[0]
+ << " number_of_landmarks \n";
+ return 0;
+ }
+
+ int number_of_landmarks = atoi(argv[1]);
+ clock_t start, end;
+
+ // Construct the Simplex Tree
+ Gudhi::Simplex_tree<> simplex_tree;
+
+ std::vector< std::pair<int, double> > l_time;
+
+ // Read the point file
+ for (int nbP = 500; nbP < 10000; nbP += 500) {
+ Point_Vector point_vector, landmarks;
+ generate_points_sphere(point_vector, nbP, 4);
+ std::cout << "Successfully generated " << point_vector.size() << " points.\n";
+ std::cout << "Ambient dimension is " << point_vector[0].size() << ".\n";
+
+ // Choose landmarks
+ start = clock();
+ std::vector<std::vector< int > > knn;
+ Gudhi::subsampling::pick_n_random_points(point_vector, 100, std::back_inserter(landmarks));
+ Gudhi::witness_complex::construct_closest_landmark_table(point_vector, landmarks, knn);
+
+ // Compute witness complex
+ Gudhi::witness_complex::witness_complex(knn, number_of_landmarks, point_vector[0].size(), simplex_tree);
+ end = clock();
+ double time = static_cast<double>(end - start) / CLOCKS_PER_SEC;
+ std::cout << "Witness complex for " << number_of_landmarks << " landmarks took "
+ << time << " s. \n";
+ std::cout << "Number of simplices is: " << simplex_tree.num_simplices() << "\n";
+ l_time.push_back(std::make_pair(nbP, time));
+ }
+ write_data(l_time, "w_time.dat");
+}
diff --git a/src/Witness_complex/include/gudhi/Construct_closest_landmark_table.h b/src/Witness_complex/include/gudhi/Construct_closest_landmark_table.h
new file mode 100644
index 00000000..ef711c34
--- /dev/null
+++ b/src/Witness_complex/include/gudhi/Construct_closest_landmark_table.h
@@ -0,0 +1,90 @@
+/* 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 CONSTRUCT_CLOSEST_LANDMARK_TABLE_H_
+#define CONSTRUCT_CLOSEST_LANDMARK_TABLE_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 Construct the closest landmark tables for all witnesses.
+ * \details Output a table 'knn', each line of which represents a witness and
+ * consists of landmarks sorted by
+ * euclidean distance from the corresponding witness.
+ *
+ * The type WitnessContainer is a random access range and
+ * the type LandmarkContainer is a range.
+ * 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 WitnessContainer,
+ typename LandmarkContainer,
+ typename KNearestNeighbours>
+ void construct_closest_landmark_table(WitnessContainer const &points,
+ LandmarkContainer const &landmarks,
+ KNearestNeighbours &knn) {
+ int nbP = boost::size(points);
+ assert(nbP >= boost::size(landmarks));
+
+ 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;
+ });
+ typename LandmarkContainer::const_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], *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 // CONSTRUCT_CLOSEST_LANDMARK_TABLE_H_
diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h
new file mode 100644
index 00000000..489cdf11
--- /dev/null
+++ b/src/Witness_complex/include/gudhi/Witness_complex.h
@@ -0,0 +1,265 @@
+/* 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 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 <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>
+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
+
+ public:
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ /* @name Constructor
+ */
+
+ //@{
+
+ // Witness_range<Closest_landmark_range<Vertex_handle>>
+
+ /*
+ * \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]
+ */
+ 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
+ }
+ 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
+ }
+ }
+ k++;
+ }
+ }
+
+ //@}
+
+ 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
+ */
+ 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]);
+ }
+ } // 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;
+ }
+ }
+ 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;
+ }
+ assert(is_witnessed);
+ return false;
+ }
+ }
+ return true;
+ }
+};
+
+ /**
+ * \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
+
+#endif // WITNESS_COMPLEX_H_
diff --git a/src/Witness_complex/test/CMakeLists.txt b/src/Witness_complex/test/CMakeLists.txt
new file mode 100644
index 00000000..bb55b0f1
--- /dev/null
+++ b/src/Witness_complex/test/CMakeLists.txt
@@ -0,0 +1,30 @@
+cmake_minimum_required(VERSION 2.6)
+project(Witness_complex_tests)
+
+if (GCOVR_PATH)
+ # for gcovr to make coverage reports - Corbera Jenkins plugin
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
+endif()
+if (GPROF_PATH)
+ # for gprof to make coverage reports - Jenkins
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg")
+endif()
+
+add_executable ( simple_witness_complexUT simple_witness_complex.cpp )
+target_link_libraries(simple_witness_complexUT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+
+# Unitary tests definition and xml result file generation
+add_test(NAME simple_witness_complexUT
+ COMMAND ${CMAKE_CURRENT_BINARY_DIR}/simple_witness_complexUT
+ # XML format for Jenkins xUnit plugin
+ --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/simple_witness_complexUT.xml --log_level=test_suite --report_level=no)
+
+add_executable ( witness_complex_pointsUT witness_complex_points.cpp )
+target_link_libraries(witness_complex_pointsUT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+
+# Unitary tests definition and xml result file generation
+add_test(NAME witness_complex_pointsUT
+ COMMAND ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_pointsUT
+ # XML format for Jenkins xUnit plugin
+ --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/witness_complex_pointsUT.xml --log_level=test_suite --report_level=no)
+
diff --git a/src/Witness_complex/test/simple_witness_complex.cpp b/src/Witness_complex/test/simple_witness_complex.cpp
new file mode 100644
index 00000000..03df78ee
--- /dev/null
+++ b/src/Witness_complex/test/simple_witness_complex.cpp
@@ -0,0 +1,59 @@
+/* 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 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/>.
+ */
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE "simple_witness_complex"
+#include <boost/test/unit_test.hpp>
+#include <boost/mpl/list.hpp>
+
+#include <gudhi/Simplex_tree.h>
+#include <gudhi/Witness_complex.h>
+
+#include <iostream>
+#include <ctime>
+#include <vector>
+
+typedef Gudhi::Simplex_tree<> Simplex_tree;
+typedef std::vector< Vertex_handle > typeVectorVertex;
+typedef Gudhi::witness_complex::Witness_complex<Simplex_tree> WitnessComplex;
+
+BOOST_AUTO_TEST_CASE(simple_witness_complex) {
+ Simplex_tree complex;
+ std::vector< typeVectorVertex > knn;
+
+ knn.push_back({1, 0, 5, 2, 6, 3, 4});
+ knn.push_back({2, 6, 4, 5, 0, 1, 3});
+ knn.push_back({3, 4, 2, 1, 5, 6, 0});
+ knn.push_back({4, 2, 1, 3, 5, 6, 0});
+ knn.push_back({5, 1, 6, 0, 2, 3, 4});
+ knn.push_back({6, 0, 5, 2, 1, 3, 4});
+ knn.push_back({0, 5, 6, 1, 2, 3, 4});
+ knn.push_back({2, 6, 4, 5, 3, 1, 0});
+ knn.push_back({1, 2, 5, 4, 3, 6, 0});
+ knn.push_back({3, 4, 0, 6, 5, 1, 2});
+ knn.push_back({5, 0, 1, 3, 6, 2, 4});
+ knn.push_back({5, 6, 1, 0, 2, 3, 4});
+ knn.push_back({1, 6, 0, 5, 2, 3, 4});
+ WitnessComplex witnessComplex(knn, 7, 7, complex);
+
+ BOOST_CHECK(witnessComplex.is_witness_complex(knn, false));
+}
diff --git a/src/Witness_complex/test/witness_complex_points.cpp b/src/Witness_complex/test/witness_complex_points.cpp
new file mode 100644
index 00000000..d40bbf14
--- /dev/null
+++ b/src/Witness_complex/test/witness_complex_points.cpp
@@ -0,0 +1,58 @@
+/* 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 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/>.
+ */
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE "witness_complex_points"
+#include <boost/test/unit_test.hpp>
+#include <boost/mpl/list.hpp>
+
+#include <gudhi/Simplex_tree.h>
+#include <gudhi/Witness_complex.h>
+#include <gudhi/Construct_closest_landmark_table.h>
+#include <gudhi/pick_n_random_points.h>
+
+#include <iostream>
+#include <vector>
+
+typedef std::vector<double> Point;
+typedef std::vector< Vertex_handle > typeVectorVertex;
+typedef Gudhi::Simplex_tree<> Simplex_tree;
+typedef Gudhi::witness_complex::Witness_complex<Simplex_tree> WitnessComplex;
+
+BOOST_AUTO_TEST_CASE(witness_complex_points) {
+ std::vector< typeVectorVertex > knn;
+ std::vector< Point > points, landmarks;
+ // Add grid points as witnesses
+ for (double i = 0; i < 10; i += 1.0)
+ for (double j = 0; j < 10; j += 1.0)
+ for (double k = 0; k < 10; k += 1.0)
+ points.push_back(Point({i, j, k}));
+
+ bool b_print_output = false;
+ // First test: random choice
+ Simplex_tree complex1;
+ Gudhi::subsampling::pick_n_random_points(points, 100, std::back_inserter(landmarks));
+ Gudhi::witness_complex::construct_closest_landmark_table(points, landmarks, knn);
+ assert(!knn.empty());
+ WitnessComplex witnessComplex1(knn, 100, 3, complex1);
+ BOOST_CHECK(witnessComplex1.is_witness_complex(knn, b_print_output));
+}
diff --git a/src/cmake/modules/FindQGLViewer.cmake b/src/cmake/modules/FindQGLViewer.cmake
index 65723d67..56c1b3cf 100644
--- a/src/cmake/modules/FindQGLViewer.cmake
+++ b/src/cmake/modules/FindQGLViewer.cmake
@@ -15,7 +15,7 @@ find_path(QGLVIEWER_INCLUDE_DIR
)
find_library(QGLVIEWER_LIBRARY_RELEASE
- NAMES qglviewer-qt4 qglviewer QGLViewer QGLViewer2
+ NAMES qglviewer-qt5 QGLViewer-qt5 qglviewer QGLViewer QGLViewer2
PATHS /usr/lib
/usr/local/lib
ENV QGLVIEWERROOT
diff --git a/src/cmake/modules/FindTBB.cmake b/src/cmake/modules/FindTBB.cmake
new file mode 100644
index 00000000..13f4d929
--- /dev/null
+++ b/src/cmake/modules/FindTBB.cmake
@@ -0,0 +1,425 @@
+# Locate Intel Threading Building Blocks include paths and libraries
+# FindTBB.cmake can be found at https://code.google.com/p/findtbb/
+# Written by Hannes Hofmann <hannes.hofmann _at_ informatik.uni-erlangen.de>
+# Improvements by Gino van den Bergen <gino _at_ dtecta.com>,
+# Florian Uhlig <F.Uhlig _at_ gsi.de>,
+# Jiri Marsik <jiri.marsik89 _at_ gmail.com>
+
+# The MIT License
+#
+# Copyright (c) 2011 Hannes Hofmann
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+# GvdB: This module uses the environment variable TBB_ARCH_PLATFORM which defines architecture and compiler.
+# e.g. "ia32/vc8" or "em64t/cc4.1.0_libc2.4_kernel2.6.16.21"
+# TBB_ARCH_PLATFORM is set by the build script tbbvars[.bat|.sh|.csh], which can be found
+# in the TBB installation directory (TBB_INSTALL_DIR).
+#
+# GvdB: Mac OS X distribution places libraries directly in lib directory.
+#
+# For backwards compatibility, you may explicitely set the CMake variables TBB_ARCHITECTURE and TBB_COMPILER.
+# TBB_ARCHITECTURE [ ia32 | em64t | itanium ]
+# which architecture to use
+# TBB_COMPILER e.g. vc9 or cc3.2.3_libc2.3.2_kernel2.4.21 or cc4.0.1_os10.4.9
+# which compiler to use (detected automatically on Windows)
+
+# This module respects
+# TBB_INSTALL_DIR or $ENV{TBB21_INSTALL_DIR} or $ENV{TBB_INSTALL_DIR}
+
+# This module defines
+# TBB_INCLUDE_DIRS, where to find task_scheduler_init.h, etc.
+# TBB_LIBRARY_DIRS, where to find TBB libraries
+# TBB_INSTALL_DIR, the base TBB install directory.
+# TBB_LIBRARIES, all the following TBB libraries (both release and debug versions, using "optimized" and "debug" CMake keywords). Note that if the debug versions are not found, the release versions will be used instead for the debug mode.
+# TBB_RELEASE_LIBRARY, the TBB release library
+# TBB_MALLOC_RELEASE_LIBRARY, the TBB release malloc library
+# TBB_DEBUG_LIBRARY, the TBB debug library
+# TBB_MALLOC_DEBUG_LIBRARY, the TBB debug malloc library
+# TBB_FOUND, If false, don't try to use TBB.
+# TBB_INTERFACE_VERSION, as defined in tbb/tbb_stddef.h
+# TBB_MALLOCPROXY_DEBUG_LIBRARY, the TBB debug malloc_proxy library (not included in TBB_LIBRARIES since it's optionnal)
+# TBB_MALLOCPROXY_RELEASE_LIBRARY, the TBB release malloc_proxy library (not included in TBB_LIBRARIES since it's optionnal)
+
+include(CheckCXXSourceCompiles)
+
+# Usage:
+# try_TBB_with_pthread(<result_var_name> [additional linker args...])
+function(try_TBB_with_pthread result_var)
+ set(TBB_try_ts_source "
+ #include <tbb/enumerable_thread_specific.h>
+ int main() {
+ tbb::enumerable_thread_specific<
+ bool*,
+ tbb::cache_aligned_allocator<bool*>,
+ tbb::ets_key_per_instance> grid;
+ }
+ ")
+ set(CMAKE_REQUIRED_LIBRARIES ${ALL_TBB_LIBRARIES} ${ARGN})
+ set(CMAKE_REQUIRED_INCLUDES ${TBB_INCLUDE_DIR})
+ check_cxx_source_compiles("${TBB_try_ts_source}" ${result_var})
+ set(${result_var} ${${result_var}} PARENT_SCOPE)
+endfunction(try_TBB_with_pthread)
+
+if (WIN32)
+ # has em64t/vc8 em64t/vc9
+ # has ia32/vc7.1 ia32/vc8 ia32/vc9
+ set(_TBB_DEFAULT_INSTALL_DIR "C:/Program Files/Intel/TBB" "C:/Program Files (x86)/Intel/TBB")
+ set(_TBB_LIB_RELEASE_NAME "tbb")
+ set(_TBB_LIB_MALLOC_RELEASE_NAME "${_TBB_LIB_RELEASE_NAME}malloc")
+ set(_TBB_LIB_MALLOCPROXY_RELEASE_NAME "${_TBB_LIB_RELEASE_NAME}malloc_proxy")
+ set(_TBB_LIB_DEBUG_NAME "${_TBB_LIB_RELEASE_NAME}_debug")
+ set(_TBB_LIB_MALLOC_DEBUG_NAME "${_TBB_LIB_MALLOC_RELEASE_NAME}_debug")
+ set(_TBB_LIB_MALLOCPROXY_DEBUG_NAME "${_TBB_LIB_MALLOCPROXY_RELEASE_NAME}_debug")
+ if (MSVC71)
+ set (_TBB_COMPILER "vc7.1")
+ endif(MSVC71)
+ if (MSVC80)
+ set(_TBB_COMPILER "vc8")
+ endif(MSVC80)
+ if (MSVC90)
+ set(_TBB_COMPILER "vc9")
+ endif(MSVC90)
+ if(MSVC10)
+ set(_TBB_COMPILER "vc10")
+ endif(MSVC10)
+ if(MSVC11)
+ set(_TBB_COMPILER "vc11")
+ endif(MSVC11)
+ if(MSVC12)
+ set(_TBB_COMPILER "vc12")
+ endif(MSVC12)
+ #note there was no MSVC13
+ if(MSVC14)
+ set(_TBB_COMPILER "vc14")
+ endif(MSVC14)
+ # Todo: add other Windows compilers such as ICL.
+ set(_TBB_ARCHITECTURE ${TBB_ARCHITECTURE})
+endif (WIN32)
+
+if (UNIX)
+ if (APPLE)
+ # MAC
+ set(_TBB_DEFAULT_INSTALL_DIR "/Library/Frameworks/Intel_TBB.framework/Versions")
+ # libs: libtbb.dylib, libtbbmalloc.dylib, *_debug
+ set(_TBB_LIB_RELEASE_NAME "tbb")
+ set(_TBB_LIB_MALLOC_RELEASE_NAME "${_TBB_LIB_RELEASE_NAME}malloc")
+ #set(_TBB_LIB_MALLOCPROXY_RELEASE_NAME "${_TBB_LIB_RELEASE_NAME}malloc_proxy")
+ set(_TBB_LIB_DEBUG_NAME "${_TBB_LIB_RELEASE_NAME}_debug")
+ set(_TBB_LIB_MALLOC_DEBUG_NAME "${_TBB_LIB_MALLOC_RELEASE_NAME}_debug")
+ #set(_TBB_LIB_MALLOCPROXY_DEBUG_NAME "${_TBB_LIB_MALLOCPROXY_RELEASE_NAME}_debug")
+ # default flavor on apple: ia32/cc4.0.1_os10.4.9
+ # Jiri: There is no reason to presume there is only one flavor and
+ # that user's setting of variables should be ignored.
+ if(NOT TBB_COMPILER)
+ set(_TBB_COMPILER "cc4.0.1_os10.4.9")
+ elseif (NOT TBB_COMPILER)
+ set(_TBB_COMPILER ${TBB_COMPILER})
+ endif(NOT TBB_COMPILER)
+ if(NOT TBB_ARCHITECTURE)
+ set(_TBB_ARCHITECTURE "ia32")
+ elseif(NOT TBB_ARCHITECTURE)
+ set(_TBB_ARCHITECTURE ${TBB_ARCHITECTURE})
+ endif(NOT TBB_ARCHITECTURE)
+ else (APPLE)
+ # LINUX
+ set(_TBB_DEFAULT_INSTALL_DIR "/opt/intel/tbb" "/usr/local/include" "/usr/include")
+ set(_TBB_LIB_RELEASE_NAME "tbb")
+ set(_TBB_LIB_MALLOC_RELEASE_NAME "${_TBB_LIB_RELEASE_NAME}malloc")
+ set(_TBB_LIB_MALLOCPROXY_RELEASE_NAME "${_TBB_LIB_RELEASE_NAME}malloc_proxy")
+ set(_TBB_LIB_DEBUG_NAME "${_TBB_LIB_RELEASE_NAME}_debug")
+ set(_TBB_LIB_MALLOC_DEBUG_NAME "${_TBB_LIB_MALLOC_RELEASE_NAME}_debug")
+ set(_TBB_LIB_MALLOCPROXY_DEBUG_NAME "${_TBB_LIB_MALLOCPROXY_RELEASE_NAME}_debug")
+ # has em64t/cc3.2.3_libc2.3.2_kernel2.4.21 em64t/cc3.3.3_libc2.3.3_kernel2.6.5 em64t/cc3.4.3_libc2.3.4_kernel2.6.9 em64t/cc4.1.0_libc2.4_kernel2.6.16.21
+ # has ia32/*
+ # has itanium/*
+ set(_TBB_COMPILER ${TBB_COMPILER})
+ set(_TBB_ARCHITECTURE ${TBB_ARCHITECTURE})
+ endif (APPLE)
+endif (UNIX)
+
+if (CMAKE_SYSTEM MATCHES "SunOS.*")
+# SUN
+# not yet supported
+# has em64t/cc3.4.3_kernel5.10
+# has ia32/*
+endif (CMAKE_SYSTEM MATCHES "SunOS.*")
+
+
+#-- Clear the public variables
+set (TBB_FOUND "NO")
+
+
+#-- Find TBB install dir and set ${_TBB_INSTALL_DIR} and cached ${TBB_INSTALL_DIR}
+# first: use CMake variable TBB_INSTALL_DIR
+if (TBB_INSTALL_DIR)
+ set (_TBB_INSTALL_DIR ${TBB_INSTALL_DIR})
+endif (TBB_INSTALL_DIR)
+# second: use environment variable
+if (NOT _TBB_INSTALL_DIR)
+ if (NOT "$ENV{TBBROOT}" STREQUAL "")
+ set (_TBB_INSTALL_DIR $ENV{TBBROOT})
+ endif (NOT "$ENV{TBBROOT}" STREQUAL "")
+ if (NOT "$ENV{TBB_INSTALL_DIR}" STREQUAL "")
+ set (_TBB_INSTALL_DIR $ENV{TBB_INSTALL_DIR})
+ endif (NOT "$ENV{TBB_INSTALL_DIR}" STREQUAL "")
+ # Intel recommends setting TBB21_INSTALL_DIR
+ if (NOT "$ENV{TBB21_INSTALL_DIR}" STREQUAL "")
+ set (_TBB_INSTALL_DIR $ENV{TBB21_INSTALL_DIR})
+ endif (NOT "$ENV{TBB21_INSTALL_DIR}" STREQUAL "")
+ if (NOT "$ENV{TBB22_INSTALL_DIR}" STREQUAL "")
+ set (_TBB_INSTALL_DIR $ENV{TBB22_INSTALL_DIR})
+ endif (NOT "$ENV{TBB22_INSTALL_DIR}" STREQUAL "")
+ if (NOT "$ENV{TBB30_INSTALL_DIR}" STREQUAL "")
+ set (_TBB_INSTALL_DIR $ENV{TBB30_INSTALL_DIR})
+ endif (NOT "$ENV{TBB30_INSTALL_DIR}" STREQUAL "")
+endif (NOT _TBB_INSTALL_DIR)
+# third: try to find path automatically
+if (NOT _TBB_INSTALL_DIR)
+ if (_TBB_DEFAULT_INSTALL_DIR)
+ set (_TBB_INSTALL_DIR ${_TBB_DEFAULT_INSTALL_DIR})
+ endif (_TBB_DEFAULT_INSTALL_DIR)
+endif (NOT _TBB_INSTALL_DIR)
+# sanity check
+if (NOT _TBB_INSTALL_DIR)
+ message ("ERROR: Unable to find Intel TBB install directory. ${_TBB_INSTALL_DIR}")
+else (NOT _TBB_INSTALL_DIR)
+# finally: set the cached CMake variable TBB_INSTALL_DIR
+if (NOT TBB_INSTALL_DIR)
+ set (TBB_INSTALL_DIR ${_TBB_INSTALL_DIR} CACHE PATH "Intel TBB install directory")
+ mark_as_advanced(TBB_INSTALL_DIR)
+endif (NOT TBB_INSTALL_DIR)
+
+
+#-- A macro to rewrite the paths of the library. This is necessary, because
+# find_library() always found the em64t/vc9 version of the TBB libs
+macro(TBB_CORRECT_LIB_DIR var_name)
+# if (NOT "${_TBB_ARCHITECTURE}" STREQUAL "em64t")
+ string(REPLACE em64t "${_TBB_ARCHITECTURE}" ${var_name} ${${var_name}})
+# endif (NOT "${_TBB_ARCHITECTURE}" STREQUAL "em64t")
+ string(REPLACE ia32 "${_TBB_ARCHITECTURE}" ${var_name} ${${var_name}})
+ string(REGEX REPLACE "vc[0-9]+(\.[0-9]+)?" "${_TBB_COMPILER}" ${var_name} ${${var_name}})
+endmacro(TBB_CORRECT_LIB_DIR var_content)
+
+
+#-- Look for include directory and set ${TBB_INCLUDE_DIR}
+set (TBB_INC_SEARCH_DIR ${_TBB_INSTALL_DIR}/include)
+# Jiri: tbbvars now sets the CPATH environment variable to the directory
+# containing the headers.
+# LR: search first with NO_DEFAULT_PATH...
+find_path(TBB_INCLUDE_DIR
+ tbb/task_scheduler_init.h
+ PATHS ${TBB_INC_SEARCH_DIR} ENV CPATH
+ NO_DEFAULT_PATH
+)
+if(NOT TBB_INCLUDE_DIR)
+# LR: ... and then search again with NO_DEFAULT_PATH if nothing was found in
+# hinted paths
+ find_path(TBB_INCLUDE_DIR
+ tbb/task_scheduler_init.h
+ PATHS ${TBB_INC_SEARCH_DIR} ENV CPATH
+ )
+endif()
+mark_as_advanced(TBB_INCLUDE_DIR)
+
+
+#-- Look for libraries
+# GvdB: $ENV{TBB_ARCH_PLATFORM} is set by the build script tbbvars[.bat|.sh|.csh]
+if (NOT $ENV{TBB_ARCH_PLATFORM} STREQUAL "")
+ set (_TBB_LIBRARY_DIR
+ ${_TBB_INSTALL_DIR}/lib/$ENV{TBB_ARCH_PLATFORM}
+ ${_TBB_INSTALL_DIR}/$ENV{TBB_ARCH_PLATFORM}/lib
+ )
+endif (NOT $ENV{TBB_ARCH_PLATFORM} STREQUAL "")
+# Jiri: This block isn't mutually exclusive with the previous one
+# (hence no else), instead I test if the user really specified
+# the variables in question.
+if ((NOT ${TBB_ARCHITECTURE} STREQUAL "") AND (NOT ${TBB_COMPILER} STREQUAL ""))
+ # HH: deprecated
+ message(STATUS "[Warning] FindTBB.cmake: The use of TBB_ARCHITECTURE and TBB_COMPILER is deprecated and may not be supported in future versions. Please set \$ENV{TBB_ARCH_PLATFORM} (using tbbvars.[bat|csh|sh]).")
+ # Jiri: It doesn't hurt to look in more places, so I store the hints from
+ # ENV{TBB_ARCH_PLATFORM} and the TBB_ARCHITECTURE and TBB_COMPILER
+ # variables and search them both.
+ set (_TBB_LIBRARY_DIR "${_TBB_INSTALL_DIR}/${_TBB_ARCHITECTURE}/${_TBB_COMPILER}/lib" ${_TBB_LIBRARY_DIR})
+endif ((NOT ${TBB_ARCHITECTURE} STREQUAL "") AND (NOT ${TBB_COMPILER} STREQUAL ""))
+
+# GvdB: Mac OS X distribution places libraries directly in lib directory.
+list(APPEND _TBB_LIBRARY_DIR ${_TBB_INSTALL_DIR}/lib)
+
+# Jiri: No reason not to check the default paths. From recent versions,
+# tbbvars has started exporting the LIBRARY_PATH and LD_LIBRARY_PATH
+# variables, which now point to the directories of the lib files.
+# It all makes more sense to use the ${_TBB_LIBRARY_DIR} as a HINTS
+# argument instead of the implicit PATHS as it isn't hard-coded
+# but computed by system introspection. Searching the LIBRARY_PATH
+# and LD_LIBRARY_PATH environment variables is now even more important
+# that tbbvars doesn't export TBB_ARCH_PLATFORM and it facilitates
+# the use of TBB built from sources.
+# LR: search first with NO_DEFAULT_PATH...
+find_library(TBB_RELEASE_LIBRARY ${_TBB_LIB_RELEASE_NAME} HINTS ${_TBB_LIBRARY_DIR}
+ PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH NO_DEFAULT_PATH)
+find_library(TBB_MALLOC_RELEASE_LIBRARY ${_TBB_LIB_MALLOC_RELEASE_NAME} HINTS ${_TBB_LIBRARY_DIR}
+ PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH NO_DEFAULT_PATH)
+find_library(TBB_MALLOCPROXY_RELEASE_LIBRARY ${_TBB_LIB_MALLOCPROXY_RELEASE_NAME} HINTS ${_TBB_LIBRARY_DIR}
+ PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH NO_DEFAULT_PATH)
+if(NOT TBB_RELEASE_LIBRARY OR NOT TBB_MALLOC_RELEASE_LIBRARY OR NOT TBB_MALLOCPROXY_RELEASE_LIBRARY)
+# LR: ... and then search again with NO_DEFAULT_PATH if nothing was found
+# in hinted paths
+ find_library(TBB_RELEASE_LIBRARY ${_TBB_LIB_RELEASE_NAME} HINTS ${_TBB_LIBRARY_DIR}
+ PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH)
+ find_library(TBB_MALLOC_RELEASE_LIBRARY ${_TBB_LIB_MALLOC_RELEASE_NAME} HINTS ${_TBB_LIBRARY_DIR}
+ PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH)
+ find_library(TBB_MALLOCPROXY_RELEASE_LIBRARY ${_TBB_LIB_MALLOCPROXY_RELEASE_NAME} HINTS ${_TBB_LIBRARY_DIR}
+ PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH)
+endif()
+
+#Extract path from TBB_RELEASE_LIBRARY name
+get_filename_component(TBB_RELEASE_LIBRARY_DIR ${TBB_RELEASE_LIBRARY} PATH)
+
+#TBB_CORRECT_LIB_DIR(TBB_RELEASE_LIBRARY)
+#TBB_CORRECT_LIB_DIR(TBB_MALLOC_RELEASE_LIBRARY)
+#TBB_CORRECT_LIB_DIR(TBB_MALLOCPROXY_RELEASE_LIBRARY)
+mark_as_advanced(TBB_RELEASE_LIBRARY TBB_MALLOC_RELEASE_LIBRARY TBB_MALLOCPROXY_RELEASE_LIBRARY)
+
+#-- Look for debug libraries
+# Jiri: Changed the same way as for the release libraries.
+find_library(TBB_DEBUG_LIBRARY ${_TBB_LIB_DEBUG_NAME} HINTS ${_TBB_LIBRARY_DIR}
+ PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH NO_DEFAULT_PATH)
+find_library(TBB_MALLOC_DEBUG_LIBRARY ${_TBB_LIB_MALLOC_DEBUG_NAME} HINTS ${_TBB_LIBRARY_DIR}
+ PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH NO_DEFAULT_PATH)
+find_library(TBB_MALLOCPROXY_DEBUG_LIBRARY ${_TBB_LIB_MALLOCPROXY_DEBUG_NAME} HINTS ${_TBB_LIBRARY_DIR}
+ PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH NO_DEFAULT_PATH)
+if(NOT TBB_DEBUG_LIBRARY OR NOT TBB_MALLOC_DEBUG_LIBRARY OR NOT TBB_MALLOCPROXY_DEBUG_LIBRARY)
+ find_library(TBB_DEBUG_LIBRARY ${_TBB_LIB_DEBUG_NAME} HINTS ${_TBB_LIBRARY_DIR}
+ PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH)
+ find_library(TBB_MALLOC_DEBUG_LIBRARY ${_TBB_LIB_MALLOC_DEBUG_NAME} HINTS ${_TBB_LIBRARY_DIR}
+ PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH)
+ find_library(TBB_MALLOCPROXY_DEBUG_LIBRARY ${_TBB_LIB_MALLOCPROXY_DEBUG_NAME} HINTS ${_TBB_LIBRARY_DIR}
+ PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH)
+endif()
+
+# Jiri: Self-built TBB stores the debug libraries in a separate directory.
+# Extract path from TBB_DEBUG_LIBRARY name
+get_filename_component(TBB_DEBUG_LIBRARY_DIR ${TBB_DEBUG_LIBRARY} PATH)
+
+#TBB_CORRECT_LIB_DIR(TBB_DEBUG_LIBRARY)
+#TBB_CORRECT_LIB_DIR(TBB_MALLOC_DEBUG_LIBRARY)
+#TBB_CORRECT_LIB_DIR(TBB_MALLOCPROXY_DEBUG_LIBRARY)
+mark_as_advanced(TBB_DEBUG_LIBRARY TBB_MALLOC_DEBUG_LIBRARY TBB_MALLOCPROXY_DEBUG_LIBRARY)
+
+if (TBB_INCLUDE_DIR)
+ if (TBB_RELEASE_LIBRARY)
+ set (TBB_FOUND "YES")
+
+ # NOTE: Removed because we don't want to link with the malloc_proxy by default
+ #if (NOT "${TBB_MALLOCPROXY_RELEASE_LIBRARY}" STREQUAL "TBB_MALLOCPROXY_RELEASE_LIBRARY-NOTFOUND")
+ # mark_as_advanced(TBB_MALLOCPROXY_RELEASE_LIBRARY)
+ # set (_TBB_MALLOCPROXY optimized ${TBB_MALLOCPROXY_RELEASE_LIBRARY})
+ #endif (NOT "${TBB_MALLOCPROXY_RELEASE_LIBRARY}" STREQUAL "TBB_MALLOCPROXY_RELEASE_LIBRARY-NOTFOUND")
+ #if (NOT "${TBB_MALLOCPROXY_DEBUG_LIBRARY}" STREQUAL "TBB_MALLOCPROXY_DEBUG_LIBRARY-NOTFOUND")
+ # mark_as_advanced(TBB_MALLOCPROXY_DEBUG_LIBRARY)
+ # set (_TBB_MALLOCPROXY ${_TBB_MALLOCPROXY} debug ${TBB_MALLOCPROXY_DEBUG_LIBRARY})
+ #endif (NOT "${TBB_MALLOCPROXY_DEBUG_LIBRARY}" STREQUAL "TBB_MALLOCPROXY_DEBUG_LIBRARY-NOTFOUND")
+
+ # TBB release library
+ set (ALL_TBB_LIBRARIES optimized ${TBB_RELEASE_LIBRARY})
+
+ # TBB debug library found?
+ if (TBB_DEBUG_LIBRARY)
+ list(APPEND ALL_TBB_LIBRARIES debug ${TBB_DEBUG_LIBRARY})
+ else (TBB_DEBUG_LIBRARY)
+ # Otherwise, link with the release library even in debug mode
+ list(APPEND ALL_TBB_LIBRARIES debug ${TBB_RELEASE_LIBRARY})
+ endif (TBB_DEBUG_LIBRARY)
+
+ # TBB malloc - release
+ if (TBB_MALLOC_RELEASE_LIBRARY)
+ list(APPEND ALL_TBB_LIBRARIES optimized ${TBB_MALLOC_RELEASE_LIBRARY})
+
+ # TBB malloc - debug
+ if (TBB_MALLOC_DEBUG_LIBRARY)
+ list(APPEND ALL_TBB_LIBRARIES debug ${TBB_MALLOC_DEBUG_LIBRARY})
+ else (TBB_MALLOC_DEBUG_LIBRARY)
+ list(APPEND ALL_TBB_LIBRARIES debug ${TBB_MALLOC_RELEASE_LIBRARY})
+ endif (TBB_MALLOC_DEBUG_LIBRARY)
+ endif (TBB_MALLOC_RELEASE_LIBRARY)
+
+ if(UNIX AND NOT APPLE)
+ # On Fedora, code using TBB might need -pthread
+
+ # First check without pthread
+ try_TBB_with_pthread(TBB_without_pthread)
+
+ if(NOT TBB_without_pthread)
+ # Then check with -pthread
+ try_TBB_with_pthread(TBB_with_pthread -pthread)
+ if(TBB_with_pthread)
+ list(APPEND ALL_TBB_LIBRARIES general -pthread)
+ endif(TBB_with_pthread)
+ endif(NOT TBB_without_pthread)
+ endif(UNIX AND NOT APPLE)
+
+ set (TBB_LIBRARIES ${ALL_TBB_LIBRARIES}
+ CACHE PATH "TBB libraries" FORCE)
+
+ # Include dirs
+ set (TBB_INCLUDE_DIRS ${TBB_INCLUDE_DIR} CACHE PATH "TBB include directory" FORCE)
+
+ # Library dirs
+ if( "${TBB_DEBUG_LIBRARY_DIR}" STREQUAL "" OR "${TBB_RELEASE_LIBRARY_DIR}" STREQUAL "${TBB_DEBUG_LIBRARY_DIR}" )
+ set (TBB_LIBRARY_DIRS
+ ${TBB_RELEASE_LIBRARY_DIR}
+ CACHE PATH "TBB library directories" FORCE)
+ else( "${TBB_DEBUG_LIBRARY_DIR}" STREQUAL "" OR "${TBB_RELEASE_LIBRARY_DIR}" STREQUAL "${TBB_DEBUG_LIBRARY_DIR}" )
+ set (TBB_LIBRARY_DIRS
+ ${TBB_RELEASE_LIBRARY_DIR} ${TBB_DEBUG_LIBRARY_DIR}
+ CACHE PATH "TBB library directories" FORCE)
+ endif( "${TBB_DEBUG_LIBRARY_DIR}" STREQUAL "" OR "${TBB_RELEASE_LIBRARY_DIR}" STREQUAL "${TBB_DEBUG_LIBRARY_DIR}" )
+
+ message(STATUS "Found Intel TBB")
+ endif (TBB_RELEASE_LIBRARY)
+endif (TBB_INCLUDE_DIR)
+
+if (NOT TBB_FOUND)
+ if(NOT TBB_FIND_QUIETLY)
+ message("ERROR: Intel TBB NOT found! Please define the TBBROOT (or TBB_INSTALL_DIR) and/or TBB_ARCH_PLATFORM environment variables.")
+ message(STATUS "Looked for Threading Building Blocks in ${_TBB_INSTALL_DIR}")
+ endif(NOT TBB_FIND_QUIETLY)
+ SET(TBB_INSTALL_DIR "TBB_INSTALL_DIR_NOT_FOUND" CACHE STRING "Intel TBB install directory")
+ # do only throw fatal, if this pkg is REQUIRED
+ if (TBB_FIND_REQUIRED)
+ message(FATAL_ERROR "Could NOT find TBB library.")
+ endif (TBB_FIND_REQUIRED)
+endif (NOT TBB_FOUND)
+
+endif (NOT _TBB_INSTALL_DIR)
+
+if (TBB_FOUND)
+ set(TBB_INTERFACE_VERSION 0)
+ FILE(READ "${TBB_INCLUDE_DIRS}/tbb/tbb_stddef.h" _TBB_VERSION_CONTENTS)
+ STRING(REGEX REPLACE ".*#define TBB_INTERFACE_VERSION ([0-9]+).*" "\\1" TBB_INTERFACE_VERSION "${_TBB_VERSION_CONTENTS}")
+ set(TBB_INTERFACE_VERSION "${TBB_INTERFACE_VERSION}")
+endif (TBB_FOUND)
+
+set(TBB_USE_FILE "UseTBB")
+
+### ** Emacs settings **
+### Local Variables:
+### cmake-tab-width: 4
+### End:
diff --git a/src/cmake/modules/GUDHI_doxygen_target.txt b/src/cmake/modules/GUDHI_doxygen_target.txt
new file mode 100644
index 00000000..d2cb952d
--- /dev/null
+++ b/src/cmake/modules/GUDHI_doxygen_target.txt
@@ -0,0 +1,11 @@
+# add a target to generate API documentation with Doxygen
+find_package(Doxygen)
+if(DOXYGEN_FOUND)
+ # configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY)
+
+ add_custom_target(doxygen ${DOXYGEN_EXECUTABLE} ${GUDHI_USER_VERSION_DIR}/Doxyfile
+ WORKING_DIRECTORY ${GUDHI_USER_VERSION_DIR}
+ DEPENDS ${GUDHI_USER_VERSION_DIR}/Doxyfile ${GUDHI_DOXYGEN_DEPENDENCY}
+ COMMENT "Generating API documentation with Doxygen in ${GUDHI_USER_VERSION_DIR}/doc/html/" VERBATIM)
+
+endif(DOXYGEN_FOUND)
diff --git a/src/cmake/modules/GUDHI_user_version_target.txt b/src/cmake/modules/GUDHI_user_version_target.txt
new file mode 100644
index 00000000..51553e7e
--- /dev/null
+++ b/src/cmake/modules/GUDHI_user_version_target.txt
@@ -0,0 +1,115 @@
+# Some functionnalities requires CMake 2.8.11 minimum
+if (NOT CMAKE_VERSION VERSION_LESS 2.8.11)
+
+ string(TIMESTAMP DATE_AND_TIME "%Y-%m-%d-%H-%M-%S")
+
+ # Definition of the custom target user_version
+ add_custom_target(user_version)
+
+ if(DEFINED USER_VERSION_DIR)
+ # set the GUDHI_USER_VERSION_DIR with USER_VERSION_DIR defined by the user
+ set(GUDHI_USER_VERSION_DIR ${CMAKE_CURRENT_BINARY_DIR}/${USER_VERSION_DIR})
+ else()
+ # set the GUDHI_USER_VERSION_DIR with timestamp and Gudhi version number
+ set(GUDHI_USER_VERSION_DIR ${CMAKE_CURRENT_BINARY_DIR}/${DATE_AND_TIME}_GUDHI_${GUDHI_VERSION})
+ endif()
+
+ set(GUDHI_DOXYGEN_DEPENDENCY user_version)
+
+ add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E
+ make_directory ${GUDHI_USER_VERSION_DIR}
+ COMMENT "user_version creation in ${GUDHI_USER_VERSION_DIR}")
+
+ add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E
+ copy ${CMAKE_SOURCE_DIR}/README ${GUDHI_USER_VERSION_DIR}/README)
+ add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E
+ copy ${CMAKE_SOURCE_DIR}/COPYING ${GUDHI_USER_VERSION_DIR}/COPYING)
+ add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E
+ copy ${CMAKE_SOURCE_DIR}/src/CMakeLists.txt ${GUDHI_USER_VERSION_DIR}/CMakeLists.txt)
+ add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E
+ copy ${CMAKE_SOURCE_DIR}/src/Doxyfile ${GUDHI_USER_VERSION_DIR}/Doxyfile)
+ add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E
+ copy ${CMAKE_SOURCE_DIR}/src/GUDHIConfigVersion.cmake.in ${GUDHI_USER_VERSION_DIR}/GUDHIConfigVersion.cmake.in)
+ add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E
+ copy ${CMAKE_SOURCE_DIR}/src/GUDHIConfig.cmake.in ${GUDHI_USER_VERSION_DIR}/GUDHIConfig.cmake.in)
+ add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E
+ copy ${CMAKE_SOURCE_DIR}/CMakeGUDHIVersion.txt ${GUDHI_USER_VERSION_DIR}/CMakeGUDHIVersion.txt)
+ add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E
+ copy ${CMAKE_SOURCE_DIR}/GUDHIVersion.cmake.in ${GUDHI_USER_VERSION_DIR}/GUDHIVersion.cmake.in)
+
+ add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E
+ copy_directory ${CMAKE_SOURCE_DIR}/biblio ${GUDHI_USER_VERSION_DIR}/biblio)
+ add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E
+ copy_directory ${CMAKE_SOURCE_DIR}/data ${GUDHI_USER_VERSION_DIR}/data)
+ add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E
+ copy_directory ${CMAKE_SOURCE_DIR}/src/cmake ${GUDHI_USER_VERSION_DIR}/cmake)
+ add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E
+ copy_directory ${CMAKE_SOURCE_DIR}/src/debian ${GUDHI_USER_VERSION_DIR}/debian)
+ add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E
+ copy_directory ${CMAKE_SOURCE_DIR}/src/GudhUI ${GUDHI_USER_VERSION_DIR}/GudhUI)
+
+ set(GUDHI_MODULES "common;Alpha_complex;Bitmap_cubical_complex;Contraction;Hasse_complex;Persistent_cohomology;Simplex_tree;Skeleton_blocker;Spatial_searching;Subsampling;Tangential_complex;Witness_complex")
+
+ foreach(GUDHI_MODULE ${GUDHI_MODULES})
+ # doc files
+ file(GLOB GUDHI_DOC_FILES ${CMAKE_SOURCE_DIR}/src/${GUDHI_MODULE}/doc/*)
+
+ foreach(GUDHI_DOC_FILE ${GUDHI_DOC_FILES})
+ get_filename_component(GUDHI_DOC_FILE_NAME ${GUDHI_DOC_FILE} NAME)
+ # GUDHI_DOC_FILE can be a file or a directory
+ if(IS_DIRECTORY ${GUDHI_DOC_FILE})
+ add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E
+ copy_directory ${GUDHI_DOC_FILE} ${GUDHI_USER_VERSION_DIR}/doc/${GUDHI_MODULE}/${GUDHI_DOC_FILE_NAME})
+ else()
+ add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E
+ copy ${GUDHI_DOC_FILE} ${GUDHI_USER_VERSION_DIR}/doc/${GUDHI_MODULE}/${GUDHI_DOC_FILE_NAME})
+ endif()
+ endforeach()
+
+ # example files
+ file(GLOB GUDHI_EXAMPLE_FILES ${CMAKE_SOURCE_DIR}/src/${GUDHI_MODULE}/example/*)
+
+ foreach(GUDHI_EXAMPLE_FILE ${GUDHI_EXAMPLE_FILES})
+ get_filename_component(GUDHI_EXAMPLE_FILE_NAME ${GUDHI_EXAMPLE_FILE} NAME)
+ # GUDHI_EXAMPLE_FILE can be a file or a directory
+ if(IS_DIRECTORY ${GUDHI_EXAMPLE_FILE})
+ add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E
+ copy_directory ${GUDHI_EXAMPLE_FILE} ${GUDHI_USER_VERSION_DIR}/example/${GUDHI_MODULE}/${GUDHI_EXAMPLE_FILE_NAME})
+ else()
+ add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E
+ copy ${GUDHI_EXAMPLE_FILE} ${GUDHI_USER_VERSION_DIR}/example/${GUDHI_MODULE}/${GUDHI_EXAMPLE_FILE_NAME})
+ endif()
+ endforeach()
+
+ # include files
+ file(GLOB GUDHI_INCLUDE_FILES ${CMAKE_SOURCE_DIR}/src/${GUDHI_MODULE}/include/gudhi/*)
+
+ foreach(GUDHI_INCLUDE_FILE ${GUDHI_INCLUDE_FILES})
+ get_filename_component(GUDHI_INCLUDE_FILE_NAME ${GUDHI_INCLUDE_FILE} NAME)
+ # GUDHI_INCLUDE_FILE can be a file or a directory
+ if(IS_DIRECTORY ${GUDHI_INCLUDE_FILE})
+ add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E
+ copy_directory ${GUDHI_INCLUDE_FILE} ${GUDHI_USER_VERSION_DIR}/include/gudhi/${GUDHI_INCLUDE_FILE_NAME})
+ else()
+ add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E
+ copy ${GUDHI_INCLUDE_FILE} ${GUDHI_USER_VERSION_DIR}/include/gudhi/${GUDHI_INCLUDE_FILE_NAME})
+ endif()
+ endforeach()
+
+ # concept files
+ file(GLOB GUDHI_CONCEPT_FILES ${CMAKE_SOURCE_DIR}/src/${GUDHI_MODULE}/concept/*.h)
+
+ foreach(GUDHI_CONCEPT_FILE ${GUDHI_CONCEPT_FILES})
+ get_filename_component(GUDHI_CONCEPT_FILE_NAME ${GUDHI_CONCEPT_FILE} NAME)
+ # GUDHI_CONCEPT_FILE can be a file or a directory
+ if(IS_DIRECTORY ${GUDHI_CONCEPT_FILE})
+ add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E
+ copy_directory ${GUDHI_CONCEPT_FILE} ${GUDHI_USER_VERSION_DIR}/concept/${GUDHI_MODULE}/${GUDHI_CONCEPT_FILE_NAME})
+ else()
+ add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E
+ copy ${GUDHI_CONCEPT_FILE} ${GUDHI_USER_VERSION_DIR}/concept/${GUDHI_MODULE}/${GUDHI_CONCEPT_FILE_NAME})
+ endif()
+ endforeach()
+ endforeach()
+
+endif()
diff --git a/src/cmake/modules/UseTBB.cmake b/src/cmake/modules/UseTBB.cmake
new file mode 100644
index 00000000..e1ef5dfe
--- /dev/null
+++ b/src/cmake/modules/UseTBB.cmake
@@ -0,0 +1,6 @@
+# This module setups the compiler for using TBB library.
+# It assumes that find_package(TBB) was already called.
+
+include_directories ( ${TBB_INCLUDE_DIRS} )
+link_directories( ${TBB_LIBRARY_DIRS} )
+add_definitions( -DNOMINMAX -DGUDHI_USE_TBB )
diff --git a/src/common/doc/Gudhi_banner.jpg b/src/common/doc/Gudhi_banner.jpg
deleted file mode 100644
index ebd3d8af..00000000
--- a/src/common/doc/Gudhi_banner.jpg
+++ /dev/null
Binary files differ
diff --git a/src/common/doc/Gudhi_banner.png b/src/common/doc/Gudhi_banner.png
new file mode 100644
index 00000000..18e8a672
--- /dev/null
+++ b/src/common/doc/Gudhi_banner.png
Binary files differ
diff --git a/src/common/doc/footer.html b/src/common/doc/footer.html
new file mode 100644
index 00000000..7b4cdc5c
--- /dev/null
+++ b/src/common/doc/footer.html
@@ -0,0 +1,29 @@
+<!-- HTML footer for doxygen 1.8.6-->
+<!-- start footer part -->
+<table style="width:100%">
+ <tr class="no-bullet shadow-black">
+ <td class="network-entypo">
+<!--BEGIN PROJECT_NAME--> $projectname
+<!--BEGIN PROJECT_NUMBER-->&#160;Version $projectnumber<!--END PROJECT_NUMBER-->
+<!--BEGIN PROJECT_BRIEF-->&#160;-&#160;$projectbrief<!--END PROJECT_BRIEF-->
+<!--END PROJECT_NAME-->
+ </td>
+ <td class="network-entypo">
+<!--BEGIN GENERATE_TREEVIEW-->
+ $generatedby
+ <a href="http://www.doxygen.org/index.html">
+ <img class="footer" src="$relpath^doxygen.png" alt="doxygen"/></a> $doxygenversion
+<!--END GENERATE_TREEVIEW-->
+ </td>
+ </tr>
+</table>
+
+<!--BEGIN !GENERATE_TREEVIEW-->
+<hr class="footer"/><address class="footer"><small> tralala
+$generatedby &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="$relpath^doxygen.png" alt="doxygen"/>
+</a> $doxygenversion
+</small></address>
+<!--END !GENERATE_TREEVIEW-->
+</body>
+</html>
diff --git a/src/common/doc/header.html b/src/common/doc/header.html
new file mode 100644
index 00000000..a6f3ed9c
--- /dev/null
+++ b/src/common/doc/header.html
@@ -0,0 +1,83 @@
+<!-- HTML header for doxygen 1.8.6-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!-- GUDHI website : class="no-js" lang="en" is necessary -->
+<html xmlns="http://www.w3.org/1999/xhtml" class="no-js" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen $doxygenversion"/>
+<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
+<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
+<!-- GUDHI website css for header BEGIN -->
+<link rel="stylesheet" type="text/css" href="http://gudhi.gforge.inria.fr/assets/css/styles_feeling_responsive.css" />
+<!-- GUDHI website css for header END -->
+<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="$relpath^jquery.js"></script>
+<script type="text/javascript" src="$relpath^dynsections.js"></script>
+$treeview
+$search
+$mathjax
+<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
+$extrastylesheet
+</head>
+<body>
+
+<!-- GUDHI website header BEGIN -->
+<div id="navigation" class="sticky">
+ <nav class="top-bar" role="navigation" data-topbar>
+ <section class="top-bar-section">
+ <ul class="right">
+ <li class="divider"></li>
+ <li><a href="http://gudhi.gforge.inria.fr/contact/">Contact</a></li>
+ </ul>
+ <ul class="left">
+ <li><a href="http://gudhi.gforge.inria.fr/"> <img src="http://gudhi.gforge.inria.fr/assets/img/home.png" alt="&nbsp;&nbsp;GUDHI">&nbsp;&nbsp;GUDHI </a></li>
+ <li class="divider"></li>
+ <li class="has-dropdown">
+ <a href="#">Project</a>
+ <ul class="dropdown">
+ <li><a href="http://gudhi.gforge.inria.fr/people/">People</a></li>
+ <li><a href="http://gudhi.gforge.inria.fr/getinvolved/">Get involved</a></li>
+ <li><a href="http://gudhi.gforge.inria.fr/partners/">Partners and Funding</a></li>
+ <li><a href="http://gudhi.gforge.inria.fr/relatedprojects/">Related projects</a></li>
+ <li><a href="http://gudhi.gforge.inria.fr/theyaretalkingaboutus/">They are talking about us</a></li>
+ </ul>
+ </li>
+ <li class="divider"></li>
+ <li class="has-dropdown">
+ <a href="#">Download</a>
+ <ul class="dropdown">
+ <li><a href="http://gudhi.gforge.inria.fr/licensing/">Licensing</a></li>
+ <li><a href="https://gforge.inria.fr/frs/?group_id=3865" target="_blank">Get the sources</a></li>
+ <li><a href="http://gudhi.gforge.inria.fr/doc/latest/installation.html">Installation manual</a></li>
+ </ul>
+ </li>
+ <li class="divider"></li>
+ <li><a href="http://gudhi.gforge.inria.fr/doc/latest/">Documentation</a></li>
+ <li class="divider"></li>
+ <li><a href="http://gudhi.gforge.inria.fr/interfaces/">Interfaces</a></li>
+ <li class="divider"></li>
+ </ul>
+ </section>
+ </nav>
+</div><!-- /#navigation -->
+<!-- GUDHI website header BEGIN -->
+
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+
+<!--BEGIN TITLEAREA-->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 30px;">
+ <!--BEGIN DISABLE_INDEX-->
+ <!--BEGIN SEARCHENGINE-->
+ <td>$searchbox</td>
+ <!--END SEARCHENGINE-->
+ <!--END DISABLE_INDEX-->
+ </tr>
+ </tbody>
+</table>
+</div>
+<!--END TITLEAREA-->
+<!-- end header part -->
diff --git a/src/common/doc/main_page.h b/src/common/doc/main_page.h
index 315aa0ac..1a2cb6ba 100644
--- a/src/common/doc/main_page.h
+++ b/src/common/doc/main_page.h
@@ -1,72 +1,364 @@
-/**
-\mainpage
-
-\image html "Gudhi_banner.jpg" "" width=20cm
-
-The Gudhi library (Geometric Understanding in Higher Dimensions) is a generic C++ library for
-topological analysis of high-dimensional data whose goal is to provide robust, efficient, flexible and easy to use
-implementations of
-state-of-the-art algorithms and data structures for computational topology.
-This library is part of the <a href="https://project.inria.fr/gudhi/">Gudhi project</a>.
-
-The current release of the library allows to use several data-structures for simplicial complexes :
-simplex tree, Hasse diagram or skeleton-blocker. Several operations can then be done on top of these
-representations such as persistent homology computation or simplification.
-All data-structures are generic and several of their aspects (such as stored elements, policies)
-can be parameterized via template classes.
-We refer to
-\cite gudhilibrary_ICMS14
-for a detailed description of the design of the library.
-
-\section installation Gudhi installation
-
-As Gudhi is a header only library, there is no need to install the library.
-
-Examples of Gudhi headers inclusion can be found in \ref demos.
-
-
-\section compiling Compiling
-
-The library uses c++11 and requires <a href="http://www.boost.org/">Boost</a> with version 1.48.0 or more recent.
-It is a multi-platform library and compiles on Linux, Mac OSX and Visual Studio 2013.
-
-
-\subsection gmp GMP:
-The multi-field persistent homology algorithm requires GMP which is a free library for arbitrary-precision
-arithmetic, operating on signed integers, rational numbers, and floating point numbers.
-
-The following examples require the <a href="http://gmplib.org/">GNU Multiple Precision Arithmetic Library</a> (GMP)
-and will not be built if GMP is not installed:
- - Persistent_cohomology/rips_multifield_persistence
- - Simplex_tree/simplex_tree_from_alpha_shapes_3
-
-Having GMP version 4.2 or higher installed is recommended.
-
-\subsection cgal CGAL:
-CGAL is a C++ library which provides easy access to efficient and reliable geometric algorithms.
-
-The following example requires the <a href="http://www.cgal.org/">Computational Geometry Algorithms Library</a> (CGAL)
-and will not be built if CGAL is not installed:
- - Simplex_tree/simplex_tree_from_alpha_shapes_3
-
-Having CGAL version 4.4 or higher installed is recommended. The procedure to install this library according to
-your operating system is detailed here http://doc.cgal.org/latest/Manual/installation.html
-
-\subsection demos Demos and examples
-
-To build the demos and libraries, run the following commands in a terminal:
+/*! \mainpage
+ * \tableofcontents
+ * \image html "Gudhi_banner.png" "" width=20cm
+ *
+ * \section Introduction Introduction
+ * The Gudhi library (Geometry Understanding in Higher Dimensions) is a generic open source C++ library for
+ * Computational Topology and Topological Data Analysis
+ * (<a class="el" target="_blank" href="https://en.wikipedia.org/wiki/Topological_data_analysis">TDA</a>).
+ * The GUDHI library intends to help the development of new algorithmic solutions in TDA and their transfer to
+ * applications. It provides robust, efficient, flexible and easy to use implementations of state-of-the-art
+ * algorithms and data structures.
+ *
+ * The current release of the GUDHI library includes:
+ *
+ * \li Data structures to represent, construct and manipulate simplicial complexes.
+ * \li Simplification of simplicial complexes by edge contraction.
+ * \li Algorithms to compute persistent homology persistent homology.
+ *
+ * All data-structures are generic and several of their aspects can be parameterized via template classes.
+ * We refer to \cite gudhilibrary_ICMS14 for a detailed description of the design of the library.
+ *
+ \section DataStructures Data structures
+ \subsection AlphaComplexDataStructure Alpha complex
+ \image html "alpha_complex_representation.png" "Alpha complex representation"
+<table border="0">
+ <tr>
+ <td width="25%">
+ <b>Author:</b> Vincent Rouvreau<br>
+ <b>Introduced in:</b> GUDHI 1.3.0<br>
+ <b>Copyright:</b> GPL v3<br>
+ </td>
+ <td width="75%">
+ Alpha_complex is a simplicial complex constructed from the finite cells of a Delaunay Triangulation.<br>
+ The filtration value of each simplex is computed as the square of the circumradius of the simplex if the
+ circumsphere is empty (the simplex is then said to be Gabriel), and as the minimum of the filtration
+ values of the codimension 1 cofaces that make it not Gabriel otherwise.
+ All simplices that have a filtration value strictly greater than a given alpha squared value are not inserted into
+ the complex.<br>
+ <b>User manual:</b> \ref alpha_complex - <b>Reference manual:</b> Gudhi::alpha_complex::Alpha_complex
+ </td>
+ </tr>
+</table>
+ \subsection CubicalComplexDataStructure Cubical complex
+ \image html "Cubical_complex_representation.png" "Cubical complex representation"
+<table border="0">
+ <tr>
+ <td width="25%">
+ <b>Author:</b> Pawel Dlotko<br>
+ <b>Introduced in:</b> GUDHI 1.3.0<br>
+ <b>Copyright:</b> GPL v3<br>
+ </td>
+ <td width="75%">
+ The cubical complex is an example of a structured complex useful in computational mathematics (specially
+ rigorous numerics) and image analysis.<br>
+ <b>User manual:</b> \ref cubical_complex - <b>Reference manual:</b> Gudhi::cubical_complex::Bitmap_cubical_complex
+ </td>
+ </tr>
+</table>
+ \subsection SimplexTreeDataStructure Simplex tree
+ \image html "Simplex_tree_representation.png" "Simplex tree representation"
+<table border="0">
+ <tr>
+ <td width="25%">
+ <b>Author:</b> Cl&eacute;ment Maria<br>
+ <b>Introduced in:</b> GUDHI 1.0.0<br>
+ <b>Copyright:</b> GPL v3<br>
+ </td>
+ <td width="75%">
+ The simplex tree is an efficient and flexible
+ data structure for representing general (filtered) simplicial complexes. The data structure
+ is described in \cite boissonnatmariasimplextreealgorithmica .<br>
+ <b>User manual:</b> \ref simplex_tree - <b>Reference manual:</b> Gudhi::Simplex_tree
+ </td>
+ </tr>
+</table>
+ \subsection SkeletonBlockerDataStructure Skeleton blocker
+ \image html "ds_representation.png" "Skeleton blocker representation"
+<table border="0">
+ <tr>
+ <td width="25%">
+ <b>Author:</b> David Salinas<br>
+ <b>Introduced in:</b> GUDHI 1.1.0<br>
+ <b>Copyright:</b> GPL v3<br>
+ </td>
+ <td width="75%">
+ The Skeleton-Blocker data-structure proposes a light encoding for simplicial complexes by storing only an *implicit*
+ representation of its simplices \cite socg_blockers_2011,\cite blockers2012. Intuitively, it just stores the
+ 1-skeleton of a simplicial complex with a graph and the set of its "missing faces" that is very small in practice.
+ This data-structure handles all simplicial complexes operations such as simplex enumeration or simplex removal but
+ operations that are particularly efficient are operations that do not require simplex enumeration such as edge
+ iteration, link computation or simplex contraction.<br>
+ <b>User manual:</b> \ref skbl - <b>Reference manual:</b> Gudhi::skeleton_blocker::Skeleton_blocker_complex
+ </td>
+ </tr>
+</table>
+ \subsection TangentialComplexDataStructure Tangential complex
+ \image html "tc_examples.png" "Tangential complex representation"
+<table border="0">
+ <tr>
+ <td width="25%">
+ <b>Author:</b> Cl&eacute;ment Jamin<br>
+ <b>Introduced in:</b> GUDHI 1.4.0<br>
+ <b>Copyright:</b> GPL v3<br>
+ </td>
+ <td width="75%">
+ A Tangential Delaunay complex is a <a target="_blank" href="https://en.wikipedia.org/wiki/Simplicial_complex">simplicial complex</a>
+ designed to reconstruct a \f$ k \f$-dimensional manifold embedded in \f$ d \f$-dimensional Euclidean space.
+ The input is a point sample coming from an unknown manifold.
+ The running time depends only linearly on the extrinsic dimension \f$ d \f$
+ and exponentially on the intrinsic dimension \f$ k \f$.<br>
+ <b>User manual:</b> \ref tangential_complex - <b>Reference manual:</b> Gudhi::tangential_complex::Tangential_complex
+ </td>
+ </tr>
+</table>
+ \subsection WitnessComplexDataStructure Witness complex
+ \image html "Witness_complex_representation.png" "Witness complex representation"
+<table border="0">
+ <tr>
+ <td width="25%">
+ <b>Author:</b> Siargey Kachanovich<br>
+ <b>Introduced in:</b> GUDHI 1.3.0<br>
+ <b>Copyright:</b> GPL v3<br>
+ </td>
+ <td width="75%">
+ Witness complex \f$ Wit(W,L) \f$ is a simplicial complex defined on two sets of points in \f$\mathbb{R}^D\f$.
+ The data structure is described in \cite boissonnatmariasimplextreealgorithmica .<br>
+ <b>User manual:</b> \ref witness_complex - <b>Reference manual:</b> Gudhi::witness_complex::SimplicialComplexForWitness
+ </td>
+ </tr>
+</table>
+
+ \section Toolbox Toolbox
+ \subsection ContractionToolbox Contraction
+ \image html "sphere_contraction_representation.png" "Sphere contraction example"
+<table border="0">
+ <tr>
+ <td width="25%">
+ <b>Author:</b> David Salinas<br>
+ <b>Introduced in:</b> GUDHI 1.1.0<br>
+ <b>Copyright:</b> GPL v3<br>
+ </td>
+ <td width="75%">
+ The purpose of this package is to offer a user-friendly interface for edge contraction simplification of huge
+ simplicial complexes. It uses the \ref skbl data-structure whose size remains small during simplification of most
+ used geometrical complexes of topological data analysis such as the Rips or the Delaunay complexes. In practice,
+ the size of this data-structure is even much lower than the total number of simplices.<br>
+ <b>User manual:</b> \ref contr
+ </td>
+ </tr>
+</table>
+ \subsection PersistentCohomologyToolbox Persistent Cohomology
+ \image html "3DTorus_poch.png" "Rips Persistent Cohomology on a 3D Torus"
+<table border="0">
+ <tr>
+ <td width="25%">
+ <b>Author:</b> Cl&eacute;ment Maria<br>
+ <b>Introduced in:</b> GUDHI 1.0.0<br>
+ <b>Copyright:</b> GPL v3<br>
+ </td>
+ <td width="75%">
+ The theory of homology consists in attaching to a topological space a sequence of (homology) groups, capturing
+ global topological features like connected components, holes, cavities, etc. Persistent homology studies the
+ evolution -- birth, life and death -- of these features when the topological space is changing. Consequently, the
+ theory is essentially composed of three elements: topological spaces, their homology groups and an evolution
+ scheme.
+ Computation of persistent cohomology using the algorithm of \cite DBLP:journals/dcg/SilvaMV11 and
+ \cite DBLP:journals/corr/abs-1208-5018 and the Compressed Annotation Matrix implementation of
+ \cite DBLP:conf/esa/BoissonnatDM13 .<br>
+ <b>User manual:</b> \ref persistent_cohomology - <b>Reference manual:</b> Gudhi::persistent_cohomology::Persistent_cohomology
+ </td>
+ </tr>
+</table>
+*/
-\verbatim
-cd /path-to-gudhi/
+/*! \page installation Gudhi installation
+ * \tableofcontents
+ * As Gudhi is a header only library, there is no need to install the library.
+ *
+ * Examples of Gudhi headers inclusion can be found in \ref demos.
+ *
+ * \section compiling Compiling
+ * The library uses c++11 and requires <a target="_blank" href="http://www.boost.org/">Boost</a> with version 1.48.0 or
+ * more recent. It is a multi-platform library and compiles on Linux, Mac OSX and Visual Studio 2015.
+ *
+ * \subsection demos Demos and examples
+ * To build the demos and examples, run the following commands in a terminal:
+\verbatim cd /path-to-gudhi/
mkdir build
cd build/
cmake ..
-make
-\endverbatim
+make \endverbatim
+ * A list of examples is available <a href="examples.html">here</a>.
+ *
+ * \subsection testsuites Test suites
+ * To test your build, run the following command in a terminal:
+ * \verbatim make test \endverbatim
+ *
+ * \section optionallibrary Optional third-party library
+ * \subsection gmp GMP:
+ * The multi-field persistent homology algorithm requires GMP which is a free library for arbitrary-precision
+ * arithmetic, operating on signed integers, rational numbers, and floating point numbers.
+ *
+ * The following example requires the <a target="_blank" href="http://gmplib.org/">GNU Multiple Precision Arithmetic
+ * Library</a> (GMP) and will not be built if GMP is not installed:
+ * \li <a href="_persistent_cohomology_2performance_rips_persistence_8cpp-example.html">
+ * Persistent_cohomology/performance_rips_persistence.cpp</a>
+ * \li <a href="_persistent_cohomology_2rips_multifield_persistence_8cpp-example.html">
+ * Persistent_cohomology/rips_multifield_persistence.cpp</a>
+ *
+ * Having GMP version 4.2 or higher installed is recommended.
+ *
+ * \subsection cgal CGAL:
+ * The \ref alpha_complex data structure and few examples requires CGAL, which is a C++ library which provides easy
+ * access to efficient and reliable geometric algorithms.
+ *
+ * Having CGAL version 4.4 or higher installed is recommended. The procedure to install this library according to
+ * your operating system is detailed here http://doc.cgal.org/latest/Manual/installation.html
+ *
+ * The following examples require the <a target="_blank" href="http://www.cgal.org/">Computational Geometry Algorithms
+ * Library</a> (CGAL \cite cgal:eb-15b) and will not be built if CGAL is not installed:
+ * \li <a href="_persistent_cohomology_2alpha_complex_3d_persistence_8cpp-example.html">
+ * Persistent_cohomology/alpha_complex_3d_persistence.cpp</a>
+ * \li <a href="_simplex_tree_2example_alpha_shapes_3_simplex_tree_from_off_file_8cpp-example.html">
+ * Simplex_tree/example_alpha_shapes_3_simplex_tree_from_off_file.cpp</a>
+ *
+ * The following example requires CGAL version &ge; 4.6:
+ * \li <a href="_witness_complex_2witness_complex_sphere_8cpp-example.html">
+ * Witness_complex/witness_complex_sphere.cpp</a>
+ *
+ * The following example requires CGAL version &ge; 4.7:
+ * \li <a href="_alpha_complex_2_alpha_complex_from_off_8cpp-example.html">
+ * Alpha_complex/Alpha_complex_from_off.cpp</a>
+ * \li <a href="_alpha_complex_2_alpha_complex_from_points_8cpp-example.html">
+ * Alpha_complex/Alpha_complex_from_points.cpp</a>
+ * \li <a href="_persistent_cohomology_2alpha_complex_persistence_8cpp-example.html">
+ * Persistent_cohomology/alpha_complex_persistence.cpp</a>
+ * \li <a href="_persistent_cohomology_2periodic_alpha_complex_3d_persistence_8cpp-example.html">
+ * Persistent_cohomology/periodic_alpha_complex_3d_persistence.cpp</a>
+ * \li <a href="_persistent_cohomology_2custom_persistence_sort_8cpp-example.html">
+ * Persistent_cohomology/custom_persistence_sort.cpp</a>
+ *
+ * \subsection eigen3 Eigen3:
+ * The \ref alpha_complex data structure and few examples requires
+ * <a target="_blank" href="http://eigen.tuxfamily.org/">Eigen3</a> is a C++ template library for linear algebra:
+ * matrices, vectors, numerical solvers, and related algorithms.
+ *
+ * The following example requires the <a target="_blank" href="http://eigen.tuxfamily.org/">Eigen3</a> and will not be
+ * built if Eigen3 is not installed:
+ * \li <a href="_alpha_complex_2_alpha_complex_from_off_8cpp-example.html">
+ * Alpha_complex/Alpha_complex_from_off.cpp</a> (requires also Eigen3)
+ * \li <a href="_alpha_complex_2_alpha_complex_from_points_8cpp-example.html">
+ * Alpha_complex/Alpha_complex_from_points.cpp</a> (requires also Eigen3)
+ * \li <a href="_persistent_cohomology_2alpha_complex_persistence_8cpp-example.html">
+ * Persistent_cohomology/alpha_complex_persistence.cpp</a>
+ * \li <a href="_persistent_cohomology_2periodic_alpha_complex_3d_persistence_8cpp-example.html">
+ * Persistent_cohomology/periodic_alpha_complex_3d_persistence.cpp</a>
+ * \li <a href="_persistent_cohomology_2custom_persistence_sort_8cpp-example.html">
+ * Persistent_cohomology/custom_persistence_sort.cpp</a>
+ *
+ * \subsection tbb Threading Building Blocks:
+ * <a target="_blank" href="https://www.threadingbuildingblocks.org/">Intel&reg; TBB</a> lets you easily write parallel
+ * C++ programs that take full advantage of multicore performance, that are portable and composable, and that have
+ * future-proof scalability.
+ *
+ * Having Intel&reg; TBB installed is recommended to parallelize and accelerate some GUDHI computations.
+ *
+ * The following examples are using Intel&reg; TBB if installed:
+ * \li <a href="_alpha_complex_2_alpha_complex_from_off_8cpp-example.html">
+ * Alpha_complex/Alpha_complex_from_off.cpp</a>
+ * \li <a href="_alpha_complex_2_alpha_complex_from_points_8cpp-example.html">
+ * Alpha_complex/Alpha_complex_from_points.cpp</a>
+ * \li <a href="_bitmap_cubical_complex_2_bitmap_cubical_complex_8cpp-example.html">
+ * Bitmap_cubical_complex/Bitmap_cubical_complex.cpp</a>
+ * \li <a href="_bitmap_cubical_complex_2_bitmap_cubical_complex_periodic_boundary_conditions_8cpp-example.html">
+ * Bitmap_cubical_complex/Bitmap_cubical_complex_periodic_boundary_conditions.cpp</a>
+ * \li <a href="_bitmap_cubical_complex_2_random_bitmap_cubical_complex_8cpp-example.html">
+ * Bitmap_cubical_complex/Random_bitmap_cubical_complex.cpp</a>
+ * \li <a href="_persistent_cohomology_2alpha_complex_3d_persistence_8cpp-example.html">
+ * Persistent_cohomology/alpha_complex_3d_persistence.cpp</a>
+ * \li <a href="_persistent_cohomology_2alpha_complex_persistence_8cpp-example.html">
+ * Persistent_cohomology/alpha_complex_persistence.cpp</a>
+ * \li <a href="_simplex_tree_2simple_simplex_tree_8cpp-example.html">
+ * Simplex_tree/simple_simplex_tree.cpp</a>
+ * \li <a href="_simplex_tree_2example_alpha_shapes_3_simplex_tree_from_off_file_8cpp-example.html">
+ * Simplex_tree/example_alpha_shapes_3_simplex_tree_from_off_file.cpp</a>
+ * \li <a href="_simplex_tree_2simplex_tree_from_cliques_of_graph_8cpp-example.html">
+ * Simplex_tree/simplex_tree_from_cliques_of_graph.cpp</a>
+ * \li <a href="_persistent_cohomology_2alpha_complex_3d_persistence_8cpp-example.html">
+ * Persistent_cohomology/alpha_complex_3d_persistence.cpp</a>
+ * \li <a href="_persistent_cohomology_2alpha_complex_persistence_8cpp-example.html">
+ * Persistent_cohomology/alpha_complex_persistence.cpp</a>
+ * \li <a href="_persistent_cohomology_2rips_persistence_via_boundary_matrix_8cpp-example.html">
+ * Persistent_cohomology/rips_persistence_via_boundary_matrix.cpp</a>
+ * \li <a href="_persistent_cohomology_2performance_rips_persistence_8cpp-example.html">
+ * Persistent_cohomology/performance_rips_persistence.cpp</a>
+ * \li <a href="_persistent_cohomology_2persistence_from_file_8cpp-example.html">
+ * Persistent_cohomology/persistence_from_file.cpp</a>
+ * \li <a href="_persistent_cohomology_2persistence_from_simple_simplex_tree_8cpp-example.html">
+ * Persistent_cohomology/persistence_from_simple_simplex_tree.cpp</a>
+ * \li <a href="_persistent_cohomology_2plain_homology_8cpp-example.html">
+ * Persistent_cohomology/plain_homology.cpp</a>
+ * \li <a href="_persistent_cohomology_2rips_multifield_persistence_8cpp-example.html">
+ * Persistent_cohomology/rips_multifield_persistence.cpp</a>
+ * \li <a href="_persistent_cohomology_2rips_persistence_8cpp-example.html">
+ * Persistent_cohomology/rips_persistence.cpp</a>
+ * \li <a href="_persistent_cohomology_2periodic_alpha_complex_3d_persistence_8cpp-example.html">
+ * Persistent_cohomology/periodic_alpha_complex_3d_persistence.cpp</a>
+ * \li <a href="_persistent_cohomology_2custom_persistence_sort_8cpp-example.html">
+ * Persistent_cohomology/custom_persistence_sort.cpp</a>
+ *
+ * \section Contributions Bug reports and contributions
+ * Please help us improving the quality of the GUDHI library. You may report bugs or suggestions to:
+ * \verbatim Contact: gudhi-users@lists.gforge.inria.fr \endverbatim
+ *
+ * Gudhi is open to external contributions. If you want to join our development team, please contact us.
+ *
+*/
-\details
+/*! \page Citation Acknowledging the GUDHI library
+ * We kindly ask users to cite the GUDHI library as appropriately as possible in their papers, and to mention the use
+ * of the GUDHI library on the web pages of their projects using GUDHI and provide us with links to these web pages.
+ * Feel free to contact us in case you have any question or remark on this topic.
+ *
+ * We provide \ref GudhiBibtex entries for the modules of the User and Reference Manual, as well as for publications
+ * directly related to the GUDHI library.
+ * \section GudhiBibtex GUDHI bibtex
+ * \verbinclude biblio/how_to_cite_gudhi.bib
+*/
-\copyright GNU General Public License v3.
-\verbatim Contact: gudhi-users@lists.gforge.inria.fr \endverbatim
+// List of Gudhi examples - Doxygen needs at least a file tag to analyse comments
+/*! @file Examples
+ * @example Alpha_complex/Alpha_complex_from_off.cpp
+ * @example Alpha_complex/Alpha_complex_from_points.cpp
+ * @example Bitmap_cubical_complex/Bitmap_cubical_complex.cpp
+ * @example Bitmap_cubical_complex/Bitmap_cubical_complex_periodic_boundary_conditions.cpp
+ * @example Bitmap_cubical_complex/Random_bitmap_cubical_complex.cpp
+ * @example common/example_CGAL_3D_points_off_reader.cpp
+ * @example common/example_CGAL_points_off_reader.cpp
+ * @example Contraction/Garland_heckbert.cpp
+ * @example Contraction/Rips_contraction.cpp
+ * @example Persistent_cohomology/alpha_complex_3d_persistence.cpp
+ * @example Persistent_cohomology/alpha_complex_persistence.cpp
+ * @example Persistent_cohomology/rips_persistence_via_boundary_matrix.cpp
+ * @example Persistent_cohomology/performance_rips_persistence.cpp
+ * @example Persistent_cohomology/periodic_alpha_complex_3d_persistence.cpp
+ * @example Persistent_cohomology/persistence_from_file.cpp
+ * @example Persistent_cohomology/persistence_from_simple_simplex_tree.cpp
+ * @example Persistent_cohomology/plain_homology.cpp
+ * @example Persistent_cohomology/rips_multifield_persistence.cpp
+ * @example Persistent_cohomology/rips_persistence.cpp
+ * @example Persistent_cohomology/custom_persistence_sort.cpp
+ * @example Simplex_tree/mini_simplex_tree.cpp
+ * @example Simplex_tree/simple_simplex_tree.cpp
+ * @example Simplex_tree/example_alpha_shapes_3_simplex_tree_from_off_file.cpp
+ * @example Simplex_tree/simplex_tree_from_cliques_of_graph.cpp
+ * @example Skeleton_blocker/Skeleton_blocker_from_simplices.cpp
+ * @example Skeleton_blocker/Skeleton_blocker_iteration.cpp
+ * @example Skeleton_blocker/Skeleton_blocker_link.cpp
+ * @example Tangential_complex/example_basic.cpp
+ * @example Tangential_complex/example_with_perturb.cpp
+ * @example Witness_complex/witness_complex_from_file.cpp
+ * @example Witness_complex/witness_complex_sphere.cpp
+ */
-*/
diff --git a/src/common/doc/stylesheet.css b/src/common/doc/stylesheet.css
new file mode 100644
index 00000000..1df177a4
--- /dev/null
+++ b/src/common/doc/stylesheet.css
@@ -0,0 +1,1367 @@
+/* The standard CSS for doxygen 1.8.6 */
+
+body, table, div, p, dl {
+ font: 400 14px/22px Roboto,sans-serif;
+}
+
+/* @group Heading Levels */
+
+h1.groupheader {
+ font-size: 150%;
+}
+
+.title {
+ font: 400 14px/28px Roboto,sans-serif;
+ font-size: 150%;
+ font-weight: bold;
+ margin: 10px 2px;
+}
+
+h2.groupheader {
+ border-bottom: 1px solid #879ECB;
+ color: #354C7B;
+ font-size: 150%;
+ font-weight: normal;
+ margin-top: 1.75em;
+ padding-top: 8px;
+ padding-bottom: 4px;
+ width: 100%;
+}
+
+h3.groupheader {
+ font-size: 100%;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ -webkit-transition: text-shadow 0.5s linear;
+ -moz-transition: text-shadow 0.5s linear;
+ -ms-transition: text-shadow 0.5s linear;
+ -o-transition: text-shadow 0.5s linear;
+ transition: text-shadow 0.5s linear;
+ margin-right: 15px;
+}
+
+h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow {
+ text-shadow: 0 0 15px cyan;
+}
+
+dt {
+ font-weight: bold;
+}
+
+div.multicol {
+ -moz-column-gap: 1em;
+ -webkit-column-gap: 1em;
+ -moz-column-count: 3;
+ -webkit-column-count: 3;
+}
+
+p.startli, p.startdd {
+ margin-top: 2px;
+}
+
+p.starttd {
+ margin-top: 0px;
+}
+
+p.endli {
+ margin-bottom: 0px;
+}
+
+p.enddd {
+ margin-bottom: 4px;
+}
+
+p.endtd {
+ margin-bottom: 2px;
+}
+
+/* @end */
+
+caption {
+ font-weight: bold;
+}
+
+span.legend {
+ font-size: 70%;
+ text-align: center;
+}
+
+h3.version {
+ font-size: 90%;
+ text-align: center;
+}
+
+div.qindex, div.navtab{
+ background-color: #EBEFF6;
+ border: 1px solid #A3B4D7;
+ text-align: center;
+}
+
+div.qindex, div.navpath {
+ width: 100%;
+ line-height: 140%;
+}
+
+div.navtab {
+ margin-right: 15px;
+}
+
+/* @group Link Styling */
+
+a {
+ color: #3D578C;
+ font-weight: normal;
+ text-decoration: none;
+}
+
+.contents a:visited {
+ color: #4665A2;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+a.qindex {
+ font-weight: bold;
+}
+
+a.qindexHL {
+ font-weight: bold;
+ background-color: #9CAFD4;
+ color: #ffffff;
+ border: 1px double #869DCA;
+}
+
+.contents a.qindexHL:visited {
+ color: #ffffff;
+}
+
+a.el {
+ font-weight: bold;
+}
+
+a.elRef {
+}
+
+a.code, a.code:visited, a.line, a.line:visited {
+ color: #4665A2;
+}
+
+a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited {
+ color: #4665A2;
+}
+
+/* @end */
+
+dl.el {
+ margin-left: -1cm;
+}
+
+pre.fragment {
+ border: 1px solid #C4CFE5;
+ background-color: #FBFCFD;
+ padding: 4px 6px;
+ margin: 4px 8px 4px 2px;
+ overflow: auto;
+ word-wrap: break-word;
+ font-size: 9pt;
+ line-height: 125%;
+ font-family: monospace, fixed;
+ font-size: 105%;
+}
+
+div.fragment {
+ padding: 4px 6px;
+ margin: 4px 8px 4px 2px;
+ background-color: #FBFCFD;
+ border: 1px solid #C4CFE5;
+}
+
+div.line {
+ font-family: monospace, fixed;
+ font-size: 13px;
+ min-height: 13px;
+ line-height: 1.0;
+ text-wrap: unrestricted;
+ white-space: -moz-pre-wrap; /* Moz */
+ white-space: -pre-wrap; /* Opera 4-6 */
+ white-space: -o-pre-wrap; /* Opera 7 */
+ white-space: pre-wrap; /* CSS3 */
+ word-wrap: break-word; /* IE 5.5+ */
+ text-indent: -53px;
+ padding-left: 53px;
+ padding-bottom: 0px;
+ margin: 0px;
+ -webkit-transition-property: background-color, box-shadow;
+ -webkit-transition-duration: 0.5s;
+ -moz-transition-property: background-color, box-shadow;
+ -moz-transition-duration: 0.5s;
+ -ms-transition-property: background-color, box-shadow;
+ -ms-transition-duration: 0.5s;
+ -o-transition-property: background-color, box-shadow;
+ -o-transition-duration: 0.5s;
+ transition-property: background-color, box-shadow;
+ transition-duration: 0.5s;
+}
+
+div.line.glow {
+ background-color: cyan;
+ box-shadow: 0 0 10px cyan;
+}
+
+
+span.lineno {
+ padding-right: 4px;
+ text-align: right;
+ border-right: 2px solid #0F0;
+ background-color: #E8E8E8;
+ white-space: pre;
+}
+span.lineno a {
+ background-color: #D8D8D8;
+}
+
+span.lineno a:hover {
+ background-color: #C8C8C8;
+}
+
+div.ah {
+ background-color: black;
+ font-weight: bold;
+ color: #ffffff;
+ margin-bottom: 3px;
+ margin-top: 3px;
+ padding: 0.2em;
+ border: solid thin #333;
+ border-radius: 0.5em;
+ -webkit-border-radius: .5em;
+ -moz-border-radius: .5em;
+ box-shadow: 2px 2px 3px #999;
+ -webkit-box-shadow: 2px 2px 3px #999;
+ -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px;
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444));
+ background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000);
+}
+
+div.groupHeader {
+ margin-left: 16px;
+ margin-top: 12px;
+ font-weight: bold;
+}
+
+div.groupText {
+ margin-left: 16px;
+ font-style: italic;
+}
+
+body {
+ background-color: white;
+ color: black;
+ margin: 0;
+}
+
+div.contents {
+ margin-top: 10px;
+ margin-left: 12px;
+ margin-right: 8px;
+}
+
+td.indexkey {
+ background-color: #EBEFF6;
+ font-weight: bold;
+ border: 1px solid #C4CFE5;
+ margin: 2px 0px 2px 0;
+ padding: 2px 10px;
+ white-space: nowrap;
+ vertical-align: top;
+}
+
+td.indexvalue {
+ background-color: #EBEFF6;
+ border: 1px solid #C4CFE5;
+ padding: 2px 10px;
+ margin: 2px 0px;
+}
+
+tr.memlist {
+ background-color: #EEF1F7;
+}
+
+p.formulaDsp {
+ text-align: center;
+}
+
+img.formulaDsp {
+
+}
+
+img.formulaInl {
+ vertical-align: middle;
+}
+
+div.center {
+ text-align: center;
+ margin-top: 0px;
+ margin-bottom: 0px;
+ padding: 0px;
+}
+
+div.center img {
+ border: 0px;
+}
+
+address.footer {
+ text-align: right;
+ padding-right: 12px;
+}
+
+img.footer {
+ border: 0px;
+ vertical-align: middle;
+}
+
+/* @group Code Colorization */
+
+span.keyword {
+ color: #008000
+}
+
+span.keywordtype {
+ color: #604020
+}
+
+span.keywordflow {
+ color: #e08000
+}
+
+span.comment {
+ color: #800000
+}
+
+span.preprocessor {
+ color: #806020
+}
+
+span.stringliteral {
+ color: #002080
+}
+
+span.charliteral {
+ color: #008080
+}
+
+span.vhdldigit {
+ color: #ff00ff
+}
+
+span.vhdlchar {
+ color: #000000
+}
+
+span.vhdlkeyword {
+ color: #700070
+}
+
+span.vhdllogic {
+ color: #ff0000
+}
+
+blockquote {
+ background-color: #F7F8FB;
+ border-left: 2px solid #9CAFD4;
+ margin: 0 24px 0 4px;
+ padding: 0 12px 0 16px;
+}
+
+/* @end */
+
+/*
+.search {
+ color: #003399;
+ font-weight: bold;
+}
+
+form.search {
+ margin-bottom: 0px;
+ margin-top: 0px;
+}
+
+input.search {
+ font-size: 75%;
+ color: #000080;
+ font-weight: normal;
+ background-color: #e8eef2;
+}
+*/
+
+td.tiny {
+ font-size: 75%;
+}
+
+.dirtab {
+ padding: 4px;
+ border-collapse: collapse;
+ border: 1px solid #A3B4D7;
+}
+
+th.dirtab {
+ background: #EBEFF6;
+ font-weight: bold;
+}
+
+hr {
+ height: 0px;
+ border: none;
+ border-top: 1px solid #4A6AAA;
+}
+
+hr.footer {
+ height: 1px;
+}
+
+/* @group Member Descriptions */
+
+table.memberdecls {
+ border-spacing: 0px;
+ padding: 0px;
+}
+
+.memberdecls td, .fieldtable tr {
+ -webkit-transition-property: background-color, box-shadow;
+ -webkit-transition-duration: 0.5s;
+ -moz-transition-property: background-color, box-shadow;
+ -moz-transition-duration: 0.5s;
+ -ms-transition-property: background-color, box-shadow;
+ -ms-transition-duration: 0.5s;
+ -o-transition-property: background-color, box-shadow;
+ -o-transition-duration: 0.5s;
+ transition-property: background-color, box-shadow;
+ transition-duration: 0.5s;
+}
+
+.memberdecls td.glow, .fieldtable tr.glow {
+ background-color: cyan;
+ box-shadow: 0 0 15px cyan;
+}
+
+.mdescLeft, .mdescRight,
+.memItemLeft, .memItemRight,
+.memTemplItemLeft, .memTemplItemRight, .memTemplParams {
+ background-color: #F9FAFC;
+ border: none;
+ margin: 4px;
+ padding: 1px 0 0 8px;
+}
+
+.mdescLeft, .mdescRight {
+ padding: 0px 8px 4px 8px;
+ color: #555;
+}
+
+.memSeparator {
+ border-bottom: 1px solid #DEE4F0;
+ line-height: 1px;
+ margin: 0px;
+ padding: 0px;
+}
+
+.memItemLeft, .memTemplItemLeft {
+ white-space: nowrap;
+}
+
+.memItemRight {
+ width: 100%;
+}
+
+.memTemplParams {
+ color: #4665A2;
+ white-space: nowrap;
+ font-size: 80%;
+}
+
+/* @end */
+
+/* @group Member Details */
+
+/* Styles for detailed member documentation */
+
+.memtemplate {
+ font-size: 80%;
+ color: #4665A2;
+ font-weight: normal;
+ margin-left: 9px;
+}
+
+.memnav {
+ background-color: #EBEFF6;
+ border: 1px solid #A3B4D7;
+ text-align: center;
+ margin: 2px;
+ margin-right: 15px;
+ padding: 2px;
+}
+
+.mempage {
+ width: 100%;
+}
+
+.memitem {
+ padding: 0;
+ margin-bottom: 10px;
+ margin-right: 5px;
+ -webkit-transition: box-shadow 0.5s linear;
+ -moz-transition: box-shadow 0.5s linear;
+ -ms-transition: box-shadow 0.5s linear;
+ -o-transition: box-shadow 0.5s linear;
+ transition: box-shadow 0.5s linear;
+ display: table !important;
+ width: 100%;
+}
+
+.memitem.glow {
+ box-shadow: 0 0 15px cyan;
+}
+
+.memname {
+ font-weight: bold;
+ margin-left: 6px;
+}
+
+.memname td {
+ vertical-align: bottom;
+}
+
+.memproto, dl.reflist dt {
+ border-top: 1px solid #A8B8D9;
+ border-left: 1px solid #A8B8D9;
+ border-right: 1px solid #A8B8D9;
+ padding: 6px 0px 6px 0px;
+ color: #253555;
+ font-weight: bold;
+ text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9);
+ background-image:url('nav_f.png');
+ background-repeat:repeat-x;
+ background-color: #E2E8F2;
+ /* opera specific markup */
+ box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+ border-top-right-radius: 4px;
+ border-top-left-radius: 4px;
+ /* firefox specific markup */
+ -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
+ -moz-border-radius-topright: 4px;
+ -moz-border-radius-topleft: 4px;
+ /* webkit specific markup */
+ -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+ -webkit-border-top-right-radius: 4px;
+ -webkit-border-top-left-radius: 4px;
+
+}
+
+.memdoc, dl.reflist dd {
+ border-bottom: 1px solid #A8B8D9;
+ border-left: 1px solid #A8B8D9;
+ border-right: 1px solid #A8B8D9;
+ padding: 6px 10px 2px 10px;
+ background-color: #FBFCFD;
+ border-top-width: 0;
+ background-image:url('nav_g.png');
+ background-repeat:repeat-x;
+ background-color: #FFFFFF;
+ /* opera specific markup */
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
+ box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+ /* firefox specific markup */
+ -moz-border-radius-bottomleft: 4px;
+ -moz-border-radius-bottomright: 4px;
+ -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
+ /* webkit specific markup */
+ -webkit-border-bottom-left-radius: 4px;
+ -webkit-border-bottom-right-radius: 4px;
+ -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+}
+
+dl.reflist dt {
+ padding: 5px;
+}
+
+dl.reflist dd {
+ margin: 0px 0px 10px 0px;
+ padding: 5px;
+}
+
+.paramkey {
+ text-align: right;
+}
+
+.paramtype {
+ white-space: nowrap;
+}
+
+.paramname {
+ color: #602020;
+ white-space: nowrap;
+}
+.paramname em {
+ font-style: normal;
+}
+.paramname code {
+ line-height: 14px;
+}
+
+.params, .retval, .exception, .tparams {
+ margin-left: 0px;
+ padding-left: 0px;
+}
+
+.params .paramname, .retval .paramname {
+ font-weight: bold;
+ vertical-align: top;
+}
+
+.params .paramtype {
+ font-style: italic;
+ vertical-align: top;
+}
+
+.params .paramdir {
+ font-family: "courier new",courier,monospace;
+ vertical-align: top;
+}
+
+table.mlabels {
+ border-spacing: 0px;
+}
+
+td.mlabels-left {
+ width: 100%;
+ padding: 0px;
+}
+
+td.mlabels-right {
+ vertical-align: bottom;
+ padding: 0px;
+ white-space: nowrap;
+}
+
+span.mlabels {
+ margin-left: 8px;
+}
+
+span.mlabel {
+ background-color: #728DC1;
+ border-top:1px solid #5373B4;
+ border-left:1px solid #5373B4;
+ border-right:1px solid #C4CFE5;
+ border-bottom:1px solid #C4CFE5;
+ text-shadow: none;
+ color: white;
+ margin-right: 4px;
+ padding: 2px 3px;
+ border-radius: 3px;
+ font-size: 7pt;
+ white-space: nowrap;
+ vertical-align: middle;
+}
+
+
+
+/* @end */
+
+/* these are for tree view when not used as main index */
+
+div.directory {
+ margin: 10px 0px;
+ border-top: 1px solid #A8B8D9;
+ border-bottom: 1px solid #A8B8D9;
+ width: 100%;
+}
+
+.directory table {
+ border-collapse:collapse;
+}
+
+.directory td {
+ margin: 0px;
+ padding: 0px;
+ vertical-align: top;
+}
+
+.directory td.entry {
+ white-space: nowrap;
+ padding-right: 6px;
+ padding-top: 3px;
+}
+
+.directory td.entry a {
+ outline:none;
+}
+
+.directory td.entry a img {
+ border: none;
+}
+
+.directory td.desc {
+ width: 100%;
+ padding-left: 6px;
+ padding-right: 6px;
+ padding-top: 3px;
+ border-left: 1px solid rgba(0,0,0,0.05);
+}
+
+.directory tr.even {
+ padding-left: 6px;
+ background-color: #F7F8FB;
+}
+
+.directory img {
+ vertical-align: -30%;
+}
+
+.directory .levels {
+ white-space: nowrap;
+ width: 100%;
+ text-align: right;
+ font-size: 9pt;
+}
+
+.directory .levels span {
+ cursor: pointer;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: #3D578C;
+}
+
+div.dynheader {
+ margin-top: 8px;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+address {
+ font-style: normal;
+ color: #2A3D61;
+}
+
+table.doxtable {
+ border-collapse:collapse;
+ margin-top: 4px;
+ margin-bottom: 4px;
+}
+
+table.doxtable td, table.doxtable th {
+ border: 1px solid #2D4068;
+ padding: 3px 7px 2px;
+}
+
+table.doxtable th {
+ background-color: #374F7F;
+ color: #FFFFFF;
+ font-size: 110%;
+ padding-bottom: 4px;
+ padding-top: 5px;
+}
+
+table.fieldtable {
+ /*width: 100%;*/
+ margin-bottom: 10px;
+ border: 1px solid #A8B8D9;
+ border-spacing: 0px;
+ -moz-border-radius: 4px;
+ -webkit-border-radius: 4px;
+ border-radius: 4px;
+ -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px;
+ -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15);
+ box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15);
+}
+
+.fieldtable td, .fieldtable th {
+ padding: 3px 7px 2px;
+}
+
+.fieldtable td.fieldtype, .fieldtable td.fieldname {
+ white-space: nowrap;
+ border-right: 1px solid #A8B8D9;
+ border-bottom: 1px solid #A8B8D9;
+ vertical-align: top;
+}
+
+.fieldtable td.fieldname {
+ padding-top: 3px;
+}
+
+.fieldtable td.fielddoc {
+ border-bottom: 1px solid #A8B8D9;
+ /*width: 100%;*/
+}
+
+.fieldtable td.fielddoc p:first-child {
+ margin-top: 0px;
+}
+
+.fieldtable td.fielddoc p:last-child {
+ margin-bottom: 2px;
+}
+
+.fieldtable tr:last-child td {
+ border-bottom: none;
+}
+
+.fieldtable th {
+ background-image:url('nav_f.png');
+ background-repeat:repeat-x;
+ background-color: #E2E8F2;
+ font-size: 90%;
+ color: #253555;
+ padding-bottom: 4px;
+ padding-top: 5px;
+ text-align:left;
+ -moz-border-radius-topleft: 4px;
+ -moz-border-radius-topright: 4px;
+ -webkit-border-top-left-radius: 4px;
+ -webkit-border-top-right-radius: 4px;
+ border-top-left-radius: 4px;
+ border-top-right-radius: 4px;
+ border-bottom: 1px solid #A8B8D9;
+}
+
+
+.tabsearch {
+ top: 0px;
+ left: 10px;
+ height: 36px;
+ background-image: url('tab_b.png');
+ z-index: 101;
+ overflow: hidden;
+ font-size: 13px;
+}
+
+.navpath ul
+{
+ font-size: 11px;
+ background-image:url('tab_b.png');
+ background-repeat:repeat-x;
+ background-position: 0 -5px;
+ height:30px;
+ line-height:30px;
+ color:#8AA0CC;
+ border:solid 1px #C2CDE4;
+ overflow:hidden;
+ margin:0px;
+ padding:0px;
+}
+
+.navpath li
+{
+ list-style-type:none;
+ float:left;
+ padding-left:10px;
+ padding-right:15px;
+ background-image:url('bc_s.png');
+ background-repeat:no-repeat;
+ background-position:right;
+ color:#364D7C;
+}
+
+.navpath li.navelem a
+{
+ height:32px;
+ display:block;
+ text-decoration: none;
+ outline: none;
+ color: #283A5D;
+ font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif;
+ text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9);
+ text-decoration: none;
+}
+
+.navpath li.navelem a:hover
+{
+ color:#6884BD;
+}
+
+.navpath li.footer
+{
+ list-style-type:none;
+ float:right;
+ padding-left:10px;
+ padding-right:15px;
+ background-image:none;
+ background-repeat:no-repeat;
+ background-position:right;
+ color:#364D7C;
+ font-size: 8pt;
+}
+
+
+div.summary
+{
+ float: right;
+ font-size: 8pt;
+ padding-right: 5px;
+ width: 50%;
+ text-align: right;
+}
+
+div.summary a
+{
+ white-space: nowrap;
+}
+
+div.ingroups
+{
+ font-size: 8pt;
+ width: 50%;
+ text-align: left;
+}
+
+div.ingroups a
+{
+ white-space: nowrap;
+}
+
+div.header
+{
+ background-image:url('nav_h.png');
+ background-repeat:repeat-x;
+ background-color: #F9FAFC;
+ margin: 0px;
+ border-bottom: 1px solid #C4CFE5;
+}
+
+div.headertitle
+{
+ padding: 5px 5px 5px 10px;
+}
+
+dl
+{
+ padding: 0 0 0 10px;
+}
+
+/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */
+dl.section
+{
+ margin-left: 0px;
+ padding-left: 0px;
+}
+
+dl.note
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #D0C000;
+}
+
+dl.warning, dl.attention
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #FF0000;
+}
+
+dl.pre, dl.post, dl.invariant
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #00D000;
+}
+
+dl.deprecated
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #505050;
+}
+
+dl.todo
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #00C0E0;
+}
+
+dl.test
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #3030E0;
+}
+
+dl.bug
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #C08050;
+}
+
+dl.section dd {
+ margin-bottom: 6px;
+}
+
+
+#projectlogo
+{
+ text-align: center;
+ vertical-align: bottom;
+ border-collapse: separate;
+}
+
+#projectlogo img
+{
+ border: 0px none;
+}
+
+#projectname
+{
+ border: 0px none;
+ font: 300% Tahoma, Arial,sans-serif;
+ margin: 0px;
+ padding: 2px 0px;
+}
+
+#projectbrief
+{
+ font: 60% Tahoma, Arial,sans-serif;
+ margin: 0px;
+ padding: 0px;
+}
+
+#projectnumber
+{
+ font: 80% Tahoma, Arial,sans-serif;
+ margin: 0px;
+ padding: 0px;
+}
+
+#titlearea
+{
+ padding: 0px;
+ margin: 0px;
+ width: 100%;
+ border-bottom: 1px solid #5373B4;
+}
+
+.image
+{
+ text-align: center;
+}
+
+.dotgraph
+{
+ text-align: center;
+}
+
+.mscgraph
+{
+ text-align: center;
+}
+
+.diagraph
+{
+ text-align: center;
+}
+
+.caption
+{
+ font-weight: bold;
+}
+
+div.zoom
+{
+ border: 1px solid #90A5CE;
+}
+
+dl.citelist {
+ margin-bottom:50px;
+}
+
+dl.citelist dt {
+ color:#334975;
+ float:left;
+ font-weight:bold;
+ margin-right:10px;
+ padding:5px;
+}
+
+dl.citelist dd {
+ margin:2px 0;
+ padding:5px 0;
+}
+
+div.toc {
+ padding: 14px 25px;
+ background-color: #F4F6FA;
+ border: 1px solid #D8DFEE;
+ border-radius: 7px 7px 7px 7px;
+ float: right;
+ height: auto;
+ margin: 0 20px 10px 10px;
+ width: 200px;
+}
+
+div.toc li {
+ background: url("bdwn.png") no-repeat scroll 0 5px transparent;
+ font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif;
+ margin-top: 5px;
+ padding-left: 10px;
+ padding-top: 2px;
+}
+
+div.toc h3 {
+ font: bold 12px/1.2 Arial,FreeSans,sans-serif;
+ color: #4665A2;
+ border-bottom: 0 none;
+ margin: 0;
+}
+
+div.toc ul {
+ list-style: none outside none;
+ border: medium none;
+ padding: 0px;
+}
+
+div.toc li.level1 {
+ margin-left: 0px;
+}
+
+div.toc li.level2 {
+ margin-left: 15px;
+}
+
+div.toc li.level3 {
+ margin-left: 30px;
+}
+
+div.toc li.level4 {
+ margin-left: 45px;
+}
+
+.inherit_header {
+ font-weight: bold;
+ color: gray;
+ cursor: pointer;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.inherit_header td {
+ padding: 6px 0px 2px 5px;
+}
+
+.inherit {
+ display: none;
+}
+
+tr.heading h2 {
+ margin-top: 12px;
+ margin-bottom: 4px;
+}
+
+/* tooltip related style info */
+
+.ttc {
+ position: absolute;
+ display: none;
+}
+
+#powerTip {
+ cursor: default;
+ white-space: nowrap;
+ background-color: white;
+ border: 1px solid gray;
+ border-radius: 4px 4px 4px 4px;
+ box-shadow: 1px 1px 7px gray;
+ display: none;
+ font-size: smaller;
+ max-width: 80%;
+ opacity: 0.9;
+ padding: 1ex 1em 1em;
+ position: absolute;
+ z-index: 2147483647;
+}
+
+#powerTip div.ttdoc {
+ color: grey;
+ font-style: italic;
+}
+
+#powerTip div.ttname a {
+ font-weight: bold;
+}
+
+#powerTip div.ttname {
+ font-weight: bold;
+}
+
+#powerTip div.ttdeci {
+ color: #006318;
+}
+
+#powerTip div {
+ margin: 0px;
+ padding: 0px;
+ font: 12px/16px Roboto,sans-serif;
+}
+
+#powerTip:before, #powerTip:after {
+ content: "";
+ position: absolute;
+ margin: 0px;
+}
+
+#powerTip.n:after, #powerTip.n:before,
+#powerTip.s:after, #powerTip.s:before,
+#powerTip.w:after, #powerTip.w:before,
+#powerTip.e:after, #powerTip.e:before,
+#powerTip.ne:after, #powerTip.ne:before,
+#powerTip.se:after, #powerTip.se:before,
+#powerTip.nw:after, #powerTip.nw:before,
+#powerTip.sw:after, #powerTip.sw:before {
+ border: solid transparent;
+ content: " ";
+ height: 0;
+ width: 0;
+ position: absolute;
+}
+
+#powerTip.n:after, #powerTip.s:after,
+#powerTip.w:after, #powerTip.e:after,
+#powerTip.nw:after, #powerTip.ne:after,
+#powerTip.sw:after, #powerTip.se:after {
+ border-color: rgba(255, 255, 255, 0);
+}
+
+#powerTip.n:before, #powerTip.s:before,
+#powerTip.w:before, #powerTip.e:before,
+#powerTip.nw:before, #powerTip.ne:before,
+#powerTip.sw:before, #powerTip.se:before {
+ border-color: rgba(128, 128, 128, 0);
+}
+
+#powerTip.n:after, #powerTip.n:before,
+#powerTip.ne:after, #powerTip.ne:before,
+#powerTip.nw:after, #powerTip.nw:before {
+ top: 100%;
+}
+
+#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after {
+ border-top-color: #ffffff;
+ border-width: 10px;
+ margin: 0px -10px;
+}
+#powerTip.n:before {
+ border-top-color: #808080;
+ border-width: 11px;
+ margin: 0px -11px;
+}
+#powerTip.n:after, #powerTip.n:before {
+ left: 50%;
+}
+
+#powerTip.nw:after, #powerTip.nw:before {
+ right: 14px;
+}
+
+#powerTip.ne:after, #powerTip.ne:before {
+ left: 14px;
+}
+
+#powerTip.s:after, #powerTip.s:before,
+#powerTip.se:after, #powerTip.se:before,
+#powerTip.sw:after, #powerTip.sw:before {
+ bottom: 100%;
+}
+
+#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after {
+ border-bottom-color: #ffffff;
+ border-width: 10px;
+ margin: 0px -10px;
+}
+
+#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before {
+ border-bottom-color: #808080;
+ border-width: 11px;
+ margin: 0px -11px;
+}
+
+#powerTip.s:after, #powerTip.s:before {
+ left: 50%;
+}
+
+#powerTip.sw:after, #powerTip.sw:before {
+ right: 14px;
+}
+
+#powerTip.se:after, #powerTip.se:before {
+ left: 14px;
+}
+
+#powerTip.e:after, #powerTip.e:before {
+ left: 100%;
+}
+#powerTip.e:after {
+ border-left-color: #ffffff;
+ border-width: 10px;
+ top: 50%;
+ margin-top: -10px;
+}
+#powerTip.e:before {
+ border-left-color: #808080;
+ border-width: 11px;
+ top: 50%;
+ margin-top: -11px;
+}
+
+#powerTip.w:after, #powerTip.w:before {
+ right: 100%;
+}
+#powerTip.w:after {
+ border-right-color: #ffffff;
+ border-width: 10px;
+ top: 50%;
+ margin-top: -10px;
+}
+#powerTip.w:before {
+ border-right-color: #808080;
+ border-width: 11px;
+ top: 50%;
+ margin-top: -11px;
+}
+
+@media print
+{
+ #top { display: none; }
+ #side-nav { display: none; }
+ #nav-path { display: none; }
+ body { overflow:visible; }
+ h1, h2, h3, h4, h5, h6 { page-break-after: avoid; }
+ .summary { display: none; }
+ .memitem { page-break-inside: avoid; }
+ #doc-content
+ {
+ margin-left:0 !important;
+ height:auto !important;
+ width:auto !important;
+ overflow:inherit;
+ display:inline;
+ }
+}
+
diff --git a/src/common/example/CMakeLists.txt b/src/common/example/CMakeLists.txt
new file mode 100644
index 00000000..b0c6d69a
--- /dev/null
+++ b/src/common/example/CMakeLists.txt
@@ -0,0 +1,21 @@
+cmake_minimum_required(VERSION 2.6)
+project(Common_examples)
+
+add_executable ( vector_double_off_reader example_vector_double_points_off_reader.cpp )
+target_link_libraries(vector_double_off_reader ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY})
+add_test(vector_double_off_reader ${CMAKE_CURRENT_BINARY_DIR}/vector_double_off_reader ${CMAKE_SOURCE_DIR}/data/points/SO3_10000.off)
+
+if(CGAL_FOUND)
+ add_executable ( cgal_3D_off_reader example_CGAL_3D_points_off_reader.cpp )
+ target_link_libraries(cgal_3D_off_reader ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY})
+ add_test(cgal_3D_off_reader ${CMAKE_CURRENT_BINARY_DIR}/cgal_3D_off_reader ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off)
+
+ # need CGAL 4.7
+ if (NOT CGAL_VERSION VERSION_LESS 4.7.0)
+ if (EIGEN3_FOUND)
+ add_executable ( cgal_off_reader example_CGAL_points_off_reader.cpp )
+ target_link_libraries(cgal_off_reader ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY})
+ add_test(cgal_off_reader ${CMAKE_CURRENT_BINARY_DIR}/cgal_off_reader ${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off)
+ endif(EIGEN3_FOUND)
+ endif (NOT CGAL_VERSION VERSION_LESS 4.7.0)
+endif()
diff --git a/src/common/example/cgal3Doffreader_result.txt b/src/common/example/cgal3Doffreader_result.txt
new file mode 100644
index 00000000..f992c8e3
--- /dev/null
+++ b/src/common/example/cgal3Doffreader_result.txt
@@ -0,0 +1,8 @@
+Point[1] = (0.959535, -0.418347, 0.302237)
+Point[2] = (2.16795, 1.85348, -0.52312)
+Point[3] = (-2.38753, -1.50911, -0.565889)
+Point[4] = (-2.70428, -1.25688, 0.188394)
+Point[5] = (-1.22932, -1.64337, -0.998632)
+...
+Point[300] = (-0.56244, 2.6018, -0.749591)
+
diff --git a/src/common/example/cgaloffreader_result.txt b/src/common/example/cgaloffreader_result.txt
new file mode 100644
index 00000000..1deb8dbd
--- /dev/null
+++ b/src/common/example/cgaloffreader_result.txt
@@ -0,0 +1,7 @@
+Point[0] = 1 1
+Point[1] = 7 0
+Point[2] = 4 6
+Point[3] = 9 6
+Point[4] = 0 14
+Point[5] = 2 19
+Point[6] = 9 17
diff --git a/src/common/example/example_CGAL_3D_points_off_reader.cpp b/src/common/example/example_CGAL_3D_points_off_reader.cpp
new file mode 100644
index 00000000..d48bb17d
--- /dev/null
+++ b/src/common/example/example_CGAL_3D_points_off_reader.cpp
@@ -0,0 +1,41 @@
+#include <gudhi/Points_3D_off_io.h>
+
+#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
+using Point_3 = Kernel::Point_3;
+
+void usage(char * const progName) {
+ std::cerr << "Usage: " << progName << " inputFile.off" << std::endl;
+ exit(-1);
+}
+
+int main(int argc, char **argv) {
+ if (argc != 2) {
+ std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl;
+ usage(argv[0]);
+ }
+
+ std::string offInputFile(argv[1]);
+ // Read the OFF file (input file name given as parameter) and triangulate points
+ Gudhi::Points_3D_off_reader<Point_3> off_reader(offInputFile);
+ // Check the read operation was correct
+ if (!off_reader.is_valid()) {
+ std::cerr << "Unable to read file " << offInputFile << std::endl;
+ usage(argv[0]);
+ }
+
+ // Retrieve the triangulation
+ std::vector<Point_3> point_cloud = off_reader.get_point_cloud();
+
+ int n {0};
+ for (auto point : point_cloud) {
+ ++n;
+ std::cout << "Point[" << n << "] = (" << point[0] << ", " << point[1] << ", " << point[2] << ")\n";
+ }
+ return 0;
+}
diff --git a/src/common/example/example_CGAL_points_off_reader.cpp b/src/common/example/example_CGAL_points_off_reader.cpp
new file mode 100644
index 00000000..4522174a
--- /dev/null
+++ b/src/common/example/example_CGAL_points_off_reader.cpp
@@ -0,0 +1,46 @@
+#include <gudhi/Points_off_io.h>
+
+// For CGAL points type in dimension d
+// cf. http://doc.cgal.org/latest/Kernel_d/classCGAL_1_1Point__d.html
+#include <CGAL/Epick_d.h>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+using Kernel = CGAL::Epick_d< CGAL::Dynamic_dimension_tag >;
+using Point_d = Kernel::Point_d;
+
+void usage(char * const progName) {
+ std::cerr << "Usage: " << progName << " inputFile.off" << std::endl;
+ exit(-1);
+}
+
+int main(int argc, char **argv) {
+ if (argc != 2) {
+ std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl;
+ usage(argv[0]);
+ }
+
+ std::string offInputFile(argv[1]);
+ // Read the OFF file (input file name given as parameter) and triangulate points
+ Gudhi::Points_off_reader<Point_d> off_reader(offInputFile);
+ // Check the read operation was correct
+ if (!off_reader.is_valid()) {
+ std::cerr << "Unable to read file " << offInputFile << std::endl;
+ usage(argv[0]);
+ }
+
+ // Retrieve the triangulation
+ std::vector<Point_d> point_cloud = off_reader.get_point_cloud();
+
+ int n {0};
+ for (auto point : point_cloud) {
+ std::cout << "Point[" << n << "] = ";
+ for (std::size_t i {0}; i < point.size(); i++)
+ std::cout << point[i] << " ";
+ std::cout << "\n";
+ ++n;
+ }
+ return 0;
+}
diff --git a/src/common/example/example_vector_double_points_off_reader.cpp b/src/common/example/example_vector_double_points_off_reader.cpp
new file mode 100644
index 00000000..8aecb26e
--- /dev/null
+++ b/src/common/example/example_vector_double_points_off_reader.cpp
@@ -0,0 +1,41 @@
+#include <gudhi/Points_off_io.h>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+using Point_d = std::vector<double>;
+
+void usage(char * const progName) {
+ std::cerr << "Usage: " << progName << " inputFile.off" << std::endl;
+ exit(-1);
+}
+
+int main(int argc, char **argv) {
+ if (argc != 2) {
+ std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl;
+ usage(argv[0]);
+ }
+
+ std::string offInputFile(argv[1]);
+ // Read the OFF file (input file name given as parameter) and triangulate points
+ Gudhi::Points_off_reader<Point_d> off_reader(offInputFile);
+ // Check the read operation was correct
+ if (!off_reader.is_valid()) {
+ std::cerr << "Unable to read file " << offInputFile << std::endl;
+ usage(argv[0]);
+ }
+
+ // Retrieve the triangulation
+ std::vector<Point_d> point_cloud = off_reader.get_point_cloud();
+
+ int n {0};
+ for (auto point : point_cloud) {
+ std::cout << "Point[" << n << "] = ";
+ for (std::size_t i {0}; i < point.size(); i++)
+ std::cout << point[i] << " ";
+ std::cout << "\n";
+ ++n;
+ }
+ return 0;
+}
diff --git a/src/common/include/gudhi/Clock.h b/src/common/include/gudhi/Clock.h
index 04c6ffb9..77f196ca 100644
--- a/src/common/include/gudhi/Clock.h
+++ b/src/common/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/src/common/include/gudhi/Debug_utils.h b/src/common/include/gudhi/Debug_utils.h
new file mode 100644
index 00000000..8ed3b7b3
--- /dev/null
+++ b/src/common/include/gudhi/Debug_utils.h
@@ -0,0 +1,57 @@
+/* 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 DEBUG_UTILS_H_
+#define DEBUG_UTILS_H_
+
+#include <iostream>
+
+#ifndef NDEBUG
+ // GUDHI_DEBUG is the Gudhi official flag for debug mode.
+ #define GUDHI_DEBUG
+#endif
+
+// GUDHI_CHECK throw an exception if expression is false in debug mode, but does nothing in release mode
+// Could assert in release mode, but cmake sets NDEBUG (for "NO DEBUG") in this mode, means assert does nothing.
+#ifdef GUDHI_DEBUG
+ #define GUDHI_CHECK(expression, excpt) 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
+
+// #define DBG_VERBOSE
+#ifdef DBG_VERBOSE
+ #define DBG(a) std::cout << "DBG: " << (a) << std::endl
+ #define DBGMSG(a, b) std::cout << "DBG: " << a << b << std::endl
+ #define DBGVALUE(a) std::cout << "DBG: " << #a << ": " << a << std::endl
+ #define DBGCONT(a) std::cout << "DBG: container " << #a << " -> "; for (auto x : a) std::cout << x << ","; std::cout << std::endl
+#else
+ #define DBG(a) (void) 0
+ #define DBGMSG(a, b) (void) 0
+ #define DBGVALUE(a) (void) 0
+ #define DBGCONT(a) (void) 0
+#endif
+
+#endif // DEBUG_UTILS_H_
diff --git a/src/common/include/gudhi/Off_reader.h b/src/common/include/gudhi/Off_reader.h
index 81b9e634..4fcd2af2 100644
--- a/src/common/include/gudhi/Off_reader.h
+++ b/src/common/include/gudhi/Off_reader.h
@@ -31,40 +31,35 @@
#include <iterator>
#include <string>
#include <vector>
+#include <fstream>
namespace Gudhi {
-/**
- * Read an off file and calls a visitor methods while reading it.
- * An off file must have its first/snd line in this format :
- * OFF
- * num_vert num_faces num_edges
- *
- * A noff file must have its first/snd line in this format :
- * nOFF
- * dim num_vert num_faces num_edges
- *
- * The number of edges num_edges is optional and can be left to zero.
+/** \brief OFF file reader top class visitor.
+ *
+ * OFF file must be conform to format described here :
+ * http://www.geomview.org/docs/html/OFF.html
*/
class Off_reader {
public:
Off_reader(std::ifstream& stream) : stream_(stream) { }
- // Off_reader(const std::string& name):stream_(name){
- // if(!stream_.is_open())
- // std::cerr <<"could not open file \n";
- // }
~Off_reader() {
stream_.close();
}
- /**
- * read an off file and calls the following methods :
- * void init(int dim,int num_vertices,int num_faces,int num_edges); //num_edges may not be set
- * void point(const std::vector<double>& point);
- * void maximal_face(const std::list<int>& face);
- * void done();
- * of the visitor when reading a point or a maximal face.
+ /** \brief
+ * Read an OFF file and calls the following methods :
+ *
+ * <CODE>void init(int dim,int num_vertices,int num_faces,int num_edges); // from file header - num_edges may not be set
+ *
+ * void point(const std::vector<double>& point); // for each point read
+ *
+ * void maximal_face(const std::list<int>& face); // for each face read
+ *
+ * void done(); // upon file read is finished</CODE>
+ *
+ * of the visitor when reading a point or a maximal face. Edges are not taken into account.
*/
template<typename OffVisitor>
bool read(OffVisitor& off_visitor) {
@@ -118,7 +113,7 @@ class Off_reader {
if (!goto_next_uncomment_line(line)) return false;
std::istringstream iss(line);
- if (is_off_file) {
+ if ((is_off_file) && (!is_noff_file)) {
off_info_.dim = 3;
if (!(iss >> off_info_.num_vertices >> off_info_.num_faces >> off_info_.num_edges)) {
std::cerr << "incorrect number of vertices/faces/edges\n";
@@ -126,8 +121,8 @@ class Off_reader {
}
} else {
if (!(iss >> off_info_.dim >> off_info_.num_vertices >> off_info_.num_faces >> off_info_.num_edges)) {
- std::cerr << "incorrect number of vertices/faces/edges\n";
- return false;
+ std::cerr << "incorrect number of vertices/faces/edges\n";
+ return false;
}
}
off_visitor.init(off_info_.dim, off_info_.num_vertices, off_info_.num_faces, off_info_.num_edges);
@@ -138,7 +133,7 @@ class Off_reader {
bool goto_next_uncomment_line(std::string& uncomment_line) {
uncomment_line.clear();
do
- std::getline(stream_, uncomment_line); while (uncomment_line[0] == '%'); // || uncomment_line.empty());
+ std::getline(stream_, uncomment_line); while (uncomment_line[0] == '%');
return (uncomment_line.size() > 0 && uncomment_line[0] != '%');
}
@@ -166,7 +161,7 @@ class Off_reader {
iss >> num_face_vertices;
std::vector<int> face;
face.assign(std::istream_iterator<int>(iss), std::istream_iterator<int>());
- if (face.size() != off_info_.dim) return false;
+ // if (face.size() != (off_info_.dim + 1)) return false;
visitor.maximal_face(face);
}
return true;
diff --git a/src/common/include/gudhi/Points_3D_off_io.h b/src/common/include/gudhi/Points_3D_off_io.h
new file mode 100644
index 00000000..b0d24998
--- /dev/null
+++ b/src/common/include/gudhi/Points_3D_off_io.h
@@ -0,0 +1,202 @@
+/* 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 POINTS_3D_OFF_IO_H_
+#define POINTS_3D_OFF_IO_H_
+
+#include <gudhi/Off_reader.h>
+
+#include <string>
+#include <vector>
+#include <fstream>
+#include <map>
+
+namespace Gudhi {
+
+/**
+ * @brief OFF file visitor implementation according to Off_reader in order to read points from an OFF file.
+ */
+template<typename Point_3>
+class Points_3D_off_visitor_reader {
+ private:
+ std::vector<Point_3> point_cloud_;
+ bool valid_;
+
+ public:
+ /** @brief Off_reader visitor init implementation.
+ *
+ * The init parameters are set from OFF file header.
+ * Dimension value is required and the value must be 3.
+ *
+ * @param[in] dim space dimension of vertices.
+ * @param[in] num_vertices number of vertices in the OFF file (not used).
+ * @param[in] num_faces number of faces in the OFF file (not used).
+ * @param[in] num_edges number of edges in the OFF file (not used).
+ */
+ void init(int dim, int num_vertices, int num_faces, int num_edges) {
+#ifdef DEBUG_TRACES
+ std::cout << "Points_3D_off_visitor_reader::init - dim=" << dim << " - num_vertices=" <<
+ num_vertices << " - num_faces=" << num_faces << " - num_edges=" << num_edges << std::endl;
+#endif // DEBUG_TRACES
+ if (dim == 3) {
+ valid_ = true;
+ } else {
+ valid_ = false;
+ std::cerr << "Points_3D_off_reader::Points_3D_off_reader cannot read OFF files in dimension " << dim << "\n";
+ }
+
+ if (num_faces > 0) {
+ std::cerr << "Points_3D_off_visitor_reader::init faces are not taken into account from OFF file for Points.\n";
+ }
+ if (num_edges > 0) {
+ std::cerr << "Points_3D_off_visitor_reader::init edges are not taken into account from OFF file for Points.\n";
+ }
+ }
+
+ /** @brief Off_reader visitor point implementation.
+ *
+ * The point function is called on each vertex line from OFF file.
+ * This function inserts the vertex in the vector of points.
+ *
+ * @param[in] point vector of vertex coordinates.
+ *
+ * @details
+ * Point_3 must have a constructor with the following form:
+ *
+ * @code template<class InputIterator > Point_3::Point_3(double x, double y, double z) @endcode
+ */
+ void point(const std::vector<double>& point) {
+ if (valid_) {
+#ifdef DEBUG_TRACES
+ std::cout << "Points_3D_off_visitor_reader::point ";
+ for (auto coordinate : point) {
+ std::cout << coordinate << " | ";
+ }
+ std::cout << std::endl;
+#endif // DEBUG_TRACES
+ // Fill the point cloud
+ point_cloud_.push_back(Point_3(point[0], point[1], point[2]));
+ }
+ }
+
+ // Off_reader visitor maximal_face implementation - Only points are read
+
+ void maximal_face(const std::vector<int>& face) { }
+
+ // Off_reader visitor done implementation - Only points are read
+
+ void done() { }
+
+ /** @brief Point cloud getter.
+ *
+ * @return The point cloud.
+ */
+ const std::vector<Point_3>& get_point_cloud() const {
+ return point_cloud_;
+ }
+
+ /** @brief Returns if the OFF file read operation was successful or not.
+ *
+ * @return OFF file read status.
+ */
+ bool is_valid() const {
+ return valid_;
+ }
+};
+
+/**
+ * \@brief OFF file reader implementation in order to read dimension 3 points from an OFF file.
+ *
+ * @details
+ * This class is using the Points_3D_off_visitor_reader to visit the OFF file according to Off_reader.
+ *
+ * Point_3 must have a constructor with the following form:
+ *
+ * @code template<class InputIterator > Point_3::Point_3(double x, double y, double z) @endcode
+ *
+ * @section point3doffioexample Example
+ *
+ * This example loads points from an OFF file and builds a vector of CGAL points in dimension 3.
+ * Then, it is asked to display the points.
+ *
+ * @include common/example_CGAL_3D_points_off_reader.cpp
+ *
+ * When launching:
+ *
+ * @code $> ./cgal3Doffreader ../../data/points/tore3D_300.off
+ * @endcode
+ *
+ * the program output is:
+ *
+ * @include common/cgal3Doffreader_result.txt
+ */
+template<typename Point_3>
+class Points_3D_off_reader {
+ public:
+ /** @brief Reads the OFF file and constructs a vector of points from the points
+ * that are in the OFF file.
+ *
+ * @param[in] name_file OFF file to read.
+ *
+ * @post Check with is_valid() function to see if read operation was successful.
+ */
+ Points_3D_off_reader(const std::string& name_file)
+ : valid_(false) {
+ std::ifstream stream(name_file);
+ if (stream.is_open()) {
+ Off_reader off_reader(stream);
+ Points_3D_off_visitor_reader<Point_3> off_visitor;
+ valid_ = off_reader.read(off_visitor);
+ valid_ = valid_ && off_visitor.is_valid();
+ if (valid_) {
+ point_cloud = off_visitor.get_point_cloud();
+ }
+ } else {
+ std::cerr << "Points_3D_off_reader::Points_3D_off_reader could not open file " << name_file << "\n";
+ }
+ }
+
+ /** @brief Returns if the OFF file read operation was successful or not.
+ *
+ * @return OFF file read status.
+ */
+ bool is_valid() const {
+ return valid_;
+ }
+
+ /** @brief Point cloud getter.
+ *
+ * @return point_cloud.
+ */
+ const std::vector<Point_3>& get_point_cloud() const {
+ return point_cloud;
+ }
+
+ private:
+ /** @brief point_cloud.*/
+ std::vector<Point_3> point_cloud;
+ /** @brief OFF file read status.*/
+ bool valid_;
+};
+
+} // namespace Gudhi
+
+#endif // POINTS_3D_OFF_IO_H_
diff --git a/src/common/include/gudhi/Points_off_io.h b/src/common/include/gudhi/Points_off_io.h
new file mode 100644
index 00000000..29af8a8a
--- /dev/null
+++ b/src/common/include/gudhi/Points_off_io.h
@@ -0,0 +1,183 @@
+/* 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 POINTS_OFF_IO_H_
+#define POINTS_OFF_IO_H_
+
+#include <gudhi/Off_reader.h>
+
+#include <string>
+#include <vector>
+#include <fstream>
+#include <map>
+
+namespace Gudhi {
+
+/**
+ * \brief OFF file visitor implementation according to Off_reader in order to read points from an OFF file.
+ */
+template<typename Point_d>
+class Points_off_visitor_reader {
+ private:
+ std::vector<Point_d> point_cloud;
+
+ public:
+ /** \brief Off_reader visitor init implementation.
+ *
+ * The init parameters are set from OFF file header.
+ * Dimension value is required in order to construct a vector of points.
+ *
+ * @param[in] dim space dimension of vertices.
+ * @param[in] num_vertices number of vertices in the OFF file (not used).
+ * @param[in] num_faces number of faces in the OFF file (not used).
+ * @param[in] num_edges number of edges in the OFF file (not used).
+ */
+ void init(int dim, int num_vertices, int num_faces, int num_edges) {
+#ifdef DEBUG_TRACES
+ std::cout << "Points_off_visitor_reader::init - dim=" << dim << " - num_vertices=" <<
+ num_vertices << " - num_faces=" << num_faces << " - num_edges=" << num_edges << std::endl;
+#endif // DEBUG_TRACES
+ if (num_faces > 0) {
+ std::cerr << "Points_off_visitor_reader::init faces are not taken into account from OFF file for Points.\n";
+ }
+ if (num_edges > 0) {
+ std::cerr << "Points_off_visitor_reader::init edges are not taken into account from OFF file for Points.\n";
+ }
+ }
+
+ /** @brief Off_reader visitor point implementation.
+ *
+ * The point function is called on each vertex line from OFF file.
+ * This function inserts the vertex in the vector of points.
+ *
+ * @param[in] point vector of vertex coordinates.
+ *
+ * @details
+ * Point_d must have a constructor with the following form:
+ *
+ * @code template<class InputIterator > Point_d::Point_d(InputIterator first, InputIterator last) @endcode
+ *
+ */
+ void point(const std::vector<double>& point) {
+#ifdef DEBUG_TRACES
+ std::cout << "Points_off_visitor_reader::point ";
+ for (auto coordinate : point) {
+ std::cout << coordinate << " | ";
+ }
+ std::cout << std::endl;
+#endif // DEBUG_TRACES
+ // Fill the point cloud
+ point_cloud.push_back(Point_d(point.begin(), point.end()));
+ }
+
+ // Off_reader visitor maximal_face implementation - Only points are read
+ void maximal_face(const std::vector<int>& face) { }
+
+ // Off_reader visitor done implementation - Only points are read
+ void done() { }
+
+ /** \brief Point cloud getter.
+ *
+ * @return point_cloud.
+ */
+ const std::vector<Point_d>& get_point_cloud() const {
+ return point_cloud;
+ }
+};
+
+/**
+ * \brief OFF file reader implementation in order to read points from an OFF file.
+ *
+ * This class is using the Points_off_visitor_reader to visit the OFF file according to Off_reader.
+ *
+ * Point_d must have a constructor with the following form:
+ *
+ * \code template<class InputIterator > Point_d::Point_d(int d, InputIterator first, InputIterator last) \endcode
+ *
+ * where d is the point dimension.
+ *
+ * \section pointoffioexample Example
+ *
+ * This example loads points from an OFF file and builds a vector of points (vector of double).
+ * Then, it is asked to display the points.
+ *
+ * \include common/example_vector_double_points_off_reader.cpp
+ *
+ * When launching:
+ *
+ * \code $> ./vector_double_off_reader ../../data/points/alphacomplexdoc.off
+ * \endcode
+ *
+ * the program output is:
+ *
+ * \include common/cgaloffreader_result.txt
+ */
+template<typename Point_d>
+class Points_off_reader {
+ public:
+ /** \brief Reads the OFF file and constructs a vector of points from the points
+ * that are in the OFF file.
+ *
+ * @param[in] name_file OFF file to read.
+ *
+ * \post Check with is_valid() function to see if read operation was successful.
+ */
+ Points_off_reader(const std::string& name_file)
+ : valid_(false) {
+ std::ifstream stream(name_file);
+ if (stream.is_open()) {
+ Off_reader off_reader(stream);
+ Points_off_visitor_reader<Point_d> off_visitor;
+ valid_ = off_reader.read(off_visitor);
+ if (valid_) {
+ point_cloud = off_visitor.get_point_cloud();
+ }
+ } else {
+ std::cerr << "Points_off_reader::Points_off_reader could not open file " << name_file << "\n";
+ }
+ }
+
+ /** \brief Returns if the OFF file read operation was successful or not.
+ *
+ * @return OFF file read status.
+ */
+ bool is_valid() const {
+ return valid_;
+ }
+
+ /** \brief Point cloud getter.
+ *
+ * @return point_cloud.
+ */
+ const std::vector<Point_d>& get_point_cloud() const {
+ return point_cloud;
+ }
+
+ private:
+ /** \brief point_cloud.*/
+ std::vector<Point_d> point_cloud;
+ /** \brief OFF file read status.*/
+ bool valid_;
+};
+
+} // namespace Gudhi
+
+#endif // POINTS_OFF_IO_H_
diff --git a/src/common/include/gudhi/Test.h b/src/common/include/gudhi/Test.h
deleted file mode 100644
index 6024c822..00000000
--- a/src/common/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/src/common/include/gudhi/allocator.h b/src/common/include/gudhi/allocator.h
new file mode 100644
index 00000000..4ede14e4
--- /dev/null
+++ b/src/common/include/gudhi/allocator.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): Marc Glisse
+ *
+ * Copyright (C) 2015 INRIA Saclay - Ile de 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 ALLOCATOR_H_
+#define ALLOCATOR_H_
+
+#include <memory>
+#include <utility>
+
+namespace Gudhi {
+
+/** \private
+ * An allocator that can be used to build an uninitialized vector.
+ */
+template <class T, class Base = std::allocator<T>>
+struct no_init_allocator : Base {
+ typedef std::allocator_traits<Base> Base_traits;
+ template <class U> struct rebind {
+ typedef no_init_allocator<U, typename Base_traits::template rebind_alloc<U>> other;
+ };
+
+ // Inherit constructors.
+ using Base::Base;
+
+ // Do nothing: that's the whole point!
+ template<class P>
+ void construct(P*) noexcept {}
+
+ template<class P, class...U> void construct(P*p, U&&...u) {
+ Base_traits::construct(*(Base*)this, p, std::forward<U>(u)...);
+ }
+};
+
+} // namespace Gudhi
+
+#endif // ALLOCATOR_H_
diff --git a/src/common/include/gudhi/console_color.h b/src/common/include/gudhi/console_color.h
new file mode 100644
index 00000000..c4671da3
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi/distance_functions.h b/src/common/include/gudhi/distance_functions.h
index e5c79ded..cd518581 100644
--- a/src/common/include/gudhi/distance_functions.h
+++ b/src/common/include/gudhi/distance_functions.h
@@ -23,6 +23,8 @@
#ifndef DISTANCE_FUNCTIONS_H_
#define DISTANCE_FUNCTIONS_H_
+#include <cmath> // for std::sqrt
+
/* Compute the Euclidean distance between two Points given
* by a range of coordinates. The points are assumed to have
* the same dimension. */
@@ -35,7 +37,7 @@ double euclidean_distance(Point &p1, Point &p2) {
double tmp = *it1 - *it2;
dist += tmp*tmp;
}
- return sqrt(dist);
+ return std::sqrt(dist);
}
#endif // DISTANCE_FUNCTIONS_H_
diff --git a/src/common/include/gudhi/random_point_generators.h b/src/common/include/gudhi/random_point_generators.h
new file mode 100644
index 00000000..3050b7ea
--- /dev/null
+++ b/src/common/include/gudhi/random_point_generators.h
@@ -0,0 +1,477 @@
+/* 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;
+ if (current_point.size() == 2 * dim) {
+ *out++ = k.construct_point_d_object()(
+ static_cast<int> (current_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::Translated_point_d k_transl =
+ k.translated_point_d_object();
+ typename Kernel::Compute_coordinate_d k_coord =
+ k.compute_coordinate_d_object();
+ for (std::size_t i = 0; i < num_points;) {
+ Point p_sphere = *generator++; // First 3 coords
+
+ FT alpha = rng.get_double(0, 6.2832);
+ std::vector<FT> pt(5);
+ pt[0] = k_coord(p_sphere, 0);
+ pt[1] = k_coord(p_sphere, 1);
+ pt[2] = k_coord(p_sphere, 2);
+ pt[3] = std::cos(alpha);
+ pt[4] = std::sin(alpha);
+ Point p(pt.begin(), pt.end());
+ points.push_back(p);
+ ++i;
+ }
+ return points;
+}
+
+// a = big radius, b = small radius
+template <typename Kernel>
+std::vector<typename Kernel::Point_d> generate_points_on_klein_bottle_3D(std::size_t num_points, double a, double b,
+ bool uniform = false) {
+ typedef typename Kernel::Point_d Point;
+ typedef typename Kernel::FT FT;
+ Kernel k;
+ CGAL::Random rng;
+
+ // if uniform
+ std::size_t num_lines = (std::size_t)sqrt(num_points);
+
+ std::vector<Point> points;
+ points.reserve(num_points);
+ for (std::size_t i = 0; i < num_points;) {
+ FT u, v;
+ if (uniform) {
+ std::size_t k1 = i / num_lines;
+ std::size_t k2 = i % num_lines;
+ u = 6.2832 * k1 / num_lines;
+ v = 6.2832 * k2 / num_lines;
+ } else {
+ u = rng.get_double(0, 6.2832);
+ v = rng.get_double(0, 6.2832);
+ }
+ double tmp = cos(u / 2) * sin(v) - sin(u / 2) * sin(2. * v);
+ Point p = construct_point(k,
+ (a + b * tmp) * cos(u),
+ (a + b * tmp) * sin(u),
+ b * (sin(u / 2) * sin(v) + cos(u / 2) * sin(2. * v)));
+ points.push_back(p);
+ ++i;
+ }
+ return points;
+}
+
+// a = big radius, b = small radius
+template <typename Kernel>
+std::vector<typename Kernel::Point_d> generate_points_on_klein_bottle_4D(std::size_t num_points, double a, double b,
+ double noise = 0., bool uniform = false) {
+ typedef typename Kernel::Point_d Point;
+ typedef typename Kernel::FT FT;
+ Kernel k;
+ CGAL::Random rng;
+
+ // if uniform
+ std::size_t num_lines = (std::size_t)sqrt(num_points);
+
+ std::vector<Point> points;
+ points.reserve(num_points);
+ for (std::size_t i = 0; i < num_points;) {
+ FT u, v;
+ if (uniform) {
+ std::size_t k1 = i / num_lines;
+ std::size_t k2 = i % num_lines;
+ u = 6.2832 * k1 / num_lines;
+ v = 6.2832 * k2 / num_lines;
+ } else {
+ u = rng.get_double(0, 6.2832);
+ v = rng.get_double(0, 6.2832);
+ }
+ Point p = construct_point(k,
+ (a + b * cos(v)) * cos(u) + (noise == 0. ? 0. : rng.get_double(0, noise)),
+ (a + b * cos(v)) * sin(u) + (noise == 0. ? 0. : rng.get_double(0, noise)),
+ b * sin(v) * cos(u / 2) + (noise == 0. ? 0. : rng.get_double(0, noise)),
+ b * sin(v) * sin(u / 2) + (noise == 0. ? 0. : rng.get_double(0, noise)));
+ points.push_back(p);
+ ++i;
+ }
+ return points;
+}
+
+
+// a = big radius, b = small radius
+
+template <typename Kernel>
+std::vector<typename Kernel::Point_d>
+generate_points_on_klein_bottle_variant_5D(
+ std::size_t num_points, double a, double b, bool uniform = false) {
+ typedef typename Kernel::Point_d Point;
+ typedef typename Kernel::FT FT;
+ Kernel k;
+ CGAL::Random rng;
+
+ // if uniform
+ std::size_t num_lines = (std::size_t)sqrt(num_points);
+
+ std::vector<Point> points;
+ points.reserve(num_points);
+ for (std::size_t i = 0; i < num_points;) {
+ FT u, v;
+ if (uniform) {
+ std::size_t k1 = i / num_lines;
+ std::size_t k2 = i % num_lines;
+ u = 6.2832 * k1 / num_lines;
+ v = 6.2832 * k2 / num_lines;
+ } else {
+ u = rng.get_double(0, 6.2832);
+ v = rng.get_double(0, 6.2832);
+ }
+ FT x1 = (a + b * cos(v)) * cos(u);
+ FT x2 = (a + b * cos(v)) * sin(u);
+ FT x3 = b * sin(v) * cos(u / 2);
+ FT x4 = b * sin(v) * sin(u / 2);
+ FT x5 = x1 + x2 + x3 + x4;
+
+ Point p = construct_point(k, x1, x2, x3, x4, x5);
+ points.push_back(p);
+ ++i;
+ }
+ return points;
+}
+
+} // namespace Gudhi
+
+#endif // RANDOM_POINT_GENERATORS_H_
diff --git a/src/common/include/gudhi/reader_utils.h b/src/common/include/gudhi/reader_utils.h
index e05714c7..899f9df6 100644
--- a/src/common/include/gudhi/reader_utils.h
+++ b/src/common/include/gudhi/reader_utils.h
@@ -58,7 +58,9 @@ inline void read_points(std::string file_name, std::vector< std::vector< double
while (iss >> x) {
point.push_back(x);
}
- points.push_back(point);
+ // Check for empty lines
+ if (!point.empty())
+ points.push_back(point);
}
in_file.close();
}
@@ -159,7 +161,7 @@ bool read_simplex(std::istream & in_, std::vector< Vertex_handle > & simplex, Fi
simplex.push_back(v);
}
in_ >> fil;
- in_.ignore((std::numeric_limits<std::streamsize>::max)(), '\n'); // ignore until the carriage return
+ in_.ignore((std::numeric_limits<std::streamsize>::max)(), '\n'); // ignore until the carriage return
return true;
}
diff --git a/src/common/include/gudhi_patches/CGAL/Convex_hull.h b/src/common/include/gudhi_patches/CGAL/Convex_hull.h
new file mode 100644
index 00000000..a8f91bf8
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/Delaunay_triangulation.h b/src/common/include/gudhi_patches/CGAL/Delaunay_triangulation.h
new file mode 100644
index 00000000..071cd184
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/Epeck_d.h b/src/common/include/gudhi_patches/CGAL/Epeck_d.h
new file mode 100644
index 00000000..52bce84c
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/Epick_d.h b/src/common/include/gudhi_patches/CGAL/Epick_d.h
new file mode 100644
index 00000000..64438539
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/IO/Triangulation_off_ostream.h b/src/common/include/gudhi_patches/CGAL/IO/Triangulation_off_ostream.h
new file mode 100644
index 00000000..701f0820
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_LA_base.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_LA_base.h
new file mode 100644
index 00000000..c13a9801
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_LA_functors.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_LA_functors.h
new file mode 100644
index 00000000..871c463a
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_base.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_base.h
new file mode 100644
index 00000000..641bf8ae
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_change_FT.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_change_FT.h
new file mode 100644
index 00000000..e09c72d0
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_complete.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_complete.h
new file mode 100644
index 00000000..ef8921db
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_filter_K.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_filter_K.h
new file mode 100644
index 00000000..179e97bf
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_filter_NT.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_filter_NT.h
new file mode 100644
index 00000000..c390a55c
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_per_dimension.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_per_dimension.h
new file mode 100644
index 00000000..179f7319
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_static_filters.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_static_filters.h
new file mode 100644
index 00000000..693e962a
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Coaffine.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Coaffine.h
new file mode 100644
index 00000000..43015d24
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Define_kernel_types.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Define_kernel_types.h
new file mode 100644
index 00000000..6a40515b
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Dimension_base.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Dimension_base.h
new file mode 100644
index 00000000..be875e63
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Filtered_predicate2.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Filtered_predicate2.h
new file mode 100644
index 00000000..1a6a67bc
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/KernelD_converter.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/KernelD_converter.h
new file mode 100644
index 00000000..a8896976
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Kernel_2_interface.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Kernel_2_interface.h
new file mode 100644
index 00000000..fa30dff0
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Kernel_3_interface.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Kernel_3_interface.h
new file mode 100644
index 00000000..96076aa8
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Kernel_d_interface.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Kernel_d_interface.h
new file mode 100644
index 00000000..dd888005
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Kernel_object_converter.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Kernel_object_converter.h
new file mode 100644
index 00000000..99918ed2
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/LA_eigen/LA.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/LA_eigen/LA.h
new file mode 100644
index 00000000..ddbdc37b
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/LA_eigen/constructors.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/LA_eigen/constructors.h
new file mode 100644
index 00000000..3636996f
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Lazy_cartesian.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Lazy_cartesian.h
new file mode 100644
index 00000000..9ecc2b63
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Aff_transformation.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Aff_transformation.h
new file mode 100644
index 00000000..6d9f070f
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Hyperplane.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Hyperplane.h
new file mode 100644
index 00000000..14e35b01
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Iso_box.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Iso_box.h
new file mode 100644
index 00000000..d053f351
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Line.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Line.h
new file mode 100644
index 00000000..6a09571c
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Ray.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Ray.h
new file mode 100644
index 00000000..be845e76
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Segment.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Segment.h
new file mode 100644
index 00000000..38361c2b
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Sphere.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Sphere.h
new file mode 100644
index 00000000..114410b4
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Weighted_point.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Weighted_point.h
new file mode 100644
index 00000000..1caf8701
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/array.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/array.h
new file mode 100644
index 00000000..0ad9bb36
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/avx4.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/avx4.h
new file mode 100644
index 00000000..954a3c1b
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_iterator_to_points_from_iterator_to_vectors.h b/src/common/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/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_iterator_to_points_from_points.h b/src/common/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/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_iterator_to_vectors_from_vectors.h b/src/common/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/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_points_from_vectors.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_points_from_vectors.h
new file mode 100644
index 00000000..7ddb73c3
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_vectors_small_dim.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_vectors_small_dim.h
new file mode 100644
index 00000000..64eafe69
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_vectors_small_dim_internal.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_vectors_small_dim_internal.h
new file mode 100644
index 00000000..b4856742
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/mix.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/mix.h
new file mode 100644
index 00000000..d4cfeeb1
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/sse2.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/sse2.h
new file mode 100644
index 00000000..2a75385c
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/v2int.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/v2int.h
new file mode 100644
index 00000000..b85a3734
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/vector.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/vector.h
new file mode 100644
index 00000000..f9cc4e3c
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h
new file mode 100644
index 00000000..44e9aa96
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Hyperplane_d.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Hyperplane_d.h
new file mode 100644
index 00000000..54fd50bd
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Point_d.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Point_d.h
new file mode 100644
index 00000000..0718c947
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Ref_count_obj.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Ref_count_obj.h
new file mode 100644
index 00000000..f33e14c0
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Segment_d.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Segment_d.h
new file mode 100644
index 00000000..bfb20a77
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Sphere_d.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Sphere_d.h
new file mode 100644
index 00000000..87f0c66e
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Vector_d.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Vector_d.h
new file mode 100644
index 00000000..b7d1f0d0
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Weighted_point_d.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Weighted_point_d.h
new file mode 100644
index 00000000..877eea21
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/function_objects_cartesian.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/function_objects_cartesian.h
new file mode 100644
index 00000000..5a132ad2
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/functor_properties.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/functor_properties.h
new file mode 100644
index 00000000..c25c4e2b
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/functor_tags.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/functor_tags.h
new file mode 100644
index 00000000..b8e17886
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/static_int.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/static_int.h
new file mode 100644
index 00000000..21858804
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/store_kernel.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/store_kernel.h
new file mode 100644
index 00000000..253e1282
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/NewKernel_d/utils.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/utils.h
new file mode 100644
index 00000000..238a2230
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/Regular_triangulation.h b/src/common/include/gudhi_patches/CGAL/Regular_triangulation.h
new file mode 100644
index 00000000..111c6ac9
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/Regular_triangulation_traits_adapter.h b/src/common/include/gudhi_patches/CGAL/Regular_triangulation_traits_adapter.h
new file mode 100644
index 00000000..78bb95a6
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/TDS_full_cell_default_storage_policy.h b/src/common/include/gudhi_patches/CGAL/TDS_full_cell_default_storage_policy.h
new file mode 100644
index 00000000..9a6030e5
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/TDS_full_cell_mirror_storage_policy.h b/src/common/include/gudhi_patches/CGAL/TDS_full_cell_mirror_storage_policy.h
new file mode 100644
index 00000000..095dfe68
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/Triangulation.h b/src/common/include/gudhi_patches/CGAL/Triangulation.h
new file mode 100644
index 00000000..906df92e
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/Triangulation_data_structure.h b/src/common/include/gudhi_patches/CGAL/Triangulation_data_structure.h
new file mode 100644
index 00000000..2493c712
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/Triangulation_ds_full_cell.h b/src/common/include/gudhi_patches/CGAL/Triangulation_ds_full_cell.h
new file mode 100644
index 00000000..541a6a85
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/Triangulation_ds_vertex.h b/src/common/include/gudhi_patches/CGAL/Triangulation_ds_vertex.h
new file mode 100644
index 00000000..381b97e1
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/Triangulation_face.h b/src/common/include/gudhi_patches/CGAL/Triangulation_face.h
new file mode 100644
index 00000000..bc9c1781
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/Triangulation_full_cell.h b/src/common/include/gudhi_patches/CGAL/Triangulation_full_cell.h
new file mode 100644
index 00000000..a0c5246f
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/Triangulation_vertex.h b/src/common/include/gudhi_patches/CGAL/Triangulation_vertex.h
new file mode 100644
index 00000000..f364717f
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/argument_swaps.h b/src/common/include/gudhi_patches/CGAL/argument_swaps.h
new file mode 100644
index 00000000..aa16f29b
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/determinant_of_vectors.h b/src/common/include/gudhi_patches/CGAL/determinant_of_vectors.h
new file mode 100644
index 00000000..e1bad64e
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/internal/Combination_enumerator.h b/src/common/include/gudhi_patches/CGAL/internal/Combination_enumerator.h
new file mode 100644
index 00000000..f411e827
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/internal/Static_or_dynamic_array.h b/src/common/include/gudhi_patches/CGAL/internal/Static_or_dynamic_array.h
new file mode 100644
index 00000000..ee6195d9
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/internal/Triangulation/Dummy_TDS.h b/src/common/include/gudhi_patches/CGAL/internal/Triangulation/Dummy_TDS.h
new file mode 100644
index 00000000..b3a0ec98
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/internal/Triangulation/Triangulation_ds_iterators.h b/src/common/include/gudhi_patches/CGAL/internal/Triangulation/Triangulation_ds_iterators.h
new file mode 100644
index 00000000..7e360026
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/internal/Triangulation/utilities.h b/src/common/include/gudhi_patches/CGAL/internal/Triangulation/utilities.h
new file mode 100644
index 00000000..a1ffc775
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/iterator_from_indices.h b/src/common/include/gudhi_patches/CGAL/iterator_from_indices.h
new file mode 100644
index 00000000..110bb4be
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/transforming_iterator.h b/src/common/include/gudhi_patches/CGAL/transforming_iterator.h
new file mode 100644
index 00000000..15ea19a5
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/transforming_pair_iterator.h b/src/common/include/gudhi_patches/CGAL/transforming_pair_iterator.h
new file mode 100644
index 00000000..48dac132
--- /dev/null
+++ b/src/common/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/src/common/include/gudhi_patches/CGAL/typeset.h b/src/common/include/gudhi_patches/CGAL/typeset.h
new file mode 100644
index 00000000..d4e24281
--- /dev/null
+++ b/src/common/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/src/common/test/CMakeLists.txt b/src/common/test/CMakeLists.txt
new file mode 100644
index 00000000..7ccdb752
--- /dev/null
+++ b/src/common/test/CMakeLists.txt
@@ -0,0 +1,24 @@
+cmake_minimum_required(VERSION 2.6)
+project(Common_tests)
+
+if (GCOVR_PATH)
+ # for gcovr to make coverage reports - Corbera Jenkins plugin
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
+endif()
+if (GPROF_PATH)
+ # for gprof to make coverage reports - Jenkins
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg")
+endif()
+
+add_executable ( poffreader_UT test_points_off_reader.cpp )
+target_link_libraries(poffreader_UT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+
+# Do not forget to copy test files in current binary dir
+file(COPY "${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
+
+# Unitary tests
+add_test(poffreader_UT ${CMAKE_CURRENT_BINARY_DIR}/poffreader_UT
+ # XML format for Jenkins xUnit plugin
+ --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/poffreader_UT.xml --log_level=test_suite --report_level=no)
+
+
diff --git a/src/common/test/README b/src/common/test/README
new file mode 100644
index 00000000..f2a7eb5a
--- /dev/null
+++ b/src/common/test/README
@@ -0,0 +1,14 @@
+To compile:
+***********
+
+cmake .
+make
+
+To launch with details:
+***********************
+
+./dtoffrw_UT --report_level=detailed --log_level=all
+
+ ==> echo $? returns 0 in case of success (non-zero otherwise)
+
+
diff --git a/src/common/test/dtoffrw_alphashapedoc_result.off b/src/common/test/dtoffrw_alphashapedoc_result.off
new file mode 100644
index 00000000..1deb8dbd
--- /dev/null
+++ b/src/common/test/dtoffrw_alphashapedoc_result.off
@@ -0,0 +1,7 @@
+Point[0] = 1 1
+Point[1] = 7 0
+Point[2] = 4 6
+Point[3] = 9 6
+Point[4] = 0 14
+Point[5] = 2 19
+Point[6] = 9 17
diff --git a/src/common/test/test_points_off_reader.cpp b/src/common/test/test_points_off_reader.cpp
new file mode 100644
index 00000000..b4f71182
--- /dev/null
+++ b/src/common/test/test_points_off_reader.cpp
@@ -0,0 +1,73 @@
+/* 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/>.
+ */
+
+#include <gudhi/Points_off_io.h>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE "points_off_read_write"
+#include <boost/test/unit_test.hpp>
+
+using Point_d = std::vector<double>;
+
+BOOST_AUTO_TEST_CASE( points_doc_test )
+{
+ // Read the OFF file (input file name given as parameter) and triangulates points
+ Gudhi::Points_off_reader<Point_d> off_reader("alphacomplexdoc.off");
+ // Check the read operation was correct
+ BOOST_CHECK(off_reader.is_valid());
+
+ // Retrieve the triangulation
+ std::vector<Point_d> point_cloud = off_reader.get_point_cloud();
+ BOOST_CHECK(point_cloud.size() == 7);
+
+ std::vector<Point_d> expected_points;
+ std::vector<double> point = {1.0, 1.0};
+ expected_points.push_back(Point_d(point.begin(), point.end()));
+ point = {7.0, 0.0};
+ expected_points.push_back(Point_d(point.begin(), point.end()));
+ point = {4.0, 6.0};
+ expected_points.push_back(Point_d(point.begin(), point.end()));
+ point = {9.0, 6.0};
+ expected_points.push_back(Point_d(point.begin(), point.end()));
+ point = {0.0, 14.0};
+ expected_points.push_back(Point_d(point.begin(), point.end()));
+ point = {2.0, 19.0};
+ expected_points.push_back(Point_d(point.begin(), point.end()));
+ point = {9.0, 17.0};
+ expected_points.push_back(Point_d(point.begin(), point.end()));
+
+ BOOST_CHECK(point_cloud == expected_points);
+}
+
+BOOST_AUTO_TEST_CASE( Delaunay_triangulation_unexisting_file_read_test )
+{
+ Gudhi::Points_off_reader<Point_d> off_reader("some_impossible_weird_file_name.off");
+ // Check the read operation was correct
+ BOOST_CHECK(!off_reader.is_valid());
+
+ std::vector<Point_d> point_cloud = off_reader.get_point_cloud();
+ BOOST_CHECK(point_cloud.size() == 0);
+}
diff --git a/src/debian/changelog b/src/debian/changelog
new file mode 100644
index 00000000..32b3f6f9
--- /dev/null
+++ b/src/debian/changelog
@@ -0,0 +1,5 @@
+gudhi (1.3.0-1) unstable; urgency=low
+
+ * Initial release.
+
+ -- Marc Glisse <marc.glisse@inria.fr> Sat, 26 Mar 2016 10:51:01 +0100
diff --git a/src/debian/compat b/src/debian/compat
new file mode 100644
index 00000000..ec635144
--- /dev/null
+++ b/src/debian/compat
@@ -0,0 +1 @@
+9
diff --git a/src/debian/control b/src/debian/control
new file mode 100644
index 00000000..838234a9
--- /dev/null
+++ b/src/debian/control
@@ -0,0 +1,26 @@
+Source: gudhi
+Priority: optional
+Maintainer: Marc Glisse <marc.glisse@normalesup.org>
+Build-Depends: debhelper (>= 9), cmake, libboost-dev
+Standards-Version: 3.9.6
+Section: libs
+Homepage: http://gudhi.gforge.inria.fr/
+#Vcs-Git: git://anonscm.debian.org/collab-maint/gudhi.git
+#Vcs-Browser: https://anonscm.debian.org/gitweb/?p=collab-maint/gudhi.git;a=summary
+
+Package: libgudhi-dev
+Section: libdevel
+Architecture: all
+Depends: libboost-dev, ${misc:Depends}
+Recommends: libcgal-dev
+Description: Gudhi library for topological data analysis
+ The Gudhi library (Geometric Understanding in Higher Dimensions) is a generic
+ open source C++ library for Computational Topology and Topological Data
+ Analysis (TDA).
+ .
+ The current release of the GUDHI library includes:
+ * Data structures to represent, construct and manipulate simplicial and
+ cubical complexes, including alpha-complex, witness complex, Rips complex.
+ * Algorithms to compute persistent homology and multi-field persistent
+ homology.
+ * Simplication of simplicial complexes by edge contraction.
diff --git a/src/debian/copyright b/src/debian/copyright
new file mode 100644
index 00000000..2e1f88cd
--- /dev/null
+++ b/src/debian/copyright
@@ -0,0 +1,28 @@
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: gudhi
+Upstream-Contact: gudhi-users@lists.gforge.inria.fr
+Source: <url://http://gudhi.gforge.inria.fr/>
+
+Files: *
+Copyright: 2014-2016 Inria Sophia Antipolis-Méditerranée
+ 2014-2016 Inria Saclay - Ile de France
+ 2014-2016 Université Nice Sophia Antipolis
+License: GPL-3.0+
+
+License: GPL-3.0+
+ 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 package 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 <https://www.gnu.org/licenses/>.
+ .
+ On Debian systems, the complete text of the GNU General
+ Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
+
diff --git a/src/debian/docs b/src/debian/docs
new file mode 100644
index 00000000..878a2ba1
--- /dev/null
+++ b/src/debian/docs
@@ -0,0 +1,2 @@
+Conventions.txt
+README
diff --git a/src/debian/rules b/src/debian/rules
new file mode 100755
index 00000000..c9b049af
--- /dev/null
+++ b/src/debian/rules
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+# See debhelper(7) (uncomment to enable)
+# output every command that modifies files on the build system.
+#export DH_VERBOSE = 1
+
+# see EXAMPLES in dpkg-buildflags(1) and read /usr/share/dpkg/*
+DPKG_EXPORT_BUILDFLAGS = 1
+include /usr/share/dpkg/default.mk
+
+# see FEATURE AREAS in dpkg-buildflags(1)
+#export DEB_BUILD_MAINT_OPTIONS = hardening=+all
+
+# see ENVIRONMENT in dpkg-buildflags(1)
+# package maintainers to append CFLAGS
+#export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic
+# package maintainers to append LDFLAGS
+#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed
+
+
+# main packaging script based on dh7 syntax
+%:
+ dh $@
+
+# dh_make generated override targets
+# This is example for Cmake (See https://bugs.debian.org/641051 )
+#override_dh_auto_configure:
+# dh_auto_configure -- \
+# -DCMAKE_LIBRARY_PATH=$(DEB_HOST_MULTIARCH)
diff --git a/src/debian/source/format b/src/debian/source/format
new file mode 100644
index 00000000..163aaf8d
--- /dev/null
+++ b/src/debian/source/format
@@ -0,0 +1 @@
+3.0 (quilt)