From 7f5fb3d262694bd8c3a61fbee38ee28c2bcc9758 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 20 May 2019 14:12:23 +0200 Subject: [PATCH 001/185] remove call to boost function (remove the need of default constructible fid map) --- .../connected_components.h | 48 +++++++++++++------ 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/connected_components.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/connected_components.h index 855b2604f1e..850c855a8e0 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/connected_components.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/connected_components.h @@ -32,8 +32,6 @@ #include #include #include -#include -#include #include #include @@ -215,6 +213,10 @@ connected_components(const PolygonMesh& pmesh, using boost::choose_param; using boost::get_param; + typedef boost::graph_traits GT; + typedef typename GT::halfedge_descriptor halfedge_descriptor; + typedef typename GT::face_descriptor face_descriptor; + typedef typename boost::lookup_named_param_def < internal_np::edge_is_constrained_t, NamedParameters, @@ -224,22 +226,40 @@ connected_components(const PolygonMesh& pmesh, = choose_param(get_param(np, internal_np::edge_is_constrained), internal::No_constraint()); - typedef Dual Dual; - typedef boost::filtered_graph > FiniteDual; - Dual dual(pmesh); - - FiniteDual finite_dual(dual, - internal::No_border(pmesh, ecmap)); - typename GetFaceIndexMap::const_type fimap = choose_param(get_param(np, internal_np::face_index), get_const_property_map(boost::face_index, pmesh)); - return boost::connected_components(finite_dual, - fcm, - boost::vertex_index_map(fimap) - ); + typename boost::property_traits::value_type i=0; + std::vector handled(num_faces(pmesh), false); + for (face_descriptor f : faces(pmesh)) + { + if (handled[get(fimap,f)]) continue; + std::vector queue; + queue.push_back(f); + while(!queue.empty()) + { + face_descriptor fq = queue.back(); + queue.pop_back(); + typename boost::property_traits::value_type fq_id = get(fimap,fq); + if ( handled[fq_id]) continue; + handled[fq_id]=true; + put(fcm, fq, i); + for (typename PolygonMesh::Halfedge_index h : halfedges_around_face(halfedge(fq, pmesh), pmesh)) + { + if ( get(ecmap, edge(h, pmesh)) ) continue; + halfedge_descriptor opp = opposite(h, pmesh); + face_descriptor fqo = face(opp, pmesh); + if ( fqo != GT::null_face() ) + { + if ( !handled[get(fimap,fqo)] ) + queue.push_back(fqo); + } + } + } + ++i; + } + return i; } template From 60d3851a201afbcab6cf2d98ca89fe2a605ab9d4 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 3 Oct 2019 13:28:10 +0200 Subject: [PATCH 002/185] Set WITH_GMPXX ON if GMPXX is found in the cmake options of cgal --- Installation/CMakeLists.txt | 7 +++++-- Installation/cmake/modules/CGAL_SetupGMP.cmake | 10 ++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Installation/CMakeLists.txt b/Installation/CMakeLists.txt index f16e99d4a1a..cfaff45d430 100644 --- a/Installation/CMakeLists.txt +++ b/Installation/CMakeLists.txt @@ -644,8 +644,11 @@ foreach (lib ${CGAL_SUPPORTING_3RD_PARTY_LIBRARIES}) list( FIND CGAL_ESSENTIAL_3RD_PARTY_LIBRARIES "${lib}" POSITION ) if ( "${POSITION}" STRGREATER "-1" ) # if lib is essential option(WITH_${lib} "Select external library ${lib}" ON) - else() - option(WITH_${lib} "Select external library ${lib}" OFF) + else() #GMPXX set in CGAL_SetupGMP.cmake + string(COMPARE EQUAL "${lib}" "GMPXX" IS_LIB_GMPXX) + if(NOT ${IS_LIB_GMPXX}) + option(WITH_${lib} "Select external library ${lib}" OFF) + endif() endif() endforeach() diff --git a/Installation/cmake/modules/CGAL_SetupGMP.cmake b/Installation/cmake/modules/CGAL_SetupGMP.cmake index 1a8c28a3c13..26fc412e135 100644 --- a/Installation/cmake/modules/CGAL_SetupGMP.cmake +++ b/Installation/cmake/modules/CGAL_SetupGMP.cmake @@ -23,12 +23,14 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CGAL_MODULES_DIR}) find_package(GMP REQUIRED) find_package(MPFR REQUIRED) +find_package(GMPXX QUIET) -if(NOT DEFINED WITH_GMPXX) +if(NOT GMPXX_FOUND) option(CGAL_WITH_GMPXX "Use CGAL with GMPXX: use C++ classes of GNU MP instead of CGAL wrappers" OFF) -endif() -if(WITH_GMPXX OR CGAL_WITH_GMPXX) - find_package(GMPXX REQUIRED) + option(WITH_GMPXX "Select external library GMPXX" OFF) +else() + option(CGAL_WITH_GMPXX "Use CGAL with GMPXX: use C++ classes of GNU MP instead of CGAL wrappers" ON) + option(WITH_GMPXX "Select external library GMPXX" ON) endif() #.rst: From 5dd3c7ee8343a8bbe25b6c62546376a222bc2c6a Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 3 Oct 2019 14:17:39 +0200 Subject: [PATCH 003/185] Better test --- Installation/CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Installation/CMakeLists.txt b/Installation/CMakeLists.txt index cfaff45d430..8fee098dc9a 100644 --- a/Installation/CMakeLists.txt +++ b/Installation/CMakeLists.txt @@ -645,8 +645,7 @@ foreach (lib ${CGAL_SUPPORTING_3RD_PARTY_LIBRARIES}) if ( "${POSITION}" STRGREATER "-1" ) # if lib is essential option(WITH_${lib} "Select external library ${lib}" ON) else() #GMPXX set in CGAL_SetupGMP.cmake - string(COMPARE EQUAL "${lib}" "GMPXX" IS_LIB_GMPXX) - if(NOT ${IS_LIB_GMPXX}) + if(NOT "${lib}" STREQUAL "GMPXX") option(WITH_${lib} "Select external library ${lib}" OFF) endif() endif() From 82009f60fd6e03f44dd5045f60a7d6bff90ff0ca Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Wed, 30 Oct 2019 15:40:27 +0100 Subject: [PATCH 004/185] Spatial_sorting: Parallelize 3D case --- .../include/CGAL/Hilbert_sort_median_3.h | 105 ++++++++++++++++-- 1 file changed, 96 insertions(+), 9 deletions(-) diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h b/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h index 1ccdea9adf6..761a7cd1929 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h @@ -17,6 +17,10 @@ #include #include +#ifdef CGAL_LINKED_WITH_TBB +#include +#endif + namespace CGAL { namespace internal { @@ -83,6 +87,8 @@ template class Hilbert_sort_median_3 { public: + + typedef Hilbert_sort_median_3 Self; typedef K Kernel; typedef typename Kernel::Point_3 Point; @@ -98,8 +104,9 @@ public: : _k(k), _limit (limit) {} + template - void sort (RandomAccessIterator begin, RandomAccessIterator end) const + void recursive_sort (RandomAccessIterator begin, RandomAccessIterator end) const { const int y = (x + 1) % 3, z = (x + 2) % 3; if (end - begin <= _limit) return; @@ -114,16 +121,96 @@ public: RandomAccessIterator m5 = internal::hilbert_split (m4, m6, Cmp< z, upz> (_k)); RandomAccessIterator m7 = internal::hilbert_split (m6, m8, Cmp< z, !upz> (_k)); - sort (m0, m1); - sort (m1, m2); - sort (m2, m3); - sort (m3, m4); - sort (m4, m5); - sort (m5, m6); - sort (m6, m7); - sort (m7, m8); + recursive_sort (m0, m1); + recursive_sort (m1, m2); + recursive_sort (m2, m3); + recursive_sort (m3, m4); + recursive_sort (m4, m5); + recursive_sort (m5, m6); + recursive_sort (m6, m7); + recursive_sort (m7, m8); } + template + struct Recursive_sort { + const Self& hs; + RandomAccessIterator begin,end; + + Recursive_sort(const Self& hs, RandomAccessIterator begin, RandomAccessIterator end) + : hs(hs), begin(begin), end(end) + {} + + void operator()() const + { + hs.recursive_sort(begin,end); + } + }; + + template + struct Hilbert_split + { + RandomAccessIterator& res; + RandomAccessIterator begin, end; + const Comp& comp; + + Hilbert_split(RandomAccessIterator& res, RandomAccessIterator begin, RandomAccessIterator end, const Comp comp) + : res(res), begin(begin), end(end), comp(comp) + {} + + void operator()() const + { + res = internal::hilbert_split(begin, end, comp); + } + }; + + + template + void sort (RandomAccessIterator begin, RandomAccessIterator end) const + { + const int y = (x + 1) % 3, z = (x + 2) % 3; + if ((end - begin) <= _limit) return; + + RandomAccessIterator m0 = begin, m8 = end; +#if defined( CGAL_LINKED_WITH_TBB) && ( ! defined (CGAL_NO_PARALLEL_SPATIAL_SORT) ) + if((end - begin) > 1024){ + RandomAccessIterator m1, m2, m3, m4, m5, m6, m7; + m4 = internal::hilbert_split(m0, m8, Cmp(_k)); + { + tbb::task_group g; + g.run(Hilbert_split >(m2,m0,m4,Cmp(_k))); + g.run(Hilbert_split >(m6,m4,m8,Cmp(_k))); + g.wait(); + } + + { + tbb::task_group g; + g.run(Hilbert_split >(m1,m0,m2,Cmp(_k))); + g.run(Hilbert_split >(m3,m2,m4,Cmp(_k))); + g.run(Hilbert_split >(m5,m4,m6,Cmp(_k))); + g.run(Hilbert_split >(m7,m6,m8,Cmp(_k))); + g.wait(); + } + + { + tbb::task_group g; + g.run(Recursive_sort(*this, m0, m1)); + g.run(Recursive_sort(*this, m1, m2)); + g.run(Recursive_sort(*this, m2, m3)); + g.run(Recursive_sort(*this, m3, m4)); + g.run(Recursive_sort(*this, m4, m5)); + g.run(Recursive_sort(*this, m5, m6)); + g.run(Recursive_sort(*this, m6, m7)); + g.run(Recursive_sort(*this, m7, m8)); + g.wait(); + } + } else { + recursive_sort<0, false, false, false>(begin, end); + } +#else + recursive_sort<0, false, false, false>(begin, end); +#endif + } + template void operator() (RandomAccessIterator begin, RandomAccessIterator end) const { From 4d55c22dfe06496ae7bee109dbe2c24812d0d2d0 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 4 Nov 2019 09:09:15 +0100 Subject: [PATCH 005/185] Use tbb::parallel_invoke() --- .../include/CGAL/Hilbert_sort_median_3.h | 45 ++++++++----------- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h b/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h index 761a7cd1929..732139e6ec1 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h @@ -18,7 +18,7 @@ #include #ifdef CGAL_LINKED_WITH_TBB -#include +#include #endif namespace CGAL { @@ -175,34 +175,25 @@ public: if((end - begin) > 1024){ RandomAccessIterator m1, m2, m3, m4, m5, m6, m7; m4 = internal::hilbert_split(m0, m8, Cmp(_k)); - { - tbb::task_group g; - g.run(Hilbert_split >(m2,m0,m4,Cmp(_k))); - g.run(Hilbert_split >(m6,m4,m8,Cmp(_k))); - g.wait(); - } - { - tbb::task_group g; - g.run(Hilbert_split >(m1,m0,m2,Cmp(_k))); - g.run(Hilbert_split >(m3,m2,m4,Cmp(_k))); - g.run(Hilbert_split >(m5,m4,m6,Cmp(_k))); - g.run(Hilbert_split >(m7,m6,m8,Cmp(_k))); - g.wait(); - } + tbb::parallel_invoke(Hilbert_split >(m2,m0,m4,Cmp(_k)), + Hilbert_split >(m6,m4,m8,Cmp(_k))); - { - tbb::task_group g; - g.run(Recursive_sort(*this, m0, m1)); - g.run(Recursive_sort(*this, m1, m2)); - g.run(Recursive_sort(*this, m2, m3)); - g.run(Recursive_sort(*this, m3, m4)); - g.run(Recursive_sort(*this, m4, m5)); - g.run(Recursive_sort(*this, m5, m6)); - g.run(Recursive_sort(*this, m6, m7)); - g.run(Recursive_sort(*this, m7, m8)); - g.wait(); - } + + tbb::parallel_invoke(Hilbert_split >(m1,m0,m2,Cmp(_k)), + Hilbert_split >(m3,m2,m4,Cmp(_k)), + Hilbert_split >(m5,m4,m6,Cmp(_k)), + Hilbert_split >(m7,m6,m8,Cmp(_k))); + + tbb::parallel_invoke(Recursive_sort(*this, m0, m1), + Recursive_sort(*this, m1, m2), + Recursive_sort(*this, m2, m3), + Recursive_sort(*this, m3, m4), + Recursive_sort(*this, m4, m5), + Recursive_sort(*this, m5, m6), + Recursive_sort(*this, m6, m7), + Recursive_sort(*this, m7, m8)); + } else { recursive_sort<0, false, false, false>(begin, end); } From d7b97756fff5286419dab8db9456cf6bc9cb56c4 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 4 Nov 2019 12:44:13 +0100 Subject: [PATCH 006/185] Add 2D version --- .../include/CGAL/Hilbert_sort_median_2.h | 75 +++++++++++++++++-- 1 file changed, 70 insertions(+), 5 deletions(-) diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h b/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h index 6d89cfc8eec..77db8f90895 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h @@ -17,6 +17,10 @@ #include #include +#ifdef CGAL_LINKED_WITH_TBB +#include +#endif + namespace CGAL { namespace internal { @@ -69,6 +73,7 @@ template class Hilbert_sort_median_2 { public: + typedef Hilbert_sort_median_2 Self; typedef K Kernel; typedef typename Kernel::Point_2 Point; @@ -85,7 +90,7 @@ public: {} template - void sort (RandomAccessIterator begin, RandomAccessIterator end) const + void recursive_sort (RandomAccessIterator begin, RandomAccessIterator end) const { const int y = (x + 1) % 2; if (end - begin <= _limit) return; @@ -96,10 +101,70 @@ public: RandomAccessIterator m1 = internal::hilbert_split (m0, m2, Cmp< y, upy> (_k)); RandomAccessIterator m3 = internal::hilbert_split (m2, m4, Cmp< y, !upy> (_k)); - sort (m0, m1); - sort (m1, m2); - sort (m2, m3); - sort (m3, m4); + recursive_sort (m0, m1); + recursive_sort (m1, m2); + recursive_sort (m2, m3); + recursive_sort (m3, m4); + } + + template + struct Recursive_sort { + const Self& hs; + RandomAccessIterator begin,end; + + Recursive_sort(const Self& hs, RandomAccessIterator begin, RandomAccessIterator end) + : hs(hs), begin(begin), end(end) + {} + + void operator()() const + { + hs.recursive_sort(begin,end); + } + }; + + template + struct Hilbert_split + { + RandomAccessIterator& res; + RandomAccessIterator begin, end; + const Comp& comp; + + Hilbert_split(RandomAccessIterator& res, RandomAccessIterator begin, RandomAccessIterator end, const Comp comp) + : res(res), begin(begin), end(end), comp(comp) + {} + + void operator()() const + { + res = internal::hilbert_split(begin, end, comp); + } + }; + + template + void sort (RandomAccessIterator begin, RandomAccessIterator end) const + { + const int y = (x + 1) % 2; + if (end - begin <= _limit) return; + + RandomAccessIterator m0 = begin, m4 = end; + +#if defined( CGAL_LINKED_WITH_TBB) && ( ! defined (CGAL_NO_PARALLEL_SPATIAL_SORT) ) + if((end - begin) > 1024){ + RandomAccessIterator m1, m2, m3; + m2 = internal::hilbert_split (m0, m4, Cmp< x, upx> (_k)); + + tbb::parallel_invoke(Hilbert_split > (m1, m0, m2, Cmp< y, upy> (_k)), + Hilbert_split > (m3, m2, m4, Cmp< y, !upy> (_k))); + + tbb::parallel_invoke(Recursive_sort (*this, m0, m1), + Recursive_sort (*this, m1, m2), + Recursive_sort (*this, m2, m3), + Recursive_sort (*this, m3, m4)); + } else { + recursive_sort<0, false, false>(begin, end); + } +#else + recursive_sort<0, false, false>(begin, end); +#endif } template From cffd1fe3a07939f5fdd0df647a8471aef762e7c3 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 4 Nov 2019 15:54:47 +0100 Subject: [PATCH 007/185] Add ConcurrencyTag --- .../examples/Spatial_sorting/CMakeLists.txt | 5 ++ .../examples/Spatial_sorting/parallel.cpp | 34 ++++++++++ Spatial_sorting/include/CGAL/Hilbert_sort_2.h | 14 ++-- Spatial_sorting/include/CGAL/Hilbert_sort_3.h | 14 ++-- .../include/CGAL/Hilbert_sort_median_2.h | 65 +++++++++++-------- .../include/CGAL/Hilbert_sort_median_3.h | 29 ++++++--- Spatial_sorting/include/CGAL/spatial_sort.h | 33 +++++----- 7 files changed, 126 insertions(+), 68 deletions(-) create mode 100644 Spatial_sorting/examples/Spatial_sorting/parallel.cpp diff --git a/Spatial_sorting/examples/Spatial_sorting/CMakeLists.txt b/Spatial_sorting/examples/Spatial_sorting/CMakeLists.txt index df5f623e1ba..35887344bff 100644 --- a/Spatial_sorting/examples/Spatial_sorting/CMakeLists.txt +++ b/Spatial_sorting/examples/Spatial_sorting/CMakeLists.txt @@ -16,6 +16,11 @@ if ( CGAL_FOUND ) create_single_source_cgal_program( "${cppfile}" ) endforeach() + find_package( TBB QUIET ) + if( TBB_FOUND ) + include( CGAL_target_use_TBB ) + CGAL_target_use_TBB( parallel ) + endif() else() message(STATUS "This program requires the CGAL library, and will not be compiled.") diff --git a/Spatial_sorting/examples/Spatial_sorting/parallel.cpp b/Spatial_sorting/examples/Spatial_sorting/parallel.cpp new file mode 100644 index 00000000000..dd00d063b4b --- /dev/null +++ b/Spatial_sorting/examples/Spatial_sorting/parallel.cpp @@ -0,0 +1,34 @@ + +#include +#include + +#include +#include + +#include +#include + + + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef K::Point_3 Point_3; +typedef CGAL::Creator_uniform_3 Creator_3; + +int main(int argc, char* argv[]) +{ + std::vector points; + v.reserve (2000); + + CGAL::Random_points_in_cube_3 gen (1.0); + + for (int i = 0; i < 2000; ++i){ + v.push_back (*gen++); + } +#ifdef CGAL_LINKED_WITH_TBB + CGAL::spatial_sort(points.begin(),points.end()); +#else + CGAL::spatial_sort(points.begin(),points.end()); +#endif + + return 0; +} diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_2.h b/Spatial_sorting/include/CGAL/Hilbert_sort_2.h index f75631089eb..b4e4fa308d1 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_2.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_2.h @@ -18,21 +18,21 @@ namespace CGAL { -template +template class Hilbert_sort_2; -template - class Hilbert_sort_2 - : public Hilbert_sort_median_2 +template + class Hilbert_sort_2 + : public Hilbert_sort_median_2 { public: Hilbert_sort_2 (const K &k=K() , std::ptrdiff_t limit=1 ) - : Hilbert_sort_median_2 (k,limit) + : Hilbert_sort_median_2 (k,limit) {} }; -template - class Hilbert_sort_2 +template + class Hilbert_sort_2 : public Hilbert_sort_middle_2 { public: diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_3.h b/Spatial_sorting/include/CGAL/Hilbert_sort_3.h index cd48af285cb..158937f49e5 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_3.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_3.h @@ -18,21 +18,21 @@ namespace CGAL { -template + template class Hilbert_sort_3; -template - class Hilbert_sort_3 - : public Hilbert_sort_median_3 + template +class Hilbert_sort_3 + : public Hilbert_sort_median_3 { public: Hilbert_sort_3 (const K &k=K() , std::ptrdiff_t limit=1 ) - : Hilbert_sort_median_3 (k,limit) + : Hilbert_sort_median_3 (k,limit) {} }; -template - class Hilbert_sort_3 + template + class Hilbert_sort_3 : public Hilbert_sort_middle_3 { public: diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h b/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h index 77db8f90895..68511bfee5c 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h @@ -17,6 +17,8 @@ #include #include +#include + #ifdef CGAL_LINKED_WITH_TBB #include #endif @@ -69,11 +71,11 @@ namespace internal { }; } -template +template class Hilbert_sort_median_2 { public: - typedef Hilbert_sort_median_2 Self; + typedef Hilbert_sort_median_2 Self; typedef K Kernel; typedef typename Kernel::Point_2 Point; @@ -139,39 +141,46 @@ public: } }; - template - void sort (RandomAccessIterator begin, RandomAccessIterator end) const - { - const int y = (x + 1) % 2; - if (end - begin <= _limit) return; - - RandomAccessIterator m0 = begin, m4 = end; - -#if defined( CGAL_LINKED_WITH_TBB) && ( ! defined (CGAL_NO_PARALLEL_SPATIAL_SORT) ) + template + void sort (RandomAccessIterator begin, RandomAccessIterator end, Parallel_tag) const + { +#ifndef CGAL_LINKED_WITH_TBB + CGAL_static_assertion_msg (!(boost::is_convertible::value), + "Parallel_tag is enabled but TBB is unavailable."); +#else + const int y = (x + 1) % 2; + if (end - begin <= _limit) return; + + RandomAccessIterator m0 = begin, m4 = end; + if((end - begin) > 1024){ RandomAccessIterator m1, m2, m3; - m2 = internal::hilbert_split (m0, m4, Cmp< x, upx> (_k)); - - tbb::parallel_invoke(Hilbert_split > (m1, m0, m2, Cmp< y, upy> (_k)), - Hilbert_split > (m3, m2, m4, Cmp< y, !upy> (_k))); - - tbb::parallel_invoke(Recursive_sort (*this, m0, m1), - Recursive_sort (*this, m1, m2), - Recursive_sort (*this, m2, m3), - Recursive_sort (*this, m3, m4)); + m2 = internal::hilbert_split (m0, m4, Cmp< x, upx> (_k)); + + tbb::parallel_invoke(Hilbert_split > (m1, m0, m2, Cmp< y, upy> (_k)), + Hilbert_split > (m3, m2, m4, Cmp< y, !upy> (_k))); + + tbb::parallel_invoke(Recursive_sort (*this, m0, m1), + Recursive_sort (*this, m1, m2), + Recursive_sort (*this, m2, m3), + Recursive_sort (*this, m3, m4)); } else { recursive_sort<0, false, false>(begin, end); } -#else - recursive_sort<0, false, false>(begin, end); #endif - } + } - template - void operator() (RandomAccessIterator begin, RandomAccessIterator end) const - { - sort <0, false, false> (begin, end); - } + template + void sort (RandomAccessIterator begin, RandomAccessIterator end, Sequential_tag) const + { + recursive_sort<0, false, false>(begin, end); + } + + template + void operator() (RandomAccessIterator begin, RandomAccessIterator end) const + { + sort <0, false, false> (begin, end, ConcurrencyTag()); + } }; } // namespace CGAL diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h b/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h index 732139e6ec1..86a1d3343a1 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h @@ -17,6 +17,8 @@ #include #include +#include + #ifdef CGAL_LINKED_WITH_TBB #include #endif @@ -83,12 +85,12 @@ namespace internal { }; } -template +template class Hilbert_sort_median_3 { public: - typedef Hilbert_sort_median_3 Self; + typedef Hilbert_sort_median_3 Self; typedef K Kernel; typedef typename Kernel::Point_3 Point; @@ -163,15 +165,18 @@ public: } }; - + template - void sort (RandomAccessIterator begin, RandomAccessIterator end) const + void sort (RandomAccessIterator begin, RandomAccessIterator end, Parallel_tag) const { +#ifndef CGAL_LINKED_WITH_TBB + CGAL_static_assertion_msg (!(boost::is_convertible::value), + "Parallel_tag is enabled but TBB is unavailable."); +#else const int y = (x + 1) % 3, z = (x + 2) % 3; if ((end - begin) <= _limit) return; RandomAccessIterator m0 = begin, m8 = end; -#if defined( CGAL_LINKED_WITH_TBB) && ( ! defined (CGAL_NO_PARALLEL_SPATIAL_SORT) ) if((end - begin) > 1024){ RandomAccessIterator m1, m2, m3, m4, m5, m6, m7; m4 = internal::hilbert_split(m0, m8, Cmp(_k)); @@ -197,15 +202,19 @@ public: } else { recursive_sort<0, false, false, false>(begin, end); } -#else - recursive_sort<0, false, false, false>(begin, end); -#endif +#endif } - + + template + void sort (RandomAccessIterator begin, RandomAccessIterator end, Sequential_tag) const + { + recursive_sort<0, false, false, false>(begin, end); + } + template void operator() (RandomAccessIterator begin, RandomAccessIterator end) const { - sort <0, false, false, false> (begin, end); + sort <0, false, false, false> (begin, end, ConcurrencyTag()); } }; diff --git a/Spatial_sorting/include/CGAL/spatial_sort.h b/Spatial_sorting/include/CGAL/spatial_sort.h index 8aa44ff6af7..d49dbf39927 100644 --- a/Spatial_sorting/include/CGAL/spatial_sort.h +++ b/Spatial_sorting/include/CGAL/spatial_sort.h @@ -29,7 +29,7 @@ namespace CGAL { namespace internal { - template + template void spatial_sort ( RandomAccessIterator begin, RandomAccessIterator end, const Kernel &k, @@ -41,7 +41,7 @@ namespace internal { { typedef std::iterator_traits Iterator_traits; typedef typename Iterator_traits::difference_type Diff_t; - typedef Hilbert_sort_2 Sort; + typedef Hilbert_sort_2 Sort; boost::rand48 random; boost::random_number_generator rng(random); CGAL::cpp98::random_shuffle(begin,end,rng); @@ -54,7 +54,7 @@ namespace internal { threshold_multiscale, ratio)) (begin, end); } - template + template void spatial_sort ( RandomAccessIterator begin, RandomAccessIterator end, const Kernel &k, @@ -66,7 +66,7 @@ namespace internal { { typedef std::iterator_traits Iterator_traits; typedef typename Iterator_traits::difference_type Diff_t; - typedef Hilbert_sort_3 Sort; + typedef Hilbert_sort_3 Sort; boost::rand48 random; boost::random_number_generator rng(random); CGAL::cpp98::random_shuffle(begin,end, rng); @@ -79,7 +79,7 @@ namespace internal { threshold_multiscale, ratio)) (begin, end); } - template + template void spatial_sort ( RandomAccessIterator begin, RandomAccessIterator end, const Kernel &k, @@ -104,10 +104,10 @@ namespace internal { threshold_multiscale, ratio)) (begin, end); } -} +} //namespace internal -template +template void spatial_sort (RandomAccessIterator begin, RandomAccessIterator end, const Kernel &k, Policy policy, @@ -118,11 +118,11 @@ void spatial_sort (RandomAccessIterator begin, RandomAccessIterator end, typedef std::iterator_traits ITraits; typedef typename ITraits::value_type value_type; - internal::spatial_sort(begin, end, k, policy, static_cast (0), + internal::spatial_sort(begin, end, k, policy, static_cast (0), threshold_hilbert,threshold_multiscale,ratio); } -template +template void spatial_sort (RandomAccessIterator begin, RandomAccessIterator end, Hilbert_sort_median_policy policy, std::ptrdiff_t threshold_hilbert=0, @@ -134,10 +134,11 @@ void spatial_sort (RandomAccessIterator begin, RandomAccessIterator end, typedef CGAL::Kernel_traits KTraits; typedef typename KTraits::Kernel Kernel; - spatial_sort (begin, end, Kernel(), policy, + spatial_sort (begin, end, Kernel(), policy, threshold_hilbert,threshold_multiscale,ratio); } -template + +template void spatial_sort (RandomAccessIterator begin, RandomAccessIterator end, Hilbert_sort_middle_policy policy, std::ptrdiff_t threshold_hilbert=0, @@ -149,30 +150,30 @@ void spatial_sort (RandomAccessIterator begin, RandomAccessIterator end, typedef CGAL::Kernel_traits KTraits; typedef typename KTraits::Kernel Kernel; - spatial_sort (begin, end, Kernel(), policy, + spatial_sort (begin, end, Kernel(), policy, threshold_hilbert,threshold_multiscale,ratio); } -template +template void spatial_sort (RandomAccessIterator begin, RandomAccessIterator end, const Kernel &k, std::ptrdiff_t threshold_hilbert=0, std::ptrdiff_t threshold_multiscale=0, double ratio=0.0) { - spatial_sort (begin, end, k, + spatial_sort (begin, end, k, Hilbert_sort_median_policy(), threshold_hilbert,threshold_multiscale,ratio); } -template + template void spatial_sort (RandomAccessIterator begin, RandomAccessIterator end, std::ptrdiff_t threshold_hilbert=0, std::ptrdiff_t threshold_multiscale=0, double ratio=0.0) { - spatial_sort (begin, end, + spatial_sort (begin, end, Hilbert_sort_median_policy(), threshold_hilbert,threshold_multiscale,ratio); } From b98d2f68760f638e49cae7e5f2b1199c586210b9 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 4 Nov 2019 16:45:30 +0100 Subject: [PATCH 008/185] Fix examples --- .../doc/Spatial_sorting/examples.txt | 1 + .../examples/Spatial_sorting/parallel.cpp | 4 +-- Spatial_sorting/include/CGAL/Hilbert_sort_2.h | 2 +- Spatial_sorting/include/CGAL/Hilbert_sort_3.h | 2 +- .../include/CGAL/Hilbert_sort_median_2.h | 1 + .../include/CGAL/Hilbert_sort_on_sphere_3.h | 2 +- Spatial_sorting/include/CGAL/hilbert_sort.h | 34 +++++++++---------- .../include/CGAL/Delaunay_triangulation_3.h | 7 ++-- 8 files changed, 28 insertions(+), 25 deletions(-) diff --git a/Spatial_sorting/doc/Spatial_sorting/examples.txt b/Spatial_sorting/doc/Spatial_sorting/examples.txt index b0d1275d633..557e126b519 100644 --- a/Spatial_sorting/doc/Spatial_sorting/examples.txt +++ b/Spatial_sorting/doc/Spatial_sorting/examples.txt @@ -1,4 +1,5 @@ /*! +\example Spatial_sorting/parallel.cpp \example Spatial_sorting/hilbert.cpp \example Spatial_sorting/hilbert_policies.cpp \example Spatial_sorting/small_example_delaunay_2.cpp diff --git a/Spatial_sorting/examples/Spatial_sorting/parallel.cpp b/Spatial_sorting/examples/Spatial_sorting/parallel.cpp index dd00d063b4b..d198c879275 100644 --- a/Spatial_sorting/examples/Spatial_sorting/parallel.cpp +++ b/Spatial_sorting/examples/Spatial_sorting/parallel.cpp @@ -17,12 +17,12 @@ typedef CGAL::Creator_uniform_3 Creator_3; int main(int argc, char* argv[]) { std::vector points; - v.reserve (2000); + points.reserve (2000); CGAL::Random_points_in_cube_3 gen (1.0); for (int i = 0; i < 2000; ++i){ - v.push_back (*gen++); + points.push_back (*gen++); } #ifdef CGAL_LINKED_WITH_TBB CGAL::spatial_sort(points.begin(),points.end()); diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_2.h b/Spatial_sorting/include/CGAL/Hilbert_sort_2.h index b4e4fa308d1..b784365a176 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_2.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_2.h @@ -18,7 +18,7 @@ namespace CGAL { -template +template class Hilbert_sort_2; template diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_3.h b/Spatial_sorting/include/CGAL/Hilbert_sort_3.h index 158937f49e5..486eec6c401 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_3.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_3.h @@ -18,7 +18,7 @@ namespace CGAL { - template + template class Hilbert_sort_3; template diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h b/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h index 68511bfee5c..a3d176b4d56 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h @@ -13,6 +13,7 @@ #define CGAL_HILBERT_SORT_MEDIAN_2_H #include +#include #include #include #include diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_on_sphere_3.h b/Spatial_sorting/include/CGAL/Hilbert_sort_on_sphere_3.h index c45dc9038d3..1ec734a9367 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_on_sphere_3.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_on_sphere_3.h @@ -42,7 +42,7 @@ class Hilbert_sort_on_sphere_3 { typedef internal::Transform_coordinates_traits_3 Face_5_traits_3; // -z +x typedef internal::Transform_coordinates_traits_3 Face_6_traits_3; // +x +y - Hilbert_sort_2 _hs_1_object; + Hilbert_sort_2 _hs_1_object; Hilbert_sort_2 _hs_2_object; Hilbert_sort_2 _hs_3_object; Hilbert_sort_2 _hs_4_object; diff --git a/Spatial_sorting/include/CGAL/hilbert_sort.h b/Spatial_sorting/include/CGAL/hilbert_sort.h index 13db962df86..0a1e8552e9b 100644 --- a/Spatial_sorting/include/CGAL/hilbert_sort.h +++ b/Spatial_sorting/include/CGAL/hilbert_sort.h @@ -31,7 +31,7 @@ namespace CGAL { namespace internal { - template + template void hilbert_sort (RandomAccessIterator begin, RandomAccessIterator end, const Kernel &k, @@ -43,10 +43,10 @@ namespace internal { boost::rand48 random; boost::random_number_generator rng(random); CGAL::cpp98::random_shuffle(begin,end, rng); - (Hilbert_sort_2 (k))(begin, end); + (Hilbert_sort_2 (k))(begin, end); } - template + template void hilbert_sort (RandomAccessIterator begin, RandomAccessIterator end, const Kernel &k, @@ -58,10 +58,10 @@ namespace internal { boost::rand48 random; boost::random_number_generator rng(random); CGAL::cpp98::random_shuffle(begin,end, rng); - (Hilbert_sort_3 (k))(begin, end); + (Hilbert_sort_3 (k))(begin, end); } - template + template void hilbert_sort (RandomAccessIterator begin, RandomAccessIterator end, const Kernel &k, @@ -75,9 +75,9 @@ namespace internal { CGAL::cpp98::random_shuffle(begin,end, rng); (Hilbert_sort_d (k))(begin, end); } -} +} // namespace internal -template +template void hilbert_sort (RandomAccessIterator begin, RandomAccessIterator end) { @@ -86,23 +86,23 @@ void hilbert_sort (RandomAccessIterator begin, RandomAccessIterator end) typedef CGAL::Kernel_traits KTraits; typedef typename KTraits::Kernel Kernel; - internal::hilbert_sort(begin, end, Kernel(), Hilbert_sort_median_policy(), + internal::hilbert_sort(begin, end, Kernel(), Hilbert_sort_median_policy(), static_cast (0)); } -template +template void hilbert_sort (RandomAccessIterator begin, RandomAccessIterator end, const Kernel &k) { typedef std::iterator_traits ITraits; typedef typename ITraits::value_type value_type; - internal::hilbert_sort(begin, end, k, Hilbert_sort_median_policy(), + internal::hilbert_sort(begin, end, k, Hilbert_sort_median_policy(), static_cast (0)); } - template + template void hilbert_sort (RandomAccessIterator begin, RandomAccessIterator end, Hilbert_sort_median_policy policy) { @@ -111,13 +111,13 @@ void hilbert_sort (RandomAccessIterator begin, RandomAccessIterator end, typedef CGAL::Kernel_traits KTraits; typedef typename KTraits::Kernel Kernel; - internal::hilbert_sort(begin, end, Kernel(), policy, + internal::hilbert_sort(begin, end, Kernel(), policy, static_cast (0)); } - template + template void hilbert_sort (RandomAccessIterator begin, RandomAccessIterator end, Hilbert_sort_middle_policy policy) { @@ -126,21 +126,21 @@ void hilbert_sort (RandomAccessIterator begin, RandomAccessIterator end, typedef CGAL::Kernel_traits KTraits; typedef typename KTraits::Kernel Kernel; - internal::hilbert_sort(begin, end, Kernel(), policy, + internal::hilbert_sort(begin, end, Kernel(), policy, static_cast (0)); } - template + template void hilbert_sort (RandomAccessIterator begin, RandomAccessIterator end, const Kernel &k, Policy policy) { typedef std::iterator_traits ITraits; typedef typename ITraits::value_type value_type; - internal::hilbert_sort(begin, end, - k, policy, static_cast (0)); + internal::hilbert_sort(begin, end, + k, policy, static_cast (0)); } } // namespace CGAL diff --git a/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h b/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h index 28d2b3f086f..6f6bb69fa2a 100644 --- a/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h +++ b/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h @@ -93,6 +93,7 @@ class Delaunay_triangulation_3 typedef Delaunay_triangulation_3 Self; public: + typedef typename Tds::Concurrency_tag Concurrency_tag; typedef Triangulation_3 Tr_Base; typedef Tds Triangulation_data_structure; @@ -349,7 +350,7 @@ public: size_type n = number_of_vertices(); std::vector points(first, last); - spatial_sort(points.begin(), points.end(), geom_traits()); + spatial_sort(points.begin(), points.end(), geom_traits()); // Parallel #ifdef CGAL_LINKED_WITH_TBB @@ -425,8 +426,8 @@ private: typedef typename Pointer_property_map::type Pmap; typedef Spatial_sort_traits_adapter_3 Search_traits; - spatial_sort(indices.begin(), indices.end(), - Search_traits(make_property_map(points),geom_traits())); + spatial_sort(indices.begin(), indices.end(), + Search_traits(make_property_map(points),geom_traits())); #ifdef CGAL_LINKED_WITH_TBB if(this->is_parallel()) From 914981fca6cb616f899d16c951d89735971ef732 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Tue, 5 Nov 2019 11:05:12 +0100 Subject: [PATCH 009/185] Polish documentation --- .../doc/Spatial_sorting/CGAL/Hilbert_sort_2.h | 8 ++++-- .../doc/Spatial_sorting/CGAL/Hilbert_sort_3.h | 8 ++++-- .../doc/Spatial_sorting/CGAL/hilbert_sort.h | 26 ++++++++++++------- .../CGAL/hilbert_sort_on_sphere.h | 15 +++++------ .../doc/Spatial_sorting/CGAL/spatial_sort.h | 23 ++++++++-------- .../include/CGAL/Hilbert_sort_median_3.h | 1 + 6 files changed, 48 insertions(+), 33 deletions(-) diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_2.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_2.h index afd639b5040..15dbdec157f 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_2.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_2.h @@ -9,10 +9,14 @@ at the median or the middle depending on the `PolicyTag`. -\tparam Traits must be a model for `SpatialSortingTraits`. +\tparam Traits must be a model of the concept `SpatialSortingTraits_2`. +\tparam PolicyTag must be `Hilbert_sort_median_policy` or `Hilbert_sort_middle_policy`. + +\tparam ConcurrencyTag must be `Sequential_tag`or `Parallel_tag`. With `Parallel_tag` +and TBB enabled, for the median policy up to four threads are used in parallel. */ -template< typename Traits, typename PolicyTag > + template< typename Traits, typename PolicyTag, typename ConcurrencyTag = Sequential_tag > class Hilbert_sort_2 { public: diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_3.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_3.h index 194c33e6206..6ee0d8deb6a 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_3.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_3.h @@ -7,10 +7,14 @@ The function object `Hilbert_sort_3` sorts iterator ranges of `Traits::Point_3` along a Hilbert curve by recursively subdividing at the median or the middle depending on the `PolicyTag`. -\tparam Traits must be a model for `SpatialSortingTraits_3`. +\tparam Traits must be a model of the concept `SpatialSortingTraits_3`. +\tparam PolicyTag must be `Hilbert_sort_median_policy` or `Hilbert_sort_middle_policy`. + +\tparam ConcurrencyTag must be `Sequential_tag`or `Parallel_tag`. With `Parallel_tag` +and TBB enabled, for the median policy up to eight threads are used in parallel. */ -template< typename Traits, typename PolicyTag > +template< typename Traits, typename PolicyTag, typename ConcurrencyTag = Sequential_tag > class Hilbert_sort_3 { public: diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h index c724e3be723..c416b65f945 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h @@ -8,18 +8,26 @@ along a Hilbert curve. It sorts the range `[begin, end)` in place. + +\tparam ConcurrencyTag With `ConcurrencyTag = Parallel_tag` and with TBB found, the sorting will be +done in 4 threads in 2D, and in 8 threads in 3D with the default policy. + +\tparam RandomAccessIterator +`std::iterator_traits::%value_type` must be convertible to +`Traits::Point_2`, `Traits::Point_3`, or `Traits::Point_d`. + +\tparam Traits must be a model for concept `SpatialSortingTraits_2`, +`SpatialSortingTraits_3`, or `SpatialSortingTraits_d`. The default traits class `Default_traits` is the kernel in which the type `std::iterator_traits::%value_type` is defined. -The default policy is `Hilbert_sort_median_policy()` and the + +\tparam PolicyTag The default policy is `Hilbert_sort_median_policy()` and the other option is `Hilbert_sort_middle_policy()`. \cgalHeading{Requirements}
    -
  1. `std::iterator_traits::%value_type` is convertible to -`Traits::Point_2`, `Traits::Point_3`, or `Traits::Point_d`. -
  2. `Traits` is a model for concept `SpatialSortingTraits_2`, -`SpatialSortingTraits_3`, or `SpatialSortingTraits_d`. +
\cgalHeading{Implementation} @@ -31,12 +39,12 @@ Creates an instance of and calls its `operator()`. */ -template +template void hilbert_sort( RandomAccessIterator begin, -RandomAccessIterator end, -const Traits& traits = Default_traits, -PolicyTag policy = Default_policy); + RandomAccessIterator end, + const Traits& traits = Default_traits, + PolicyTag policy = Default_policy); } /* namespace CGAL */ diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort_on_sphere.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort_on_sphere.h index 308a7e18f0c..7da9fab177f 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort_on_sphere.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort_on_sphere.h @@ -9,23 +9,20 @@ If input points are not close to the input sphere, this function still works, bu It sorts the range `[begin, end)` in place. +\tparam RandomAccessIterator `std::iterator_traits::%value_type` must be convertible to +`Traits::Point_3`. + +\tparam Traits must be a model for concept `SpatialSortingTraits_3`. The default traits class `Default_traits` is the kernel in which the type `std::iterator_traits::%value_type` is defined. -The default policy is `Hilbert_sort_median_policy()` and the + +\tparam PolicyTag The default policy is `Hilbert_sort_median_policy()` and the other option is `Hilbert_sort_middle_policy()`. The input sphere is given by a squared radius and a center, parameter `sqr_radius` and parameter `center` respectively. The default squared radius of the sphere is 1.0. The default center of the sphere is the origin (0,0,0). -\cgalHeading{Requirements} - -
    -
  1. `std::iterator_traits::%value_type` is convertible to -`Traits::Point_3`. -
  2. `Traits` is a model for concept `SpatialSortingTraits_3`. -
- \cgalHeading{Precondition}
    diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h index bec60e92aa8..6c29794f6a9 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h @@ -10,22 +10,23 @@ of being close in the order. It sorts the range `[begin, end)` in place. +\tparam ConcurrencyTag must be `Sequential_tag`or `Parallel_tag`. +With `Parallel_tag` and TBB enabled, the sorting will be +done using up to four threads in 2D, and up to eight threads in 3D with the median policy. + +\tparam RandomAccessIterator `std::iterator_traits::%value_type` must be convertible to +`Traits::Point_2`, `Traits::Point_3`, or `Traits::Point_d`. + +\tparam Traits must be a model for concept `SpatialSortingTraits_2`, +`SpatialSortingTraits_3`, or `SpatialSortingTraits_d`. The default traits class `Default_traits` is the kernel in which the type `std::iterator_traits::%value_type` is defined. -The default policy is `Hilbert_sort_median_policy()` and the -other option is `Hilbert_sort_middle_policy()`. +\tparam PolicyTag The default policy is `Hilbert_sort_median_policy` and the +other option is `Hilbert_sort_middle_policy`. The default values for the thresholds and the ratio depend on the dimension. -\cgalHeading{Requirements} - -
      -
    1. `std::iterator_traits::%value_type` is convertible to -`Traits::Point_2`, `Traits::Point_3`, or `Traits::Point_d`. -
    2. `Traits` is a model for concept `SpatialSortingTraits_2`, -`SpatialSortingTraits_3`, or `SpatialSortingTraits_d`. -
    \cgalHeading{Implementation} @@ -44,7 +45,7 @@ times the original size of the set, Hilbert sort is applied on the second subset. */ -template + template void spatial_sort( RandomAccessIterator begin, RandomAccessIterator end, diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h b/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h index 86a1d3343a1..e92e8421b13 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h @@ -13,6 +13,7 @@ #define CGAL_HILBERT_SORT_MEDIAN_3_H #include +#include #include #include #include From dea6d34167487517e19e6a9f28a0dd0c8716bd0e Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Tue, 5 Nov 2019 11:11:47 +0100 Subject: [PATCH 010/185] Polish documentation --- Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt | 5 +++++ Spatial_sorting/examples/Spatial_sorting/CMakeLists.txt | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt b/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt index e726f56299d..3feb361c595 100644 --- a/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt +++ b/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt @@ -208,6 +208,11 @@ In this example program, the sorted sequence of points is retrieved using the indices of the points in a vector of pairs of points and integers. \cgalExample{Spatial_sorting/sp_sort_using_property_map_d.cpp} +\section Spatial_sortingParallel Spatial Sorting in Parallel + +The Hilbert sort and spatial sort functions when using the median policy and with TBB +enabled, are parallized and use up to four/eight threads for 2D/3D. + \section Spatial_sortingDesign Design and Implementation History The first implementation of Hilbert and spatial sorting (2D and 3D) in CGAL was done by Cristophe Delage. Then, Olivier Devillers improved its design, diff --git a/Spatial_sorting/examples/Spatial_sorting/CMakeLists.txt b/Spatial_sorting/examples/Spatial_sorting/CMakeLists.txt index 35887344bff..a285126fbe6 100644 --- a/Spatial_sorting/examples/Spatial_sorting/CMakeLists.txt +++ b/Spatial_sorting/examples/Spatial_sorting/CMakeLists.txt @@ -1,4 +1,3 @@ -# Created by the script cgal_create_cmake_script # This is the CMake script for compiling a CGAL application. From cc75efdbb5d0fccbb2ca1853f5f4d4d454e4a468 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 7 Nov 2019 15:57:23 +0100 Subject: [PATCH 011/185] Add static filter for Coplanar_3 --- .../CGAL/internal/Static_filters/Coplanar_3.h | 54 +++++++++++++++++++ .../internal/Static_filters/Static_filters.h | 9 ++++ .../include/CGAL/Kernel/interface_macros.h | 2 +- 3 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 Filtered_kernel/include/CGAL/internal/Static_filters/Coplanar_3.h diff --git a/Filtered_kernel/include/CGAL/internal/Static_filters/Coplanar_3.h b/Filtered_kernel/include/CGAL/internal/Static_filters/Coplanar_3.h new file mode 100644 index 00000000000..20fbade4402 --- /dev/null +++ b/Filtered_kernel/include/CGAL/internal/Static_filters/Coplanar_3.h @@ -0,0 +1,54 @@ +// Copyright (c) 2011 GeometryFactory (France) +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Andreas Fabri, Laurent Rineau + + +#ifndef CGAL_INTERNAL_STATIC_FILTERS_COPLANAR_3_H +#define CGAL_INTERNAL_STATIC_FILTERS_COPLANAR_3_H + +namespace CGAL { + +namespace internal { + +namespace Static_filters_predicates { + + +template < typename K_base, typename SFK > +class Coplanar_3 + : public K_base::Coplanar_3 +{ + typedef typename K_base::Point_3 Point_3; + typedef typename K_base::Coplanar_3 Base; + typedef typename SFK::Orientation_3 Orientation_3; + +public: + + typedef typename Base::result_type result_type; + + + + result_type + operator()(const Point_3& p,const Point_3& q, const Point_3& r, const Point_3& s) const + { + return Orientation_3()(p,q,r,s) == COPLANAR; + } + + + +}; // end class Coplanar_3 + +} // end namespace Static_filters_predicates + +} // end namespace internal + +} // end namespace CGAL + +#endif // CGAL_INTERNAL_STATIC_FILTERS_COPLANAR_3_H diff --git a/Filtered_kernel/include/CGAL/internal/Static_filters/Static_filters.h b/Filtered_kernel/include/CGAL/internal/Static_filters/Static_filters.h index 9dbf6c02f5b..95216db79f9 100644 --- a/Filtered_kernel/include/CGAL/internal/Static_filters/Static_filters.h +++ b/Filtered_kernel/include/CGAL/internal/Static_filters/Static_filters.h @@ -42,6 +42,8 @@ #endif // CGAL_DISABLE_STATIC_FILTERS_ADDED_2011 +# include + #ifndef CGAL_NO_EQUAL_3_STATIC_FILTERS # include # include @@ -96,6 +98,7 @@ class Static_filters : public K_base { typedef Static_filters Self; + typedef Static_filters_predicates::Coplanar_3 Coplanar_3; public: #ifndef CGAL_NO_EQUAL_3_STATIC_FILTERS typedef Static_filters_predicates::Equal_2 Equal_2; @@ -137,6 +140,12 @@ public: collinear_3_object() const { return Collinear_3(); } + Coplanar_3 + coplanar_3_object() const + { + return Coplanar_3(); + } + #ifndef CGAL_NO_EQUAL_3_STATIC_FILTERS Equal_2 equal_2_object() const diff --git a/Kernel_23/include/CGAL/Kernel/interface_macros.h b/Kernel_23/include/CGAL/Kernel/interface_macros.h index efe62876159..18d35b53366 100644 --- a/Kernel_23/include/CGAL/Kernel/interface_macros.h +++ b/Kernel_23/include/CGAL/Kernel/interface_macros.h @@ -488,7 +488,7 @@ CGAL_Kernel_pred_RT(Coplanar_orientation_3, coplanar_orientation_3_object) CGAL_Kernel_pred_RT(Coplanar_side_of_bounded_circle_3, coplanar_side_of_bounded_circle_3_object) -CGAL_Kernel_pred(Coplanar_3, +CGAL_Kernel_pred_RT(Coplanar_3, coplanar_3_object) CGAL_Kernel_pred(Counterclockwise_in_between_2, counterclockwise_in_between_2_object) From 21bd1af50526a69371c4cde930de60fa9b9f1cb3 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 7 Nov 2019 17:54:46 +0100 Subject: [PATCH 012/185] Avoid chains of next and target --- .../self_intersections.h | 95 +++++++++---------- 1 file changed, 47 insertions(+), 48 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index 409bdc4900d..7d09bc5ea1d 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -73,6 +73,7 @@ struct Intersect_facets typedef typename Kernel::Segment_3 Segment; typedef typename Kernel::Triangle_3 Triangle; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::property_map::const_type Ppmap; // members @@ -102,6 +103,17 @@ struct Intersect_facets void operator()(const Box* b, const Box* c) const { halfedge_descriptor h = halfedge(b->info(), m_tmesh); + halfedge_descriptor g = halfedge(c->info(),m_tmesh); + + vertex_descriptor hv[3], gv[3]; + hv[0] = target(h, m_tmesh); + hv[1] = target(next(h, m_tmesh), m_tmesh); + hv[2] = source(h, m_tmesh); + + gv[0] = target(g, m_tmesh); + gv[1] = target(next(g, m_tmesh), m_tmesh); + gv[2] = source(g, m_tmesh); + halfedge_descriptor opp_h; // check for shared egde @@ -110,13 +122,13 @@ struct Intersect_facets if(face(opp_h, m_tmesh) == c->info()){ // there is an intersection if the four points are coplanar and // the triangles overlap - if(CGAL::coplanar(get(m_vpmap, target(h, m_tmesh)), - get(m_vpmap, target(next(h, m_tmesh), m_tmesh)), - get(m_vpmap, source(h, m_tmesh)), + if(CGAL::coplanar(get(m_vpmap, hv[i]), + get(m_vpmap, hv[(i+1)&3]), + get(m_vpmap, hv[(i+2)&3]), get(m_vpmap, target(next(opp_h, m_tmesh), m_tmesh))) && - CGAL::coplanar_orientation(get(m_vpmap, source(h, m_tmesh)), - get(m_vpmap, target(h, m_tmesh)), - get(m_vpmap, target(next(h, m_tmesh), m_tmesh)), + CGAL::coplanar_orientation(get(m_vpmap, hv[(i+2)&3]), + get(m_vpmap, hv[i]), + get(m_vpmap, hv[(i+1)&3]), get(m_vpmap, target(next(opp_h, m_tmesh), m_tmesh))) == CGAL::POSITIVE){ *m_iterator_wrapper++ = std::make_pair(b->info(), c->info()); @@ -129,50 +141,37 @@ struct Intersect_facets } // check for shared vertex --> maybe intersection, maybe not - halfedge_descriptor g = halfedge(c->info(),m_tmesh); + halfedge_descriptor v; - if(target(h,m_tmesh) == target(g,m_tmesh)) - v = g; - if(target(h,m_tmesh) == target(next(g,m_tmesh),m_tmesh)) - v = next(g,m_tmesh); - if(target(h,m_tmesh) == target(next(next(g,m_tmesh),m_tmesh),m_tmesh)) - v = next(next(g,m_tmesh),m_tmesh); - - if(v == halfedge_descriptor()){ - h = next(h,m_tmesh); - if(target(h,m_tmesh) == target(g,m_tmesh)) - v = g; - if(target(h,m_tmesh) == target(next(g,m_tmesh),m_tmesh)) - v = next(g,m_tmesh); - if(target(h,m_tmesh) == target(next(next(g,m_tmesh),m_tmesh),m_tmesh)) - v = next(next(g,m_tmesh),m_tmesh); - if(v == halfedge_descriptor()){ - h = next(h,m_tmesh); - if(target(h,m_tmesh) == target(g,m_tmesh)) - v = g; - if(target(h,m_tmesh) == target(next(g,m_tmesh),m_tmesh)) - v = next(g,m_tmesh); - if(target(h,m_tmesh) == target(next(next(g,m_tmesh),m_tmesh),m_tmesh)) - v = next(next(g,m_tmesh),m_tmesh); + int i(0),j(0); + bool shared = false; + for(; i < 3 && (! shared); ++i){ + for(j = 0; j < 3 && (! shared); ++j){ + if(hv[i]==gv[j]){ + shared = true; + break; + } + if(shared){ + break; + } } } - - if(v != halfedge_descriptor()){ + if(shared){ // found shared vertex: CGAL_assertion(target(h,m_tmesh) == target(v,m_tmesh)); // geometric check if the opposite segments intersect the triangles - Triangle t1 = triangle_functor( get(m_vpmap,target(h,m_tmesh)), - get(m_vpmap, target(next(h,m_tmesh),m_tmesh)), - get(m_vpmap, target(next(next(h,m_tmesh),m_tmesh),m_tmesh))); - Triangle t2 = triangle_functor( get(m_vpmap, target(v,m_tmesh)), - get(m_vpmap, target(next(v,m_tmesh),m_tmesh)), - get(m_vpmap, target(next(next(v,m_tmesh),m_tmesh),m_tmesh))); + Triangle t1 = triangle_functor( get(m_vpmap, hv[0]), + get(m_vpmap, hv[1]), + get(m_vpmap, hv[2])); + Triangle t2 = triangle_functor( get(m_vpmap, gv[0]), + get(m_vpmap, gv[1]), + get(m_vpmap, gv[2])); - Segment s1 = segment_functor( get(m_vpmap, target(next(h,m_tmesh),m_tmesh)), - get(m_vpmap, target(next(next(h,m_tmesh),m_tmesh),m_tmesh))); - Segment s2 = segment_functor( get(m_vpmap, target(next(v,m_tmesh),m_tmesh)), - get(m_vpmap, target(next(next(v,m_tmesh),m_tmesh),m_tmesh))); + Segment s1 = segment_functor( get(m_vpmap, hv[(i+1)&3]), + get(m_vpmap, hv[(i+2)&3]) ); + Segment s2 = segment_functor( get(m_vpmap, gv[(j+1)&3]), + get(m_vpmap, gv[(j+2)&3])); if(do_intersect_3_functor(t1,s2)){ *m_iterator_wrapper++ = std::make_pair(b->info(), c->info()); @@ -183,12 +182,12 @@ struct Intersect_facets } // check for geometric intersection - Triangle t1 = triangle_functor( get(m_vpmap, target(h,m_tmesh)), - get(m_vpmap, target(next(h,m_tmesh),m_tmesh)), - get(m_vpmap, target(next(next(h,m_tmesh),m_tmesh),m_tmesh))); - Triangle t2 = triangle_functor( get(m_vpmap, target(g,m_tmesh)), - get(m_vpmap, target(next(g,m_tmesh),m_tmesh)), - get(m_vpmap, target(next(next(g,m_tmesh),m_tmesh),m_tmesh))); + Triangle t1 = triangle_functor( get(m_vpmap, hv[0]), + get(m_vpmap, hv[1]), + get(m_vpmap, hv[2])); + Triangle t2 = triangle_functor( get(m_vpmap, gv[0]), + get(m_vpmap, gv[1]), + get(m_vpmap, gv[2])); if(do_intersect_3_functor(t1, t2)){ *m_iterator_wrapper++ = std::make_pair(b->info(), c->info()); } From e18413c9b5016f7d29c72b4acf8d4d3ab8d83164 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 7 Nov 2019 21:26:53 +0100 Subject: [PATCH 013/185] fixes --- .../self_intersections.h | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index 7d09bc5ea1d..decbb718f93 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -122,13 +122,18 @@ struct Intersect_facets if(face(opp_h, m_tmesh) == c->info()){ // there is an intersection if the four points are coplanar and // the triangles overlap + get(m_vpmap, hv[i]); + get(m_vpmap, hv[(i + 1) % 3]); + get(m_vpmap, hv[(i + 2) % 3]); + get(m_vpmap, target(next(opp_h, m_tmesh), m_tmesh)); + if(CGAL::coplanar(get(m_vpmap, hv[i]), - get(m_vpmap, hv[(i+1)&3]), - get(m_vpmap, hv[(i+2)&3]), + get(m_vpmap, hv[(i+1)%3]), + get(m_vpmap, hv[(i+2)%3]), get(m_vpmap, target(next(opp_h, m_tmesh), m_tmesh))) && - CGAL::coplanar_orientation(get(m_vpmap, hv[(i+2)&3]), + CGAL::coplanar_orientation(get(m_vpmap, hv[(i+2)%3]), get(m_vpmap, hv[i]), - get(m_vpmap, hv[(i+1)&3]), + get(m_vpmap, hv[(i+1)%3]), get(m_vpmap, target(next(opp_h, m_tmesh), m_tmesh))) == CGAL::POSITIVE){ *m_iterator_wrapper++ = std::make_pair(b->info(), c->info()); @@ -152,14 +157,14 @@ struct Intersect_facets shared = true; break; } - if(shared){ - break; - } } + if (shared) { + break; + } } if(shared){ // found shared vertex: - CGAL_assertion(target(h,m_tmesh) == target(v,m_tmesh)); + assert(hv[i] == gv[j]); // geometric check if the opposite segments intersect the triangles Triangle t1 = triangle_functor( get(m_vpmap, hv[0]), get(m_vpmap, hv[1]), @@ -168,10 +173,10 @@ struct Intersect_facets get(m_vpmap, gv[1]), get(m_vpmap, gv[2])); - Segment s1 = segment_functor( get(m_vpmap, hv[(i+1)&3]), - get(m_vpmap, hv[(i+2)&3]) ); - Segment s2 = segment_functor( get(m_vpmap, gv[(j+1)&3]), - get(m_vpmap, gv[(j+2)&3])); + Segment s1 = segment_functor( get(m_vpmap, hv[(i+1)%3]), + get(m_vpmap, hv[(i+2)%3]) ); + Segment s2 = segment_functor( get(m_vpmap, gv[(j+1)%3]), + get(m_vpmap, gv[(j+2)%3])); if(do_intersect_3_functor(t1,s2)){ *m_iterator_wrapper++ = std::make_pair(b->info(), c->info()); From b6bc521c22dfd24e6393740eb9d896d2a1d964d1 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 8 Nov 2019 16:21:20 +0100 Subject: [PATCH 014/185] WIP does not even compile --- .../CGAL/Box_intersection_d/segment_tree.h | 65 ++++------------- .../include/CGAL/box_intersection_d.h | 9 ++- .../Polygon_mesh_processing/CMakeLists.txt | 1 + .../self_intersections_example.cpp | 12 +++- .../self_intersections.h | 72 +++++++++++++++++-- 5 files changed, 99 insertions(+), 60 deletions(-) diff --git a/Box_intersection_d/include/CGAL/Box_intersection_d/segment_tree.h b/Box_intersection_d/include/CGAL/Box_intersection_d/segment_tree.h index 74a113c46b8..d7514750c9b 100644 --- a/Box_intersection_d/include/CGAL/Box_intersection_d/segment_tree.h +++ b/Box_intersection_d/include/CGAL/Box_intersection_d/segment_tree.h @@ -24,7 +24,8 @@ #include #include - +#include +#include #include #include #include @@ -93,8 +94,8 @@ void one_way_scan( RandomAccessIter1 p_begin, RandomAccessIter1 p_end, bool in_order = true ) { typedef typename Traits::Compare Compare; - std::sort( p_begin, p_end, Compare( 0 ) ); - std::sort( i_begin, i_end, Compare( 0 ) ); + tbb::parallel_sort( p_begin, p_end, Compare( 0 ) ); + tbb::parallel_sort( i_begin, i_end, Compare( 0 ) ); // for each box viewed as interval i for( RandomAccessIter2 i = i_begin; i != i_end; ++i ) { @@ -133,8 +134,8 @@ void modified_two_way_scan( { typedef typename Traits::Compare Compare; - std::sort( p_begin, p_end, Compare( 0 ) ); - std::sort( i_begin, i_end, Compare( 0 ) ); + tbb::parallel_sort( p_begin, p_end, Compare( 0 ) ); + tbb::parallel_sort( i_begin, i_end, Compare( 0 ) ); // for each box viewed as interval while( i_begin != i_end && p_begin != p_end ) { @@ -323,7 +324,8 @@ void segment_tree( RandomAccessIter1 p_begin, RandomAccessIter1 p_end, RandomAccessIter2 i_begin, RandomAccessIter2 i_end, T lo, T hi, Callback callback, Predicate_traits traits, - std::ptrdiff_t cutoff, int dim, bool in_order ) + std::ptrdiff_t cutoff, int dim, bool in_order, + tbb::task_group& tg) { typedef typename Predicate_traits::Spanning Spanning; typedef typename Predicate_traits::Lo_less Lo_less; @@ -332,37 +334,10 @@ void segment_tree( RandomAccessIter1 p_begin, RandomAccessIter1 p_end, const T inf = box_limits< T >::inf(); const T sup = box_limits< T >::sup(); -#if CGAL_BOX_INTERSECTION_DEBUG - CGAL_STATIC_THREAD_LOCAL_VARIABLE(int, level, -1); - Counter bla( level ); - CGAL_BOX_INTERSECTION_DUMP("range: [" << lo << "," << hi << ") dim " - << dim << std::endl ) - CGAL_BOX_INTERSECTION_DUMP("intervals: " ) - //dump_box_numbers( i_begin, i_end, traits ); - dump_intervals( i_begin, i_end, traits, dim ); - CGAL_BOX_INTERSECTION_DUMP("points: " ) - //dump_box_numbers( p_begin, p_end, traits ); - dump_points( p_begin, p_end, traits, dim ); -#endif - -#if CGAL_SEGMENT_TREE_CHECK_INVARIANTS - { - // first: each point is inside segment [lo,hi) - for( RandomAccessIter1 it = p_begin; it != p_end; ++it ) { - CGAL_assertion( Lo_less( hi, dim )(*it) ); - CGAL_assertion( Lo_less( lo, dim )(*it) == false ); - } - // second: each interval intersects segment [lo,hi) - for( RandomAccessIter2 it = i_begin; it != i_end; ++it ) - CGAL_assertion( Hi_greater(lo,dim)(*it) && Lo_less(hi,dim)(*it)); - } -#endif - if( p_begin == p_end || i_begin == i_end || lo >= hi ) return; if( dim == 0 ) { - CGAL_BOX_INTERSECTION_DUMP( "dim = 0. scanning ... " << std::endl ) one_way_scan( p_begin, p_end, i_begin, i_end, callback, traits, dim, in_order ); return; @@ -371,7 +346,6 @@ void segment_tree( RandomAccessIter1 p_begin, RandomAccessIter1 p_end, if( std::distance( p_begin, p_end ) < cutoff || std::distance( i_begin, i_end ) < cutoff ) { - CGAL_BOX_INTERSECTION_DUMP( "scanning ... " << std::endl ) modified_two_way_scan( p_begin, p_end, i_begin, i_end, callback, traits, dim, in_order ); return; @@ -381,23 +355,18 @@ void segment_tree( RandomAccessIter1 p_begin, RandomAccessIter1 p_end, std::partition( i_begin, i_end, Spanning( lo, hi, dim ) ); if( i_begin != i_span_end ) { - CGAL_BOX_INTERSECTION_DUMP( "checking spanning intervals ... " - << std::endl ) + // make two calls for roots of segment tree at next level. segment_tree( p_begin, p_end, i_begin, i_span_end, inf, sup, - callback, traits, cutoff, dim - 1, in_order ); + callback, traits, cutoff, dim - 1, in_order, tg ); segment_tree( i_begin, i_span_end, p_begin, p_end, inf, sup, - callback, traits, cutoff, dim - 1, !in_order ); + callback, traits, cutoff, dim - 1, !in_order, tg ); } T mi; RandomAccessIter1 p_mid = split_points( p_begin, p_end, traits, dim, mi ); if( p_mid == p_begin || p_mid == p_end ) { - CGAL_BOX_INTERSECTION_DUMP( "unable to split points! ") - //dump_points( p_begin, p_end, traits, dim ); - CGAL_BOX_INTERSECTION_DUMP( "performing modified two_way_san ... " - << std::endl ) modified_two_way_scan( p_begin, p_end, i_span_end, i_end, callback, traits, dim, in_order ); return; @@ -407,21 +376,17 @@ void segment_tree( RandomAccessIter1 p_begin, RandomAccessIter1 p_end, // separate left intervals. // left intervals have a low point strictly less than mi i_mid = std::partition( i_span_end, i_end, Lo_less( mi, dim ) ); - CGAL_BOX_INTERSECTION_DUMP("->left" << std::endl ) + segment_tree( p_begin, p_mid, i_span_end, i_mid, lo, mi, - callback, traits, cutoff, dim, in_order ); + callback, traits, cutoff, dim, in_order, tg ); // separate right intervals. // right intervals have a high point strictly higher than mi i_mid = std::partition( i_span_end, i_end, Hi_greater( mi, dim ) ); - CGAL_BOX_INTERSECTION_DUMP("->right"<< std::endl ) + segment_tree( p_mid, p_end, i_span_end, i_mid, mi, hi, - callback, traits, cutoff, dim, in_order ); + callback, traits, cutoff, dim, in_order, tg ); } -#if CGAL_BOX_INTERSECTION_DEBUG - #undef CGAL_BOX_INTERSECTION_DUMP -#endif -#undef CGAL_BOX_INTERSECTION_DEBUG } // end namespace Box_intersection_d diff --git a/Box_intersection_d/include/CGAL/box_intersection_d.h b/Box_intersection_d/include/CGAL/box_intersection_d.h index d7952400617..d2e3415ed8e 100644 --- a/Box_intersection_d/include/CGAL/box_intersection_d.h +++ b/Box_intersection_d/include/CGAL/box_intersection_d.h @@ -25,6 +25,8 @@ #include #include +#include + #include namespace CGAL { @@ -40,6 +42,7 @@ void box_intersection_custom_predicates_d( std::ptrdiff_t cutoff = 10, Box_intersection_d::Setting setting = Box_intersection_d::BIPARTITE) { + tbb::task_group tg; typedef BoxPredicateTraits Traits; typedef typename Traits::NT NT; CGAL_assertion( Traits::dimension() > 0 ); @@ -47,10 +50,12 @@ void box_intersection_custom_predicates_d( const NT inf = Box_intersection_d::box_limits::inf(); const NT sup = Box_intersection_d::box_limits::sup(); Box_intersection_d::segment_tree(begin1, end1, begin2, end2, - inf, sup, callback, traits, cutoff, dim, true); + inf, sup, callback, traits, cutoff, dim, true, tg); if(setting == Box_intersection_d::BIPARTITE) Box_intersection_d::segment_tree(begin2, end2, begin1, end1, - inf, sup, callback, traits, cutoff, dim, false); + inf, sup, callback, traits, cutoff, dim, false, tg); + + tg.wait(); } diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt index 88701b9e196..eeebbd3e6cc 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt @@ -108,6 +108,7 @@ endif(OpenMesh_FOUND) find_package( TBB ) if( TBB_FOUND ) + CGAL_target_use_TBB(self_intersections_example) CGAL_target_use_TBB(hausdorff_distance_remeshing_example) else() message( STATUS "NOTICE: Intel TBB was not found. Sequential code will be used." ) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp index 93a2de84858..403d22786a0 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp @@ -2,6 +2,8 @@ #include #include +#include +#include #include @@ -22,17 +24,23 @@ int main(int argc, char* argv[]) std::cerr << "Not a valid input file." << std::endl; return 1; } - + /* bool intersecting = PMP::does_self_intersect(mesh, PMP::parameters::vertex_point_map(get(CGAL::vertex_point, mesh))); std::cout << (intersecting ? "There are self-intersections." : "There is no self-intersection.") << std::endl; + */ + CGAL::Real_timer rtimer; + CGAL::Timer timer; + rtimer.start(); + timer.start(); + std::vector > intersected_tris; PMP::self_intersections(mesh, std::back_inserter(intersected_tris)); - + std::cout << rtimer.time() << " " << timer.time() << " sec." << std::endl; std::cout << intersected_tris.size() << " pairs of triangles intersect." << std::endl; return 0; diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index decbb718f93..e18be4a35d4 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -40,12 +40,17 @@ #include #include +#include +#include + #ifdef DOXYGEN_RUNNING #define CGAL_PMP_NP_TEMPLATE_PARAMETERS NamedParameters #define CGAL_PMP_NP_CLASS NamedParameters #endif namespace CGAL { + + namespace internal { template &r) const + { + for (std::size_t i = r.begin(); i != r.end(); ++i) { + vertex_descriptor vd(i); + if(degree(vd, m_tmesh)<= 3){ + return; + } + halfedge_descriptor hd = halfedge(vd, m_tmesh), done(hd); + + do { //for each hd with vd as target + // no need to look at the neighbor faces + // later do the shared edge test with them + Triangle th = triangle_functor( get(m_vpmap, vd), + get(m_vpmap, source(hd,m_tmesh)), + get(m_vpmap, target(next(hd,m_tmesh), m_tmesh)) ); + halfedge_descriptor start = prev(opposite(prev(opposite(hd,m_tmesh),m_tmesh),m_tmesh),m_tmesh); + halfedge_descriptor stop = opposite(next(hd,m_tmesh),m_tmesh); + while(start != stop){ + if(start < h){ + Segment ss = segment_functor(get(m_vpmap, source(start,m_tmesh)), + get(m_vpmap, target(next(start,m_tmesh), m_tmesh))); + if(do_intersect_3_functor(th, ss)){ + *m_iterator_wrapper++ = std::make_pair(face(h,m_tmesh), face(start, m_tmesh)); + } + } + start = prev(opposite(hd,m_tmesh),m_tmesh); + } + ++hd; + }while(hd != done); + } + } + void operator()(const Box* b, const Box* c) const { halfedge_descriptor h = halfedge(b->info(), m_tmesh); @@ -163,6 +200,7 @@ struct Intersect_facets } } if(shared){ +#if 0 // found shared vertex: assert(hv[i] == gv[j]); // geometric check if the opposite segments intersect the triangles @@ -183,6 +221,7 @@ struct Intersect_facets } else if(do_intersect_3_functor(t2,s1)){ *m_iterator_wrapper++ = std::make_pair(b->info(), c->info()); } +#endif return; } @@ -211,6 +250,8 @@ struct Throw_at_output { }// namespace internal + + namespace Polygon_mesh_processing { #ifndef DOXYGEN_RUNNING @@ -226,6 +267,7 @@ self_intersections( const FaceRange& face_range, const NamedParameters& np); #endif + /** * \ingroup PMP_intersection_grp * detects and records self-intersections of a triangulated surface mesh. @@ -253,22 +295,27 @@ self_intersections( const FaceRange& face_range, * * @return `out` */ + + template #else //avoid ambiguity with self_intersections(faces, tmesh, out) - , class P, class T, class R + , class P, class T, class R> #endif -> + + OutputIterator self_intersections(const TriangleMesh& tmesh , OutputIterator out #ifdef DOXYGEN_RUNNING - , const NamedParameters& np) + , const NamedParameters& np #else - , const Named_function_parameters& np) + , const Named_function_parameters& np #endif + ) + { return self_intersections(faces(tmesh), tmesh, out, np); } @@ -281,6 +328,8 @@ self_intersections(const TriangleMesh& tmesh, OutputIterator out) return self_intersections(tmesh, out, CGAL::Polygon_mesh_processing::parameters::all_default()); } + + /// \endcond /*! @@ -326,6 +375,7 @@ self_intersections( const FaceRange& face_range, typedef TriangleMesh TM; typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename CGAL::Box_intersection_d::Box_with_info_d Box; // make one box per facet @@ -357,8 +407,18 @@ self_intersections( const FaceRange& face_range, for(Box& b : boxes) box_ptr.push_back(&b); - // compute self-intersections filtered out by boxes + typedef typename GetGeomTraits::type GeomTraits; + + Emptyset_iterator dev0; + CGAL::internal::Intersect_facets + intersect_facets_parallel(tmesh, dev0, vpmap, + parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits), GeomTraits())); + + std::cout << "do it"<< std::endl; + tbb::parallel_for(tbb::blocked_range(0, num_vertices(tmesh)), intersect_facets_parallel); + + // compute self-intersections filtered out by boxes CGAL::internal::Intersect_facets intersect_facets(tmesh, out, vpmap, parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits), GeomTraits())); From 19487c78a2491061dd8c4f5ea2fb71f23e260117 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 11 Nov 2019 13:38:28 +0100 Subject: [PATCH 015/185] fix warning --- Spatial_sorting/examples/Spatial_sorting/parallel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Spatial_sorting/examples/Spatial_sorting/parallel.cpp b/Spatial_sorting/examples/Spatial_sorting/parallel.cpp index d198c879275..2914be56562 100644 --- a/Spatial_sorting/examples/Spatial_sorting/parallel.cpp +++ b/Spatial_sorting/examples/Spatial_sorting/parallel.cpp @@ -14,7 +14,7 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef K::Point_3 Point_3; typedef CGAL::Creator_uniform_3 Creator_3; -int main(int argc, char* argv[]) +int main() { std::vector points; points.reserve (2000); From ead0da3c7749c1d3327e713f51ee1d7ba7f274e7 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Tue, 12 Nov 2019 11:40:40 +0100 Subject: [PATCH 016/185] WIP: not the same number of intersections for Tuyaeaux.stl --- .../CGAL/Box_intersection_d/segment_tree.h | 12 +- .../include/CGAL/box_intersection_d.h | 7 +- .../self_intersections_example.cpp | 6 +- .../self_intersections.h | 223 +++++++++++++++--- 4 files changed, 197 insertions(+), 51 deletions(-) diff --git a/Box_intersection_d/include/CGAL/Box_intersection_d/segment_tree.h b/Box_intersection_d/include/CGAL/Box_intersection_d/segment_tree.h index d7514750c9b..c54cae50f28 100644 --- a/Box_intersection_d/include/CGAL/Box_intersection_d/segment_tree.h +++ b/Box_intersection_d/include/CGAL/Box_intersection_d/segment_tree.h @@ -25,7 +25,6 @@ #include #include -#include #include #include #include @@ -324,8 +323,7 @@ void segment_tree( RandomAccessIter1 p_begin, RandomAccessIter1 p_end, RandomAccessIter2 i_begin, RandomAccessIter2 i_end, T lo, T hi, Callback callback, Predicate_traits traits, - std::ptrdiff_t cutoff, int dim, bool in_order, - tbb::task_group& tg) + std::ptrdiff_t cutoff, int dim, bool in_order) { typedef typename Predicate_traits::Spanning Spanning; typedef typename Predicate_traits::Lo_less Lo_less; @@ -358,9 +356,9 @@ void segment_tree( RandomAccessIter1 p_begin, RandomAccessIter1 p_end, // make two calls for roots of segment tree at next level. segment_tree( p_begin, p_end, i_begin, i_span_end, inf, sup, - callback, traits, cutoff, dim - 1, in_order, tg ); + callback, traits, cutoff, dim - 1, in_order ); segment_tree( i_begin, i_span_end, p_begin, p_end, inf, sup, - callback, traits, cutoff, dim - 1, !in_order, tg ); + callback, traits, cutoff, dim - 1, !in_order ); } T mi; @@ -378,13 +376,13 @@ void segment_tree( RandomAccessIter1 p_begin, RandomAccessIter1 p_end, i_mid = std::partition( i_span_end, i_end, Lo_less( mi, dim ) ); segment_tree( p_begin, p_mid, i_span_end, i_mid, lo, mi, - callback, traits, cutoff, dim, in_order, tg ); + callback, traits, cutoff, dim, in_order ); // separate right intervals. // right intervals have a high point strictly higher than mi i_mid = std::partition( i_span_end, i_end, Hi_greater( mi, dim ) ); segment_tree( p_mid, p_end, i_span_end, i_mid, mi, hi, - callback, traits, cutoff, dim, in_order, tg ); + callback, traits, cutoff, dim, in_order ); } diff --git a/Box_intersection_d/include/CGAL/box_intersection_d.h b/Box_intersection_d/include/CGAL/box_intersection_d.h index d2e3415ed8e..bf5a8f3d62a 100644 --- a/Box_intersection_d/include/CGAL/box_intersection_d.h +++ b/Box_intersection_d/include/CGAL/box_intersection_d.h @@ -25,7 +25,6 @@ #include #include -#include #include @@ -42,7 +41,6 @@ void box_intersection_custom_predicates_d( std::ptrdiff_t cutoff = 10, Box_intersection_d::Setting setting = Box_intersection_d::BIPARTITE) { - tbb::task_group tg; typedef BoxPredicateTraits Traits; typedef typename Traits::NT NT; CGAL_assertion( Traits::dimension() > 0 ); @@ -50,12 +48,11 @@ void box_intersection_custom_predicates_d( const NT inf = Box_intersection_d::box_limits::inf(); const NT sup = Box_intersection_d::box_limits::sup(); Box_intersection_d::segment_tree(begin1, end1, begin2, end2, - inf, sup, callback, traits, cutoff, dim, true, tg); + inf, sup, callback, traits, cutoff, dim, true); if(setting == Box_intersection_d::BIPARTITE) Box_intersection_d::segment_tree(begin2, end2, begin1, end1, - inf, sup, callback, traits, cutoff, dim, false, tg); + inf, sup, callback, traits, cutoff, dim, false); - tg.wait(); } diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp index 403d22786a0..0db9f8b95ab 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp @@ -1,3 +1,4 @@ +int I,J,KK; #include #include @@ -15,6 +16,7 @@ namespace PMP = CGAL::Polygon_mesh_processing; int main(int argc, char* argv[]) { + I = J = KK = 0; const char* filename = (argc > 1) ? argv[1] : "data/pig.off"; std::ifstream input(filename); @@ -42,6 +44,8 @@ int main(int argc, char* argv[]) PMP::self_intersections(mesh, std::back_inserter(intersected_tris)); std::cout << rtimer.time() << " " << timer.time() << " sec." << std::endl; std::cout << intersected_tris.size() << " pairs of triangles intersect." << std::endl; - + std::cout << "I = " << I << std::endl; + std::cout << "J = " << J << std::endl; + std::cout << "KK = " << KK << std::endl; return 0; } diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index e18be4a35d4..eda406ef940 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -27,6 +27,7 @@ #include +#include #include #include #include @@ -42,6 +43,7 @@ #include #include +#include #ifdef DOXYGEN_RUNNING #define CGAL_PMP_NP_TEMPLATE_PARAMETERS NamedParameters @@ -50,8 +52,69 @@ namespace CGAL { - namespace internal { + +template +struct TriangleTriangle { + const TM& m_tmesh; + const VertexPointMap m_vpmap; + typename Kernel::Construct_triangle_3 triangle_functor; + typename Kernel::Do_intersect_3 do_intersect_3_functor; + typedef typename Kernel::Triangle_3 Triangle; + + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + const std::vector >& seq_v_faces; + std::vector& dointersect; + mutable bool result; + + + TriangleTriangle(const std::vector >& seq_v_faces, + std::vector& dointersect, + const TM& tmesh, VertexPointMap vpmap, const Kernel& kernel) + : seq_v_faces(seq_v_faces), + m_tmesh(tmesh), + m_vpmap(vpmap), + triangle_functor(kernel.construct_triangle_3_object()), + do_intersect_3_functor(kernel.do_intersect_3_object()), + dointersect(dointersect), + result(false) + {} + + void operator()(const tbb::blocked_range &r) const + { + for (std::size_t i = r.begin(); i != r.end(); ++i) { + const std::pair& tt = seq_v_faces[i]; + + halfedge_descriptor h = halfedge(tt.first, m_tmesh); + halfedge_descriptor g = halfedge(tt.second ,m_tmesh); + + vertex_descriptor hv[3], gv[3]; + hv[0] = target(h, m_tmesh); + hv[1] = target(next(h, m_tmesh), m_tmesh); + hv[2] = source(h, m_tmesh); + + gv[0] = target(g, m_tmesh); + gv[1] = target(next(g, m_tmesh), m_tmesh); + gv[2] = source(g, m_tmesh); + Triangle t1 = triangle_functor( get(m_vpmap, hv[0]), + get(m_vpmap, hv[1]), + get(m_vpmap, hv[2])); + Triangle t2 = triangle_functor( get(m_vpmap, gv[0]), + get(m_vpmap, gv[1]), + get(m_vpmap, gv[2])); + if(do_intersect_3_functor(t1, t2)){ + dointersect[i] = true; + result = true; + } + } + } +}; + + template ::halfedge_descriptor halfedge_descriptor; @@ -109,30 +173,66 @@ struct Intersect_facets { for (std::size_t i = r.begin(); i != r.end(); ++i) { vertex_descriptor vd(i); - if(degree(vd, m_tmesh)<= 3){ - return; - } + halfedge_descriptor hd = halfedge(vd, m_tmesh), done(hd); - - do { //for each hd with vd as target - // no need to look at the neighbor faces - // later do the shared edge test with them - Triangle th = triangle_functor( get(m_vpmap, vd), - get(m_vpmap, source(hd,m_tmesh)), - get(m_vpmap, target(next(hd,m_tmesh), m_tmesh)) ); - halfedge_descriptor start = prev(opposite(prev(opposite(hd,m_tmesh),m_tmesh),m_tmesh),m_tmesh); - halfedge_descriptor stop = opposite(next(hd,m_tmesh),m_tmesh); - while(start != stop){ - if(start < h){ - Segment ss = segment_functor(get(m_vpmap, source(start,m_tmesh)), - get(m_vpmap, target(next(start,m_tmesh), m_tmesh))); - if(do_intersect_3_functor(th, ss)){ - *m_iterator_wrapper++ = std::make_pair(face(h,m_tmesh), face(start, m_tmesh)); - } - } - start = prev(opposite(hd,m_tmesh),m_tmesh); + if(is_border(hd, m_tmesh)){ + hd = prev(opposite(hd,m_tmesh),m_tmesh); } - ++hd; + + do { //for each hd with vd as target look at all other faces + Point p = get(m_vpmap, vd); + Point q = get(m_vpmap, target(next(hd,m_tmesh), m_tmesh)); + Point r = get(m_vpmap, source(hd,m_tmesh)); + + //std::ostringstream out; + //out << std::endl << "p = " << p << std::endl; + //out << "q = " << q << std::endl; + //out << "r = " << r << std::endl; + + + Triangle th = triangle_functor(p, q, r); + + // first look at the directly shared edges + halfedge_descriptor ohd = opposite(hd, m_tmesh); + if((! is_border(ohd,m_tmesh)) && (hd < ohd)){ + vertex_descriptor ov = target(next(ohd,m_tmesh), m_tmesh); + Point s = get(m_vpmap, ov); + //out << "s 1 = " << s << std::endl; + J++; + if(CGAL::coplanar(p,q,r,s) && CGAL::coplanar_orientation(r,p,q,s) == POSITIVE){ + //out << "coplanar 1" << std::endl; + *m_iterator_wrapper++ = std::make_pair(face(hd,m_tmesh), face(ohd, m_tmesh)); + } + } + ohd = opposite(next(hd,m_tmesh), m_tmesh); + if((! is_border(ohd,m_tmesh)) && (hd < ohd)){ + vertex_descriptor ov = target(next(ohd,m_tmesh), m_tmesh); + Point s = get(m_vpmap, ov); + //out << "s 2 = " << s << std::endl; + J++; + if(CGAL::coplanar(p,q,r,s) && CGAL::coplanar_orientation(p,q,r,s) == POSITIVE){ + //out << "coplanar 2" << std::endl; + *m_iterator_wrapper++ = std::make_pair(face(hd,m_tmesh), face(ohd, m_tmesh)); + } + } + //std::cout << out.str() << std::flush; + // no need to look at the oppposite segement for the direct neighbor faces + + halfedge_descriptor po = prev(opposite(hd,m_tmesh),m_tmesh); + halfedge_descriptor op = opposite(next(hd,m_tmesh),m_tmesh); + + for(halfedge_descriptor start : halfedges_around_target(hd,m_tmesh)){ + if((start == hd) || (start == op) || (start == po) || is_border(start, m_tmesh)){ + continue; + } + Segment ss = segment_functor(get(m_vpmap, source(start,m_tmesh)), + get(m_vpmap, target(next(start,m_tmesh), m_tmesh))); + if(do_intersect_3_functor(th, ss)){ + I++; + *m_iterator_wrapper++ = std::make_pair(face(hd,m_tmesh), face(start, m_tmesh)); + } + } + hd = prev(opposite(hd,m_tmesh),m_tmesh); }while(hd != done); } } @@ -153,6 +253,7 @@ struct Intersect_facets halfedge_descriptor opp_h; +#if 0 // check for shared egde for(unsigned int i=0; i<3; ++i){ opp_h = opposite(h, m_tmesh); @@ -181,7 +282,7 @@ struct Intersect_facets } h = next(h, m_tmesh); } - +#endif // check for shared vertex --> maybe intersection, maybe not halfedge_descriptor v; @@ -195,9 +296,9 @@ struct Intersect_facets break; } } - if (shared) { - break; - } + if (shared) { + break; + } } if(shared){ #if 0 @@ -224,7 +325,8 @@ struct Intersect_facets #endif return; } - +#if 0 + KK++; // check for geometric intersection Triangle t1 = triangle_functor( get(m_vpmap, hv[0]), get(m_vpmap, hv[1]), @@ -233,8 +335,11 @@ struct Intersect_facets get(m_vpmap, gv[1]), get(m_vpmap, gv[2])); if(do_intersect_3_functor(t1, t2)){ +#endif *m_iterator_wrapper++ = std::make_pair(b->info(), c->info()); +#if 0 } +#endif } // end operator () }; // end struct Intersect_facets @@ -408,24 +513,66 @@ self_intersections( const FaceRange& face_range, box_ptr.push_back(&b); + // (A) Parallel: look at each vertex and its incident faces + // Intersections are written into a concurrent vector typedef typename GetGeomTraits::type GeomTraits; - Emptyset_iterator dev0; - CGAL::internal::Intersect_facets - intersect_facets_parallel(tmesh, dev0, vpmap, - parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits), GeomTraits())); + typedef tbb::concurrent_vector > CV; + CV cv_faces; + typedef std::back_insert_iterator CVI; - std::cout << "do it"<< std::endl; + CGAL::internal::Intersect_facets + intersect_facets_parallel(tmesh, + std::back_inserter(cv_faces), // result + vpmap, + parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits), GeomTraits())); + + Real_timer rt; + rt.start(); tbb::parallel_for(tbb::blocked_range(0, num_vertices(tmesh)), intersect_facets_parallel); - + + // Copy from the concurent container to the output iterator + for(CV::iterator it = cv_faces.begin(); it != cv_faces.end(); ++it){ + *out ++= *it; + } + std::cout << "parallel_for " << rt.time() << "sec."<< std::endl; + + // (B) Sequential: Look at pairs of triangles with intersecting bbox + // Copy the pairs which do not share an edge or a vertex into a std::vector + rt.reset(); // compute self-intersections filtered out by boxes - CGAL::internal::Intersect_facets - intersect_facets(tmesh, out, vpmap, - parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits), GeomTraits())); + typedef std::vector >SeqV; + SeqV seq_v_faces; + typedef std::back_insert_iterator SeqVI; + + CGAL::internal::Intersect_facets + intersect_facets(tmesh, + std::back_inserter(seq_v_faces), // result + vpmap, + parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits), GeomTraits())); std::ptrdiff_t cutoff = 2000; CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(),intersect_facets,cutoff); - return intersect_facets.m_iterator; + + // (C) Parallel: + std::vector dointersect(seq_v_faces.size()); + CGAL::internal::TriangleTriangle tt(seq_v_faces, + dointersect, + tmesh, + vpmap, + parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits), GeomTraits())); + tbb::parallel_for(tbb::blocked_range(0, seq_v_faces.size()), tt); + if(tt.result){ + std::cout << "there was at least one proper intersection" << std::endl; + } + for(int i = 0; i < seq_v_faces.size(); ++i){ + if(dointersect[i]){ + *out ++= seq_v_faces[i]; + } + } + + std::cout << "box_self_intersection_d " << rt.time() << "sec."<< std::endl; + return out; } /// \cond SKIP_IN_MANUAL From 899d8f7b59437a180e66b2f32b46779c2d046cc1 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Tue, 12 Nov 2019 13:01:26 +0100 Subject: [PATCH 017/185] cleanup --- .../self_intersections_example.cpp | 8 +- .../self_intersections.h | 135 ++++-------------- 2 files changed, 28 insertions(+), 115 deletions(-) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp index 0db9f8b95ab..2ac214c7993 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp @@ -1,4 +1,3 @@ -int I,J,KK; #include #include @@ -16,7 +15,6 @@ namespace PMP = CGAL::Polygon_mesh_processing; int main(int argc, char* argv[]) { - I = J = KK = 0; const char* filename = (argc > 1) ? argv[1] : "data/pig.off"; std::ifstream input(filename); @@ -42,10 +40,8 @@ int main(int argc, char* argv[]) std::vector > intersected_tris; PMP::self_intersections(mesh, std::back_inserter(intersected_tris)); - std::cout << rtimer.time() << " " << timer.time() << " sec." << std::endl; + std::cout << std::endl << "Total: " << rtimer.time() << " " << timer.time() << " sec." << std::endl; std::cout << intersected_tris.size() << " pairs of triangles intersect." << std::endl; - std::cout << "I = " << I << std::endl; - std::cout << "J = " << J << std::endl; - std::cout << "KK = " << KK << std::endl; + return 0; } diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index eda406ef940..7a67358dbcb 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -69,11 +69,12 @@ struct TriangleTriangle { typedef typename boost::graph_traits::face_descriptor face_descriptor; const std::vector >& seq_v_faces; std::vector& dointersect; - mutable bool result; + bool& result; TriangleTriangle(const std::vector >& seq_v_faces, std::vector& dointersect, + bool& result, const TM& tmesh, VertexPointMap vpmap, const Kernel& kernel) : seq_v_faces(seq_v_faces), m_tmesh(tmesh), @@ -81,7 +82,7 @@ struct TriangleTriangle { triangle_functor(kernel.construct_triangle_3_object()), do_intersect_3_functor(kernel.do_intersect_3_object()), dointersect(dointersect), - result(false) + result(result) {} void operator()(const tbb::blocked_range &r) const @@ -184,11 +185,6 @@ struct Intersect_facets Point q = get(m_vpmap, target(next(hd,m_tmesh), m_tmesh)); Point r = get(m_vpmap, source(hd,m_tmesh)); - //std::ostringstream out; - //out << std::endl << "p = " << p << std::endl; - //out << "q = " << q << std::endl; - //out << "r = " << r << std::endl; - Triangle th = triangle_functor(p, q, r); @@ -197,10 +193,7 @@ struct Intersect_facets if((! is_border(ohd,m_tmesh)) && (hd < ohd)){ vertex_descriptor ov = target(next(ohd,m_tmesh), m_tmesh); Point s = get(m_vpmap, ov); - //out << "s 1 = " << s << std::endl; - J++; if(CGAL::coplanar(p,q,r,s) && CGAL::coplanar_orientation(r,p,q,s) == POSITIVE){ - //out << "coplanar 1" << std::endl; *m_iterator_wrapper++ = std::make_pair(face(hd,m_tmesh), face(ohd, m_tmesh)); } } @@ -208,27 +201,20 @@ struct Intersect_facets if((! is_border(ohd,m_tmesh)) && (hd < ohd)){ vertex_descriptor ov = target(next(ohd,m_tmesh), m_tmesh); Point s = get(m_vpmap, ov); - //out << "s 2 = " << s << std::endl; - J++; if(CGAL::coplanar(p,q,r,s) && CGAL::coplanar_orientation(p,q,r,s) == POSITIVE){ - //out << "coplanar 2" << std::endl; *m_iterator_wrapper++ = std::make_pair(face(hd,m_tmesh), face(ohd, m_tmesh)); } } - //std::cout << out.str() << std::flush; - // no need to look at the oppposite segement for the direct neighbor faces - halfedge_descriptor po = prev(opposite(hd,m_tmesh),m_tmesh); halfedge_descriptor op = opposite(next(hd,m_tmesh),m_tmesh); for(halfedge_descriptor start : halfedges_around_target(hd,m_tmesh)){ - if((start == hd) || (start == op) || (start == po) || is_border(start, m_tmesh)){ + if((start == hd) || (start == op) || (start == po) || is_border(start, m_tmesh) || (face(hd, m_tmesh) < face(start, m_tmesh))){ continue; } Segment ss = segment_functor(get(m_vpmap, source(start,m_tmesh)), get(m_vpmap, target(next(start,m_tmesh), m_tmesh))); if(do_intersect_3_functor(th, ss)){ - I++; *m_iterator_wrapper++ = std::make_pair(face(hd,m_tmesh), face(start, m_tmesh)); } } @@ -253,93 +239,21 @@ struct Intersect_facets halfedge_descriptor opp_h; -#if 0 - // check for shared egde - for(unsigned int i=0; i<3; ++i){ - opp_h = opposite(h, m_tmesh); - if(face(opp_h, m_tmesh) == c->info()){ - // there is an intersection if the four points are coplanar and - // the triangles overlap - get(m_vpmap, hv[i]); - get(m_vpmap, hv[(i + 1) % 3]); - get(m_vpmap, hv[(i + 2) % 3]); - get(m_vpmap, target(next(opp_h, m_tmesh), m_tmesh)); - if(CGAL::coplanar(get(m_vpmap, hv[i]), - get(m_vpmap, hv[(i+1)%3]), - get(m_vpmap, hv[(i+2)%3]), - get(m_vpmap, target(next(opp_h, m_tmesh), m_tmesh))) && - CGAL::coplanar_orientation(get(m_vpmap, hv[(i+2)%3]), - get(m_vpmap, hv[i]), - get(m_vpmap, hv[(i+1)%3]), - get(m_vpmap, target(next(opp_h, m_tmesh), m_tmesh))) - == CGAL::POSITIVE){ - *m_iterator_wrapper++ = std::make_pair(b->info(), c->info()); - return; - } else { // there is a shared edge but no intersection - return; - } - } - h = next(h, m_tmesh); - } -#endif - // check for shared vertex --> maybe intersection, maybe not + // ignore shared vertex as already dealt with halfedge_descriptor v; int i(0),j(0); - bool shared = false; - for(; i < 3 && (! shared); ++i){ - for(j = 0; j < 3 && (! shared); ++j){ + for(; i < 3; ++i){ + for(j = 0; j < 3; ++j){ if(hv[i]==gv[j]){ - shared = true; - break; + return; } } - if (shared) { - break; - } } - if(shared){ -#if 0 - // found shared vertex: - assert(hv[i] == gv[j]); - // geometric check if the opposite segments intersect the triangles - Triangle t1 = triangle_functor( get(m_vpmap, hv[0]), - get(m_vpmap, hv[1]), - get(m_vpmap, hv[2])); - Triangle t2 = triangle_functor( get(m_vpmap, gv[0]), - get(m_vpmap, gv[1]), - get(m_vpmap, gv[2])); - - Segment s1 = segment_functor( get(m_vpmap, hv[(i+1)%3]), - get(m_vpmap, hv[(i+2)%3]) ); - Segment s2 = segment_functor( get(m_vpmap, gv[(j+1)%3]), - get(m_vpmap, gv[(j+2)%3])); - - if(do_intersect_3_functor(t1,s2)){ - *m_iterator_wrapper++ = std::make_pair(b->info(), c->info()); - } else if(do_intersect_3_functor(t2,s1)){ - *m_iterator_wrapper++ = std::make_pair(b->info(), c->info()); - } -#endif - return; - } -#if 0 - KK++; - // check for geometric intersection - Triangle t1 = triangle_functor( get(m_vpmap, hv[0]), - get(m_vpmap, hv[1]), - get(m_vpmap, hv[2])); - Triangle t2 = triangle_functor( get(m_vpmap, gv[0]), - get(m_vpmap, gv[1]), - get(m_vpmap, gv[2])); - if(do_intersect_3_functor(t1, t2)){ -#endif - *m_iterator_wrapper++ = std::make_pair(b->info(), c->info()); -#if 0 - } -#endif + *m_iterator_wrapper++ = std::make_pair(b->info(), c->info()); + } // end operator () }; // end struct Intersect_facets @@ -529,18 +443,18 @@ self_intersections( const FaceRange& face_range, Real_timer rt; rt.start(); + tbb::parallel_for(tbb::blocked_range(0, num_vertices(tmesh)), intersect_facets_parallel); // Copy from the concurent container to the output iterator for(CV::iterator it = cv_faces.begin(); it != cv_faces.end(); ++it){ *out ++= *it; } - std::cout << "parallel_for " << rt.time() << "sec."<< std::endl; - + std::cout << "(A) Parallel: faces incident to each vertex " << rt.time() << "sec."<< std::endl; + rt.reset(); + // (B) Sequential: Look at pairs of triangles with intersecting bbox // Copy the pairs which do not share an edge or a vertex into a std::vector - rt.reset(); - // compute self-intersections filtered out by boxes typedef std::vector >SeqV; SeqV seq_v_faces; typedef std::back_insert_iterator SeqVI; @@ -553,25 +467,28 @@ self_intersections( const FaceRange& face_range, std::ptrdiff_t cutoff = 2000; CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(),intersect_facets,cutoff); - - // (C) Parallel: + std::cout << "(B) Sequential: boxes that intersect " << rt.time() << "sec."<< std::endl; + rt.reset(); + + // (C) Parallel: Perform geometric test on pairs not sharing an edge or a vertex std::vector dointersect(seq_v_faces.size()); + bool result(false); CGAL::internal::TriangleTriangle tt(seq_v_faces, dointersect, + result, tmesh, vpmap, parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits), GeomTraits())); tbb::parallel_for(tbb::blocked_range(0, seq_v_faces.size()), tt); - if(tt.result){ - std::cout << "there was at least one proper intersection" << std::endl; - } - for(int i = 0; i < seq_v_faces.size(); ++i){ - if(dointersect[i]){ - *out ++= seq_v_faces[i]; + if(result){ + for(int i = 0; i < seq_v_faces.size(); ++i){ + if(dointersect[i]){ + *out ++= seq_v_faces[i]; + } } } - std::cout << "box_self_intersection_d " << rt.time() << "sec."<< std::endl; + std::cout << "(C) Parallel: Filter triangles that intersect " << rt.time() << "sec."<< std::endl; return out; } From fc72b37db46032794d3708f311d74b7ec51a46f4 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Tue, 12 Nov 2019 15:31:26 +0100 Subject: [PATCH 018/185] Functor cleanup --- .../self_intersections.h | 281 +++++++++++++++--- 1 file changed, 235 insertions(+), 46 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index 7a67358dbcb..53508614a01 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -53,6 +53,159 @@ namespace CGAL { namespace internal { + + template +struct Intersect_facets +{ + // wrapper to check whether anything is inserted to output iterator + struct Output_iterator_with_bool + { + Output_iterator_with_bool(OutputIterator* out, bool* intersected) + : m_iterator(out), m_intersected(intersected) { } + + template + void operator()(const T& t) { + *m_intersected = true; + *(*m_iterator)++ = t; + } + + OutputIterator* m_iterator; + bool* m_intersected; + }; +// typedefs + typedef typename Kernel::Segment_3 Segment; + typedef typename Kernel::Triangle_3 Triangle; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::property_map::const_type Ppmap; + +// members + const TM& m_tmesh; + const VertexPointMap m_vpmap; + mutable OutputIterator m_iterator; + mutable bool m_intersected; + mutable boost::function_output_iterator m_iterator_wrapper; + + typename Kernel::Construct_segment_3 segment_functor; + typename Kernel::Construct_triangle_3 triangle_functor; + typename Kernel::Do_intersect_3 do_intersect_3_functor; + + + Intersect_facets(const TM& tmesh, OutputIterator it, VertexPointMap vpmap, const Kernel& kernel) + : + m_tmesh(tmesh), + m_vpmap(vpmap), + m_iterator(it), + m_intersected(false), + m_iterator_wrapper(Output_iterator_with_bool(&m_iterator, &m_intersected)), + segment_functor(kernel.construct_segment_3_object()), + triangle_functor(kernel.construct_triangle_3_object()), + do_intersect_3_functor(kernel.do_intersect_3_object()) + { } + + void operator()(const Box* b, const Box* c) const + { + halfedge_descriptor h = halfedge(b->info(), m_tmesh); + halfedge_descriptor g = halfedge(c->info(),m_tmesh); + + vertex_descriptor hv[3], gv[3]; + hv[0] = target(h, m_tmesh); + hv[1] = target(next(h, m_tmesh), m_tmesh); + hv[2] = source(h, m_tmesh); + + gv[0] = target(g, m_tmesh); + gv[1] = target(next(g, m_tmesh), m_tmesh); + gv[2] = source(g, m_tmesh); + + halfedge_descriptor opp_h; + + // check for shared egde + for(unsigned int i=0; i<3; ++i){ + opp_h = opposite(h, m_tmesh); + if(face(opp_h, m_tmesh) == c->info()){ + // there is an intersection if the four points are coplanar and + // the triangles overlap + get(m_vpmap, hv[i]); + get(m_vpmap, hv[(i + 1) % 3]); + get(m_vpmap, hv[(i + 2) % 3]); + get(m_vpmap, target(next(opp_h, m_tmesh), m_tmesh)); + + if(CGAL::coplanar(get(m_vpmap, hv[i]), + get(m_vpmap, hv[(i+1)%3]), + get(m_vpmap, hv[(i+2)%3]), + get(m_vpmap, target(next(opp_h, m_tmesh), m_tmesh))) && + CGAL::coplanar_orientation(get(m_vpmap, hv[(i+2)%3]), + get(m_vpmap, hv[i]), + get(m_vpmap, hv[(i+1)%3]), + get(m_vpmap, target(next(opp_h, m_tmesh), m_tmesh))) + == CGAL::POSITIVE){ + *m_iterator_wrapper++ = std::make_pair(b->info(), c->info()); + return; + } else { // there is a shared edge but no intersection + return; + } + } + h = next(h, m_tmesh); + } + + // check for shared vertex --> maybe intersection, maybe not + + halfedge_descriptor v; + + int i(0),j(0); + bool shared = false; + for(; i < 3 && (! shared); ++i){ + for(j = 0; j < 3 && (! shared); ++j){ + if(hv[i]==gv[j]){ + shared = true; + break; + } + } + if (shared) { + break; + } + } + if(shared){ + // found shared vertex: + assert(hv[i] == gv[j]); + // geometric check if the opposite segments intersect the triangles + Triangle t1 = triangle_functor( get(m_vpmap, hv[0]), + get(m_vpmap, hv[1]), + get(m_vpmap, hv[2])); + Triangle t2 = triangle_functor( get(m_vpmap, gv[0]), + get(m_vpmap, gv[1]), + get(m_vpmap, gv[2])); + + Segment s1 = segment_functor( get(m_vpmap, hv[(i+1)%3]), + get(m_vpmap, hv[(i+2)%3]) ); + Segment s2 = segment_functor( get(m_vpmap, gv[(j+1)%3]), + get(m_vpmap, gv[(j+2)%3])); + + if(do_intersect_3_functor(t1,s2)){ + *m_iterator_wrapper++ = std::make_pair(b->info(), c->info()); + } else if(do_intersect_3_functor(t2,s1)){ + *m_iterator_wrapper++ = std::make_pair(b->info(), c->info()); + } + return; + } + + // check for geometric intersection + Triangle t1 = triangle_functor( get(m_vpmap, hv[0]), + get(m_vpmap, hv[1]), + get(m_vpmap, hv[2])); + Triangle t2 = triangle_functor( get(m_vpmap, gv[0]), + get(m_vpmap, gv[1]), + get(m_vpmap, gv[2])); + if(do_intersect_3_functor(t1, t2)){ + *m_iterator_wrapper++ = std::make_pair(b->info(), c->info()); + } + } // end operator () +}; // end struct Intersect_facets + template +struct Incident_faces_filter +{ + // wrapper to check whether anything is inserted to output iterator + struct Output_iterator_with_bool + { + Output_iterator_with_bool(OutputIterator* out, bool* intersected) + : m_iterator(out), m_intersected(intersected) { } + + template + void operator()(const T& t) { + *m_intersected = true; + *(*m_iterator)++ = t; + } + + OutputIterator* m_iterator; + bool* m_intersected; + }; +// typedefs + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + +// members + const TM& m_tmesh; + mutable OutputIterator m_iterator; + mutable bool m_intersected; + mutable boost::function_output_iterator m_iterator_wrapper; + + + Incident_faces_filter(const TM& tmesh, OutputIterator it) + : m_tmesh(tmesh), + m_iterator(it), + m_iterator_wrapper(Output_iterator_with_bool(&m_iterator, &m_intersected)) + {} + + void operator()(const Box* b, const Box* c) const + { + halfedge_descriptor h = halfedge(b->info(), m_tmesh); + halfedge_descriptor g = halfedge(c->info(),m_tmesh); + + vertex_descriptor hv[3], gv[3]; + hv[0] = target(h, m_tmesh); + hv[1] = target(next(h, m_tmesh), m_tmesh); + hv[2] = source(h, m_tmesh); + + gv[0] = target(g, m_tmesh); + gv[1] = target(next(g, m_tmesh), m_tmesh); + gv[2] = source(g, m_tmesh); + + halfedge_descriptor opp_h; + + // ignore shared vertex as already dealt with + + halfedge_descriptor v; + + int i(0),j(0); + for(; i < 3; ++i){ + for(j = 0; j < 3; ++j){ + if(hv[i]==gv[j]){ + return; + } + } + } + *m_iterator_wrapper++ = std::make_pair(b->info(), c->info()); + + } // end operator () +}; + template -struct Intersect_facets +struct Intersect_facets_incident_to_vertex { // wrapper to check whether anything is inserted to output iterator struct Output_iterator_with_bool @@ -158,7 +381,7 @@ struct Intersect_facets typename Kernel::Do_intersect_3 do_intersect_3_functor; - Intersect_facets(const TM& tmesh, OutputIterator it, VertexPointMap vpmap, const Kernel& kernel) + Intersect_facets_incident_to_vertex(const TM& tmesh, OutputIterator it, VertexPointMap vpmap, const Kernel& kernel) : m_tmesh(tmesh), m_vpmap(vpmap), @@ -223,38 +446,6 @@ struct Intersect_facets } } - void operator()(const Box* b, const Box* c) const - { - halfedge_descriptor h = halfedge(b->info(), m_tmesh); - halfedge_descriptor g = halfedge(c->info(),m_tmesh); - - vertex_descriptor hv[3], gv[3]; - hv[0] = target(h, m_tmesh); - hv[1] = target(next(h, m_tmesh), m_tmesh); - hv[2] = source(h, m_tmesh); - - gv[0] = target(g, m_tmesh); - gv[1] = target(next(g, m_tmesh), m_tmesh); - gv[2] = source(g, m_tmesh); - - halfedge_descriptor opp_h; - - - // ignore shared vertex as already dealt with - - halfedge_descriptor v; - - int i(0),j(0); - for(; i < 3; ++i){ - for(j = 0; j < 3; ++j){ - if(hv[i]==gv[j]){ - return; - } - } - } - *m_iterator_wrapper++ = std::make_pair(b->info(), c->info()); - - } // end operator () }; // end struct Intersect_facets struct Throw_at_output { @@ -435,16 +626,16 @@ self_intersections( const FaceRange& face_range, CV cv_faces; typedef std::back_insert_iterator CVI; - CGAL::internal::Intersect_facets - intersect_facets_parallel(tmesh, - std::back_inserter(cv_faces), // result - vpmap, - parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits), GeomTraits())); + CGAL::internal::Intersect_facets_incident_to_vertex + intersect_facets_incident_to_vertex(tmesh, + std::back_inserter(cv_faces), // result + vpmap, + parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits), GeomTraits())); Real_timer rt; rt.start(); - tbb::parallel_for(tbb::blocked_range(0, num_vertices(tmesh)), intersect_facets_parallel); + tbb::parallel_for(tbb::blocked_range(0, num_vertices(tmesh)), intersect_facets_incident_to_vertex); // Copy from the concurent container to the output iterator for(CV::iterator it = cv_faces.begin(); it != cv_faces.end(); ++it){ @@ -459,14 +650,12 @@ self_intersections( const FaceRange& face_range, SeqV seq_v_faces; typedef std::back_insert_iterator SeqVI; - CGAL::internal::Intersect_facets - intersect_facets(tmesh, - std::back_inserter(seq_v_faces), // result - vpmap, - parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits), GeomTraits())); + CGAL::internal::Incident_faces_filter + incident_faces_filter(tmesh, + std::back_inserter(seq_v_faces)); std::ptrdiff_t cutoff = 2000; - CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(),intersect_facets,cutoff); + CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(),incident_faces_filter,cutoff); std::cout << "(B) Sequential: boxes that intersect " << rt.time() << "sec."<< std::endl; rt.reset(); From 732d1d8f8aa26d0ec335222e41b556ee3c07ef25 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Tue, 12 Nov 2019 16:32:08 +0100 Subject: [PATCH 019/185] Add overloads with ConcurencyTag --- .../self_intersections_example.cpp | 2 +- .../self_intersections.h | 86 ++++++++++++++++--- 2 files changed, 76 insertions(+), 12 deletions(-) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp index 2ac214c7993..440d7738bd5 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp @@ -39,7 +39,7 @@ int main(int argc, char* argv[]) std::vector > intersected_tris; - PMP::self_intersections(mesh, std::back_inserter(intersected_tris)); + PMP::self_intersections(mesh, std::back_inserter(intersected_tris)); std::cout << std::endl << "Total: " << rtimer.time() << " " << timer.time() << " sec." << std::endl; std::cout << intersected_tris.size() << " pairs of triangles intersect." << std::endl; diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index 53508614a01..909a00381f3 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -204,7 +204,7 @@ struct Intersect_facets *m_iterator_wrapper++ = std::make_pair(b->info(), c->info()); } } // end operator () -}; // end struct Intersect_facets + }; // end struct Intersect_facets template OutputIterator self_intersections( const FaceRange& face_range, const TriangleMesh& tmesh, OutputIterator out, - const NamedParameters& np); + const NamedParameters& np, + ConcurrencyTag); #endif @@ -506,8 +508,8 @@ self_intersections( const FaceRange& face_range, * @return `out` */ - -template @@ -527,16 +529,16 @@ self_intersections(const TriangleMesh& tmesh ) { - return self_intersections(faces(tmesh), tmesh, out, np); + return self_intersections(faces(tmesh), tmesh, out, np, ConcurrencyTag()); } /// \cond SKIP_IN_MANUAL -template +template OutputIterator self_intersections(const TriangleMesh& tmesh, OutputIterator out) { - return self_intersections(tmesh, out, - CGAL::Polygon_mesh_processing::parameters::all_default()); + return self_intersections(faces(tmesh), tmesh, out, + CGAL::Polygon_mesh_processing::parameters::all_default(), ConcurrencyTag()); } @@ -579,7 +581,67 @@ OutputIterator self_intersections( const FaceRange& face_range, const TriangleMesh& tmesh, OutputIterator out, - const NamedParameters& np) + const NamedParameters& np, + Sequential_tag) +{ + CGAL_precondition(CGAL::is_triangle_mesh(tmesh)); + + typedef TriangleMesh TM; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef typename CGAL::Box_intersection_d::Box_with_info_d Box; + + // make one box per facet + std::vector boxes; + boxes.reserve( + std::distance( boost::begin(face_range), boost::end(face_range) ) + ); + + typedef typename GetVertexPointMap::const_type VertexPointMap; + VertexPointMap vpmap = parameters::choose_parameter(parameters::get_parameter(np, internal_np::vertex_point), + get_const_property_map(boost::vertex_point, tmesh)); + + for(face_descriptor f : face_range) + { + typename boost::property_traits::reference + p = get(vpmap, target(halfedge(f,tmesh),tmesh)), + q = get(vpmap, target(next(halfedge(f, tmesh), tmesh), tmesh)), + r = get(vpmap, target(next(next(halfedge(f, tmesh), tmesh), tmesh), tmesh)); + + if ( collinear(p, q, r) ) + *out++= std::make_pair(f,f); + else + boxes.push_back(Box(p.bbox() + q.bbox() + r.bbox(), f)); + } + // generate box pointers + std::vector box_ptr; + box_ptr.reserve(num_faces(tmesh)); + + for(Box& b : boxes) + box_ptr.push_back(&b); + + // compute self-intersections filtered out by boxes + typedef typename GetGeomTraits::type GeomTraits; + CGAL::internal::Intersect_facets + intersect_facets(tmesh, out, vpmap, + parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits), GeomTraits())); + + std::ptrdiff_t cutoff = 2000; + CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(),intersect_facets,cutoff); + return intersect_facets.m_iterator; +} + + +template +OutputIterator +self_intersections( const FaceRange& face_range, + const TriangleMesh& tmesh, + OutputIterator out, + const NamedParameters& np, + Parallel_tag) { CGAL_precondition(CGAL::is_triangle_mesh(tmesh)); @@ -682,7 +744,8 @@ self_intersections( const FaceRange& face_range, } /// \cond SKIP_IN_MANUAL -template @@ -691,7 +754,8 @@ OutputIterator self_intersections(const FaceRange& face_range, OutputIterator out) { return self_intersections(face_range, tmesh, out, - CGAL::Polygon_mesh_processing::parameters::all_default()); + CGAL::Polygon_mesh_processing::parameters::all_default(), + ConcurrencyTag()); } /// \endcond From 343ca0b4a7639ff0ee64e6bcb256e39639cc258a Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Tue, 12 Nov 2019 18:27:32 +0100 Subject: [PATCH 020/185] Add the version that reports all pairs of faces and performs the intersection tests in parallel --- .../self_intersections_example.cpp | 2 + .../self_intersections.h | 270 +++++++++++++++++- 2 files changed, 265 insertions(+), 7 deletions(-) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp index 440d7738bd5..179eeec96ca 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp @@ -1,3 +1,5 @@ +struct Parallel_tag_bis {}; + #include #include diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index 909a00381f3..c40df55bae6 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -41,9 +41,11 @@ #include #include +#ifdef CGAL_LINKED_WITH_TBB #include #include #include +#endif #ifdef DOXYGEN_RUNNING #define CGAL_PMP_NP_TEMPLATE_PARAMETERS NamedParameters @@ -81,6 +83,7 @@ struct Intersect_facets typedef typename Kernel::Triangle_3 Triangle; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; typedef typename boost::property_map::const_type Ppmap; // members @@ -108,7 +111,7 @@ struct Intersect_facets { } void operator()(const Box* b, const Box* c) const - { + { halfedge_descriptor h = halfedge(b->info(), m_tmesh); halfedge_descriptor g = halfedge(c->info(),m_tmesh); @@ -206,7 +209,10 @@ struct Intersect_facets } // end operator () }; // end struct Intersect_facets + +#ifdef CGAL_LINKED_WITH_TBB +// The functor for testing only triangles that do not share an edge or vertex in parallel template @@ -269,6 +275,146 @@ struct TriangleTriangle { }; +// The functor for doing all geometric tests in parallel +template +struct AllPairs { + const TM& m_tmesh; + const VertexPointMap m_vpmap; + mutable OutputIterator m_iterator; + typename Kernel::Construct_segment_3 segment_functor; + typename Kernel::Construct_triangle_3 triangle_functor; + typename Kernel::Do_intersect_3 do_intersect_3_functor; + typedef typename Kernel::Segment_3 Segment; + typedef typename Kernel::Triangle_3 Triangle; + + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + const std::vector >& seq_faces; + + + AllPairs(const std::vector >& seq_faces, + OutputIterator it, + const TM& tmesh, VertexPointMap vpmap, const Kernel& kernel) + : seq_faces(seq_faces), + m_tmesh(tmesh), + m_vpmap(vpmap), + m_iterator(it), + triangle_functor(kernel.construct_triangle_3_object()), + do_intersect_3_functor(kernel.do_intersect_3_object()) + {} + + void operator()(const tbb::blocked_range &r) const + { + for (std::size_t ri = r.begin(); ri != r.end(); ++ri) { + const std::pair& ff = seq_faces[ri]; + this->operator()(ff); + } + } + + void operator()(const std::pair& ff) const + { + halfedge_descriptor h = halfedge(ff.first, m_tmesh), g = halfedge(ff.second, m_tmesh); + + vertex_descriptor hv[3], gv[3]; + hv[0] = target(h, m_tmesh); + hv[1] = target(next(h, m_tmesh), m_tmesh); + hv[2] = source(h, m_tmesh); + + gv[0] = target(g, m_tmesh); + gv[1] = target(next(g, m_tmesh), m_tmesh); + gv[2] = source(g, m_tmesh); + + halfedge_descriptor opp_h; + + // check for shared egde + for(unsigned int i=0; i<3; ++i){ + opp_h = opposite(h, m_tmesh); + if(face(opp_h, m_tmesh) == ff.second){ + // there is an intersection if the four points are coplanar and + // the triangles overlap + get(m_vpmap, hv[i]); + get(m_vpmap, hv[(i + 1) % 3]); + get(m_vpmap, hv[(i + 2) % 3]); + get(m_vpmap, target(next(opp_h, m_tmesh), m_tmesh)); + + if(CGAL::coplanar(get(m_vpmap, hv[i]), + get(m_vpmap, hv[(i+1)%3]), + get(m_vpmap, hv[(i+2)%3]), + get(m_vpmap, target(next(opp_h, m_tmesh), m_tmesh))) && + CGAL::coplanar_orientation(get(m_vpmap, hv[(i+2)%3]), + get(m_vpmap, hv[i]), + get(m_vpmap, hv[(i+1)%3]), + get(m_vpmap, target(next(opp_h, m_tmesh), m_tmesh))) + == CGAL::POSITIVE){ + *m_iterator++ = ff; + return; + } else { // there is a shared edge but no intersection + return; + } + } + h = next(h, m_tmesh); + } + + // check for shared vertex --> maybe intersection, maybe not + + halfedge_descriptor v; + + int i(0),j(0); + bool shared = false; + for(; i < 3 && (! shared); ++i){ + for(j = 0; j < 3 && (! shared); ++j){ + if(hv[i]==gv[j]){ + shared = true; + break; + } + } + if (shared) { + break; + } + } + if(shared){ + // found shared vertex: + assert(hv[i] == gv[j]); + // geometric check if the opposite segments intersect the triangles + Triangle t1 = triangle_functor( get(m_vpmap, hv[0]), + get(m_vpmap, hv[1]), + get(m_vpmap, hv[2])); + Triangle t2 = triangle_functor( get(m_vpmap, gv[0]), + get(m_vpmap, gv[1]), + get(m_vpmap, gv[2])); + + Segment s1 = segment_functor( get(m_vpmap, hv[(i+1)%3]), + get(m_vpmap, hv[(i+2)%3]) ); + Segment s2 = segment_functor( get(m_vpmap, gv[(j+1)%3]), + get(m_vpmap, gv[(j+2)%3])); + + if(do_intersect_3_functor(t1,s2)){ + *m_iterator ++ = ff; + } else if(do_intersect_3_functor(t2,s1)){ + *m_iterator ++ = ff; + } + return; + } + + // check for geometric intersection + Triangle t1 = triangle_functor( get(m_vpmap, hv[0]), + get(m_vpmap, hv[1]), + get(m_vpmap, hv[2])); + Triangle t2 = triangle_functor( get(m_vpmap, gv[0]), + get(m_vpmap, gv[1]), + get(m_vpmap, gv[2])); + if(do_intersect_3_functor(t1, t2)){ + *m_iterator ++ = ff; + } + } +}; + + +// The functor for filtering pairs of faces that share an edge or vertex template @@ -339,6 +485,27 @@ struct Incident_faces_filter } // end operator () }; +// The functor that filters nothing +template +struct All_faces_filter +{ + mutable OutputIterator m_iterator; + + + All_faces_filter(OutputIterator it) + : m_iterator(it) + {} + + template + void operator()(const Box* b, const Box* c) const + { + *m_iterator ++ = std::make_pair(b->info(), c->info()); + + } // end operator () +}; + + +// The functor that computes intersections for faces incident to a vertex template box_ptr; - box_ptr.reserve(num_faces(tmesh)); + box_ptr.reserve(boxes.size()); for(Box& b : boxes) box_ptr.push_back(&b); @@ -630,6 +798,7 @@ self_intersections( const FaceRange& face_range, return intersect_facets.m_iterator; } +#ifdef CGAL_LINKED_WITH_TBB template +OutputIterator +self_intersections( const FaceRange& face_range, + const TriangleMesh& tmesh, + OutputIterator out, + const NamedParameters& np, + Parallel_tag) +{ + CGAL_precondition(CGAL::is_triangle_mesh(tmesh)); + + typedef TriangleMesh TM; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename CGAL::Box_intersection_d::Box_with_info_d Box; + + // make one box per facet + std::vector boxes; + boxes.reserve( + std::distance( boost::begin(face_range), boost::end(face_range) ) + ); + + typedef typename GetVertexPointMap::const_type VertexPointMap; + VertexPointMap vpmap = parameters::choose_parameter(parameters::get_parameter(np, internal_np::vertex_point), + get_const_property_map(boost::vertex_point, tmesh)); + + for(face_descriptor f : face_range) + { + typename boost::property_traits::reference + p = get(vpmap, target(halfedge(f,tmesh),tmesh)), + q = get(vpmap, target(next(halfedge(f, tmesh), tmesh), tmesh)), + r = get(vpmap, target(next(next(halfedge(f, tmesh), tmesh), tmesh), tmesh)); + + if ( collinear(p, q, r) ) + *out++= std::make_pair(f,f); + else + boxes.push_back(Box(p.bbox() + q.bbox() + r.bbox(), f)); + } + // generate box pointers + std::vector box_ptr; + box_ptr.reserve(boxes.size()); + + for(Box& b : boxes) + box_ptr.push_back(&b); + + // (A) Sequentially write all pairs of faces with intersecting bbox into a std::vector + std::ptrdiff_t cutoff = 2000; + typedef std::vector >SeqV; + typedef std::back_insert_iterator SeqVI; + SeqV face_pairs; + internal::All_faces_filter all_faces_filter(std::back_inserter(face_pairs)); + CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(),all_faces_filter,cutoff); + + + // (B) Parallel: perform the geometric tests + typedef typename GetGeomTraits::type GeomTraits; + + typedef tbb::concurrent_vector > CV; + CV cv_faces; + typedef std::back_insert_iterator CVI; + + + CGAL::internal::AllPairs + all_pairs(face_pairs, + std::back_inserter(cv_faces), // result + tmesh, + vpmap, + parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits), GeomTraits())); + + Real_timer rt; + rt.start(); + + tbb::parallel_for(tbb::blocked_range(0, face_pairs.size()), all_pairs); + + // (C) Sequentially: Copy from the concurent container to the output iterator + for(CV::iterator it = cv_faces.begin(); it != cv_faces.end(); ++it){ + *out ++= *it; + } + return out; +} +#endif // CGAL_LINKED_WITH_TBB + + /// \cond SKIP_IN_MANUAL template Date: Tue, 12 Nov 2019 18:35:46 +0100 Subject: [PATCH 021/185] Add CGAL_LINKED_WITH_TBB in the Box_intersection_d without ConcurrencyTag --- .../include/CGAL/Box_intersection_d/segment_tree.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Box_intersection_d/include/CGAL/Box_intersection_d/segment_tree.h b/Box_intersection_d/include/CGAL/Box_intersection_d/segment_tree.h index c54cae50f28..e6a9ca0e05e 100644 --- a/Box_intersection_d/include/CGAL/Box_intersection_d/segment_tree.h +++ b/Box_intersection_d/include/CGAL/Box_intersection_d/segment_tree.h @@ -24,7 +24,9 @@ #include #include +#ifdef CGAL_LINKED_WITH_TBB #include +#endif #include #include #include @@ -93,8 +95,14 @@ void one_way_scan( RandomAccessIter1 p_begin, RandomAccessIter1 p_end, bool in_order = true ) { typedef typename Traits::Compare Compare; + +#ifdef CGAL_LINKED_WITH_TBB tbb::parallel_sort( p_begin, p_end, Compare( 0 ) ); tbb::parallel_sort( i_begin, i_end, Compare( 0 ) ); +#else + std::sort( p_begin, p_end, Compare( 0 ) ); + std::sort( i_begin, i_end, Compare( 0 ) ); +#endif // for each box viewed as interval i for( RandomAccessIter2 i = i_begin; i != i_end; ++i ) { @@ -133,8 +141,13 @@ void modified_two_way_scan( { typedef typename Traits::Compare Compare; +#ifdef CGAL_LINKED_WITH_TBB tbb::parallel_sort( p_begin, p_end, Compare( 0 ) ); tbb::parallel_sort( i_begin, i_end, Compare( 0 ) ); +#else + std::sort( p_begin, p_end, Compare( 0 ) ); + std::sort( i_begin, i_end, Compare( 0 ) ); +#endif // for each box viewed as interval while( i_begin != i_end && p_begin != p_end ) { From a35a7ebf9b18795c45f931ff0a195941c29064d8 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Tue, 12 Nov 2019 18:40:17 +0100 Subject: [PATCH 022/185] fix a reserve() --- .../include/CGAL/Polygon_mesh_processing/self_intersections.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index c40df55bae6..d923c0cbbe0 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -843,7 +843,7 @@ self_intersections( const FaceRange& face_range, } // generate box pointers std::vector box_ptr; - box_ptr.reserve(num_faces(tmesh)); + box_ptr.reserve(boxes.size()); for(Box& b : boxes) box_ptr.push_back(&b); From 2d14c67304e0d9b0ebdf4b52de1a71b1e27b59ed Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Wed, 13 Nov 2019 09:07:10 +0100 Subject: [PATCH 023/185] Remove unused class Output_iterator_with_bool --- .../self_intersections.h | 75 +++---------------- 1 file changed, 9 insertions(+), 66 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index d923c0cbbe0..2bbaa472e22 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -62,22 +62,7 @@ namespace internal { class OutputIterator, class VertexPointMap> struct Intersect_facets -{ - // wrapper to check whether anything is inserted to output iterator - struct Output_iterator_with_bool { - Output_iterator_with_bool(OutputIterator* out, bool* intersected) - : m_iterator(out), m_intersected(intersected) { } - - template - void operator()(const T& t) { - *m_intersected = true; - *(*m_iterator)++ = t; - } - - OutputIterator* m_iterator; - bool* m_intersected; - }; // typedefs typedef typename Kernel::Segment_3 Segment; typedef typename Kernel::Triangle_3 Triangle; @@ -90,8 +75,6 @@ struct Intersect_facets const TM& m_tmesh; const VertexPointMap m_vpmap; mutable OutputIterator m_iterator; - mutable bool m_intersected; - mutable boost::function_output_iterator m_iterator_wrapper; typename Kernel::Construct_segment_3 segment_functor; typename Kernel::Construct_triangle_3 triangle_functor; @@ -103,8 +86,6 @@ struct Intersect_facets m_tmesh(tmesh), m_vpmap(vpmap), m_iterator(it), - m_intersected(false), - m_iterator_wrapper(Output_iterator_with_bool(&m_iterator, &m_intersected)), segment_functor(kernel.construct_segment_3_object()), triangle_functor(kernel.construct_triangle_3_object()), do_intersect_3_functor(kernel.do_intersect_3_object()) @@ -146,7 +127,7 @@ struct Intersect_facets get(m_vpmap, hv[(i+1)%3]), get(m_vpmap, target(next(opp_h, m_tmesh), m_tmesh))) == CGAL::POSITIVE){ - *m_iterator_wrapper++ = std::make_pair(b->info(), c->info()); + *m_iterator++ = std::make_pair(b->info(), c->info()); return; } else { // there is a shared edge but no intersection return; @@ -189,9 +170,9 @@ struct Intersect_facets get(m_vpmap, gv[(j+2)%3])); if(do_intersect_3_functor(t1,s2)){ - *m_iterator_wrapper++ = std::make_pair(b->info(), c->info()); + *m_iterator++ = std::make_pair(b->info(), c->info()); } else if(do_intersect_3_functor(t2,s1)){ - *m_iterator_wrapper++ = std::make_pair(b->info(), c->info()); + *m_iterator++ = std::make_pair(b->info(), c->info()); } return; } @@ -204,7 +185,7 @@ struct Intersect_facets get(m_vpmap, gv[1]), get(m_vpmap, gv[2])); if(do_intersect_3_functor(t1, t2)){ - *m_iterator_wrapper++ = std::make_pair(b->info(), c->info()); + *m_iterator++ = std::make_pair(b->info(), c->info()); } } // end operator () }; // end struct Intersect_facets @@ -420,21 +401,6 @@ template struct Incident_faces_filter { - // wrapper to check whether anything is inserted to output iterator - struct Output_iterator_with_bool - { - Output_iterator_with_bool(OutputIterator* out, bool* intersected) - : m_iterator(out), m_intersected(intersected) { } - - template - void operator()(const T& t) { - *m_intersected = true; - *(*m_iterator)++ = t; - } - - OutputIterator* m_iterator; - bool* m_intersected; - }; // typedefs typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; @@ -442,14 +408,10 @@ struct Incident_faces_filter // members const TM& m_tmesh; mutable OutputIterator m_iterator; - mutable bool m_intersected; - mutable boost::function_output_iterator m_iterator_wrapper; - Incident_faces_filter(const TM& tmesh, OutputIterator it) : m_tmesh(tmesh), - m_iterator(it), - m_iterator_wrapper(Output_iterator_with_bool(&m_iterator, &m_intersected)) + m_iterator(it) {} void operator()(const Box* b, const Box* c) const @@ -480,7 +442,7 @@ struct Incident_faces_filter } } } - *m_iterator_wrapper++ = std::make_pair(b->info(), c->info()); + *m_iterator++ = std::make_pair(b->info(), c->info()); } // end operator () }; @@ -513,21 +475,6 @@ template struct Intersect_facets_incident_to_vertex { - // wrapper to check whether anything is inserted to output iterator - struct Output_iterator_with_bool - { - Output_iterator_with_bool(OutputIterator* out, bool* intersected) - : m_iterator(out), m_intersected(intersected) { } - - template - void operator()(const T& t) { - *m_intersected = true; - *(*m_iterator)++ = t; - } - - OutputIterator* m_iterator; - bool* m_intersected; - }; // typedefs typedef typename Kernel::Point_3 Point; typedef typename Kernel::Segment_3 Segment; @@ -540,8 +487,6 @@ struct Intersect_facets_incident_to_vertex const TM& m_tmesh; const VertexPointMap m_vpmap; mutable OutputIterator m_iterator; - mutable bool m_intersected; - mutable boost::function_output_iterator m_iterator_wrapper; typename Kernel::Construct_segment_3 segment_functor; typename Kernel::Construct_triangle_3 triangle_functor; @@ -553,8 +498,6 @@ struct Intersect_facets_incident_to_vertex m_tmesh(tmesh), m_vpmap(vpmap), m_iterator(it), - m_intersected(false), - m_iterator_wrapper(Output_iterator_with_bool(&m_iterator, &m_intersected)), segment_functor(kernel.construct_segment_3_object()), triangle_functor(kernel.construct_triangle_3_object()), do_intersect_3_functor(kernel.do_intersect_3_object()) @@ -584,7 +527,7 @@ struct Intersect_facets_incident_to_vertex vertex_descriptor ov = target(next(ohd,m_tmesh), m_tmesh); Point s = get(m_vpmap, ov); if(CGAL::coplanar(p,q,r,s) && CGAL::coplanar_orientation(r,p,q,s) == POSITIVE){ - *m_iterator_wrapper++ = std::make_pair(face(hd,m_tmesh), face(ohd, m_tmesh)); + *m_iterator++ = std::make_pair(face(hd,m_tmesh), face(ohd, m_tmesh)); } } ohd = opposite(next(hd,m_tmesh), m_tmesh); @@ -592,7 +535,7 @@ struct Intersect_facets_incident_to_vertex vertex_descriptor ov = target(next(ohd,m_tmesh), m_tmesh); Point s = get(m_vpmap, ov); if(CGAL::coplanar(p,q,r,s) && CGAL::coplanar_orientation(p,q,r,s) == POSITIVE){ - *m_iterator_wrapper++ = std::make_pair(face(hd,m_tmesh), face(ohd, m_tmesh)); + *m_iterator++ = std::make_pair(face(hd,m_tmesh), face(ohd, m_tmesh)); } } halfedge_descriptor po = prev(opposite(hd,m_tmesh),m_tmesh); @@ -605,7 +548,7 @@ struct Intersect_facets_incident_to_vertex Segment ss = segment_functor(get(m_vpmap, source(start,m_tmesh)), get(m_vpmap, target(next(start,m_tmesh), m_tmesh))); if(do_intersect_3_functor(th, ss)){ - *m_iterator_wrapper++ = std::make_pair(face(hd,m_tmesh), face(start, m_tmesh)); + *m_iterator++ = std::make_pair(face(hd,m_tmesh), face(start, m_tmesh)); } } hd = prev(opposite(hd,m_tmesh),m_tmesh); From 5ea8d361296966a2d79a23467b571812a16b23c9 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Wed, 13 Nov 2019 09:35:48 +0100 Subject: [PATCH 024/185] Do not use a concurrent_vector --- .../self_intersections_example.cpp | 2 +- .../self_intersections.h | 37 +++++++++---------- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp index 179eeec96ca..25c75967ee3 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp @@ -41,7 +41,7 @@ int main(int argc, char* argv[]) std::vector > intersected_tris; - PMP::self_intersections(mesh, std::back_inserter(intersected_tris)); + PMP::self_intersections(mesh, std::back_inserter(intersected_tris)); std::cout << std::endl << "Total: " << rtimer.time() << " " << timer.time() << " sec." << std::endl; std::cout << intersected_tris.size() << " pairs of triangles intersect." << std::endl; diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index 2bbaa472e22..fc2d33d1738 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -259,12 +259,10 @@ struct TriangleTriangle { // The functor for doing all geometric tests in parallel template struct AllPairs { const TM& m_tmesh; const VertexPointMap m_vpmap; - mutable OutputIterator m_iterator; typename Kernel::Construct_segment_3 segment_functor; typename Kernel::Construct_triangle_3 triangle_functor; typename Kernel::Do_intersect_3 do_intersect_3_functor; @@ -275,15 +273,15 @@ struct AllPairs { typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; const std::vector >& seq_faces; - + std::vector& dointersect; AllPairs(const std::vector >& seq_faces, - OutputIterator it, + std::vector& dointersect, const TM& tmesh, VertexPointMap vpmap, const Kernel& kernel) : seq_faces(seq_faces), + dointersect(dointersect), m_tmesh(tmesh), m_vpmap(vpmap), - m_iterator(it), triangle_functor(kernel.construct_triangle_3_object()), do_intersect_3_functor(kernel.do_intersect_3_object()) {} @@ -291,13 +289,14 @@ struct AllPairs { void operator()(const tbb::blocked_range &r) const { for (std::size_t ri = r.begin(); ri != r.end(); ++ri) { - const std::pair& ff = seq_faces[ri]; - this->operator()(ff); + + this->operator()(ri); } } - void operator()(const std::pair& ff) const + void operator()(std::size_t ri) const { + const std::pair& ff = seq_faces[ri]; halfedge_descriptor h = halfedge(ff.first, m_tmesh), g = halfedge(ff.second, m_tmesh); vertex_descriptor hv[3], gv[3]; @@ -331,7 +330,7 @@ struct AllPairs { get(m_vpmap, hv[(i+1)%3]), get(m_vpmap, target(next(opp_h, m_tmesh), m_tmesh))) == CGAL::POSITIVE){ - *m_iterator++ = ff; + dointersect[ri]=true; return; } else { // there is a shared edge but no intersection return; @@ -374,9 +373,9 @@ struct AllPairs { get(m_vpmap, gv[(j+2)%3])); if(do_intersect_3_functor(t1,s2)){ - *m_iterator ++ = ff; + dointersect[ri] = true; } else if(do_intersect_3_functor(t2,s1)){ - *m_iterator ++ = ff; + dointersect[ri] = true; } return; } @@ -389,7 +388,7 @@ struct AllPairs { get(m_vpmap, gv[1]), get(m_vpmap, gv[2])); if(do_intersect_3_functor(t1, t2)){ - *m_iterator ++ = ff; + dointersect[ri] = true; } } }; @@ -916,14 +915,11 @@ self_intersections( const FaceRange& face_range, // (B) Parallel: perform the geometric tests typedef typename GetGeomTraits::type GeomTraits; - typedef tbb::concurrent_vector > CV; - CV cv_faces; - typedef std::back_insert_iterator CVI; - + std::vector dointersect(face_pairs.size(),0); - CGAL::internal::AllPairs + CGAL::internal::AllPairs all_pairs(face_pairs, - std::back_inserter(cv_faces), // result + dointersect, tmesh, vpmap, parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits), GeomTraits())); @@ -934,8 +930,9 @@ self_intersections( const FaceRange& face_range, tbb::parallel_for(tbb::blocked_range(0, face_pairs.size()), all_pairs); // (C) Sequentially: Copy from the concurent container to the output iterator - for(CV::iterator it = cv_faces.begin(); it != cv_faces.end(); ++it){ - *out ++= *it; + for(int i=0; i < dointersect.size(); ++i){ + if(dointersect[i]) + *out ++= face_pairs[i]; } return out; } From 884b2cf2abe1206c57ec09d5e72084f2ac3febbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 13 Nov 2019 15:41:11 +0100 Subject: [PATCH 025/185] restore removed code --- .../CGAL/Box_intersection_d/segment_tree.h | 43 +++++++++++++++++-- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/Box_intersection_d/include/CGAL/Box_intersection_d/segment_tree.h b/Box_intersection_d/include/CGAL/Box_intersection_d/segment_tree.h index e6a9ca0e05e..5c31223d85a 100644 --- a/Box_intersection_d/include/CGAL/Box_intersection_d/segment_tree.h +++ b/Box_intersection_d/include/CGAL/Box_intersection_d/segment_tree.h @@ -345,10 +345,37 @@ void segment_tree( RandomAccessIter1 p_begin, RandomAccessIter1 p_end, const T inf = box_limits< T >::inf(); const T sup = box_limits< T >::sup(); +#if CGAL_BOX_INTERSECTION_DEBUG + CGAL_STATIC_THREAD_LOCAL_VARIABLE(int, level, -1); + Counter bla( level ); + CGAL_BOX_INTERSECTION_DUMP("range: [" << lo << "," << hi << ") dim " + << dim << std::endl ) + CGAL_BOX_INTERSECTION_DUMP("intervals: " ) + //dump_box_numbers( i_begin, i_end, traits ); + dump_intervals( i_begin, i_end, traits, dim ); + CGAL_BOX_INTERSECTION_DUMP("points: " ) + //dump_box_numbers( p_begin, p_end, traits ); + dump_points( p_begin, p_end, traits, dim ); +#endif + +#if CGAL_SEGMENT_TREE_CHECK_INVARIANTS + { + // first: each point is inside segment [lo,hi) + for( RandomAccessIter1 it = p_begin; it != p_end; ++it ) { + CGAL_assertion( Lo_less( hi, dim )(*it) ); + CGAL_assertion( Lo_less( lo, dim )(*it) == false ); + } + // second: each interval intersects segment [lo,hi) + for( RandomAccessIter2 it = i_begin; it != i_end; ++it ) + CGAL_assertion( Hi_greater(lo,dim)(*it) && Lo_less(hi,dim)(*it)); + } +#endif + if( p_begin == p_end || i_begin == i_end || lo >= hi ) return; if( dim == 0 ) { + CGAL_BOX_INTERSECTION_DUMP( "dim = 0. scanning ... " << std::endl ) one_way_scan( p_begin, p_end, i_begin, i_end, callback, traits, dim, in_order ); return; @@ -357,6 +384,7 @@ void segment_tree( RandomAccessIter1 p_begin, RandomAccessIter1 p_end, if( std::distance( p_begin, p_end ) < cutoff || std::distance( i_begin, i_end ) < cutoff ) { + CGAL_BOX_INTERSECTION_DUMP( "scanning ... " << std::endl ) modified_two_way_scan( p_begin, p_end, i_begin, i_end, callback, traits, dim, in_order ); return; @@ -366,7 +394,8 @@ void segment_tree( RandomAccessIter1 p_begin, RandomAccessIter1 p_end, std::partition( i_begin, i_end, Spanning( lo, hi, dim ) ); if( i_begin != i_span_end ) { - + CGAL_BOX_INTERSECTION_DUMP( "checking spanning intervals ... " + << std::endl ) // make two calls for roots of segment tree at next level. segment_tree( p_begin, p_end, i_begin, i_span_end, inf, sup, callback, traits, cutoff, dim - 1, in_order ); @@ -378,6 +407,10 @@ void segment_tree( RandomAccessIter1 p_begin, RandomAccessIter1 p_end, RandomAccessIter1 p_mid = split_points( p_begin, p_end, traits, dim, mi ); if( p_mid == p_begin || p_mid == p_end ) { + CGAL_BOX_INTERSECTION_DUMP( "unable to split points! ") + //dump_points( p_begin, p_end, traits, dim ); + CGAL_BOX_INTERSECTION_DUMP( "performing modified two_way_san ... " + << std::endl ) modified_two_way_scan( p_begin, p_end, i_span_end, i_end, callback, traits, dim, in_order ); return; @@ -387,17 +420,21 @@ void segment_tree( RandomAccessIter1 p_begin, RandomAccessIter1 p_end, // separate left intervals. // left intervals have a low point strictly less than mi i_mid = std::partition( i_span_end, i_end, Lo_less( mi, dim ) ); - + CGAL_BOX_INTERSECTION_DUMP("->left" << std::endl ) segment_tree( p_begin, p_mid, i_span_end, i_mid, lo, mi, callback, traits, cutoff, dim, in_order ); // separate right intervals. // right intervals have a high point strictly higher than mi i_mid = std::partition( i_span_end, i_end, Hi_greater( mi, dim ) ); - + CGAL_BOX_INTERSECTION_DUMP("->right"<< std::endl ) segment_tree( p_mid, p_end, i_span_end, i_mid, mi, hi, callback, traits, cutoff, dim, in_order ); } +#if CGAL_BOX_INTERSECTION_DEBUG + #undef CGAL_BOX_INTERSECTION_DUMP +#endif +#undef CGAL_BOX_INTERSECTION_DEBUG } // end namespace Box_intersection_d From ceddeb9756be02b3f197ee58b11b6d143bad75b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 13 Nov 2019 15:55:08 +0100 Subject: [PATCH 026/185] hide debug code --- .../self_intersections.h | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index fc2d33d1738..1a888d59fdd 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -25,6 +25,10 @@ #include #include +#ifdef CGAL_PMP_SI_DEBUG +#include +#endif + #include #include @@ -804,18 +808,21 @@ self_intersections( const FaceRange& face_range, std::back_inserter(cv_faces), // result vpmap, parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits), GeomTraits())); - +#ifdef CGAL_PMP_SI_DEBUG Real_timer rt; rt.start(); +#endif tbb::parallel_for(tbb::blocked_range(0, num_vertices(tmesh)), intersect_facets_incident_to_vertex); // Copy from the concurent container to the output iterator - for(CV::iterator it = cv_faces.begin(); it != cv_faces.end(); ++it){ + for(typename CV::iterator it = cv_faces.begin(); it != cv_faces.end(); ++it){ *out ++= *it; } +#ifdef CGAL_PMP_SI_DEBUG std::cout << "(A) Parallel: faces incident to each vertex " << rt.time() << "sec."<< std::endl; rt.reset(); +#endif // (B) Sequential: Look at pairs of triangles with intersecting bbox // Copy the pairs which do not share an edge or a vertex into a std::vector @@ -829,8 +836,10 @@ self_intersections( const FaceRange& face_range, std::ptrdiff_t cutoff = 2000; CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(),incident_faces_filter,cutoff); +#ifdef CGAL_PMP_SI_DEBUG std::cout << "(B) Sequential: boxes that intersect " << rt.time() << "sec."<< std::endl; rt.reset(); +#endif // (C) Parallel: Perform geometric test on pairs not sharing an edge or a vertex std::vector dointersect(seq_v_faces.size()); @@ -849,8 +858,9 @@ self_intersections( const FaceRange& face_range, } } } - +#ifdef CGAL_PMP_SI_DEBUG std::cout << "(C) Parallel: Filter triangles that intersect " << rt.time() << "sec."<< std::endl; +#endif return out; } @@ -924,9 +934,6 @@ self_intersections( const FaceRange& face_range, vpmap, parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits), GeomTraits())); - Real_timer rt; - rt.start(); - tbb::parallel_for(tbb::blocked_range(0, face_pairs.size()), all_pairs); // (C) Sequentially: Copy from the concurent container to the output iterator From e4b205bca664e9757fa65014d58890aba887c084 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 14 Nov 2019 06:31:43 +0100 Subject: [PATCH 027/185] update doc + reorder/factorize code --- .../self_intersections.h | 425 ++++++++---------- 1 file changed, 178 insertions(+), 247 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index 1a888d59fdd..098c17ebfa1 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -66,7 +66,7 @@ namespace internal { class OutputIterator, class VertexPointMap> struct Intersect_facets - { +{ // typedefs typedef typename Kernel::Segment_3 Segment; typedef typename Kernel::Triangle_3 Triangle; @@ -84,7 +84,6 @@ struct Intersect_facets typename Kernel::Construct_triangle_3 triangle_functor; typename Kernel::Do_intersect_3 do_intersect_3_functor; - Intersect_facets(const TM& tmesh, OutputIterator it, VertexPointMap vpmap, const Kernel& kernel) : m_tmesh(tmesh), @@ -93,10 +92,10 @@ struct Intersect_facets segment_functor(kernel.construct_segment_3_object()), triangle_functor(kernel.construct_triangle_3_object()), do_intersect_3_functor(kernel.do_intersect_3_object()) - { } + {} void operator()(const Box* b, const Box* c) const - { + { halfedge_descriptor h = halfedge(b->info(), m_tmesh); halfedge_descriptor g = halfedge(c->info(),m_tmesh); @@ -107,8 +106,8 @@ struct Intersect_facets gv[0] = target(g, m_tmesh); gv[1] = target(next(g, m_tmesh), m_tmesh); - gv[2] = source(g, m_tmesh); - + gv[2] = source(g, m_tmesh); + halfedge_descriptor opp_h; // check for shared egde @@ -153,9 +152,9 @@ struct Intersect_facets break; } } - if (shared) { - break; - } + if (shared) { + break; + } } if(shared){ // found shared vertex: @@ -192,12 +191,11 @@ struct Intersect_facets *m_iterator++ = std::make_pair(b->info(), c->info()); } } // end operator () - }; // end struct Intersect_facets - +}; // end struct Intersect_facets #ifdef CGAL_LINKED_WITH_TBB - // The functor for testing only triangles that do not share an edge or vertex in parallel +// TO BE REMOVED? template @@ -215,7 +213,6 @@ struct TriangleTriangle { std::vector& dointersect; bool& result; - TriangleTriangle(const std::vector >& seq_v_faces, std::vector& dointersect, bool& result, @@ -228,7 +225,7 @@ struct TriangleTriangle { dointersect(dointersect), result(result) {} - + void operator()(const tbb::blocked_range &r) const { for (std::size_t i = r.begin(); i != r.end(); ++i) { @@ -236,15 +233,15 @@ struct TriangleTriangle { halfedge_descriptor h = halfedge(tt.first, m_tmesh); halfedge_descriptor g = halfedge(tt.second ,m_tmesh); - + vertex_descriptor hv[3], gv[3]; hv[0] = target(h, m_tmesh); hv[1] = target(next(h, m_tmesh), m_tmesh); hv[2] = source(h, m_tmesh); - + gv[0] = target(g, m_tmesh); gv[1] = target(next(g, m_tmesh), m_tmesh); - gv[2] = source(g, m_tmesh); + gv[2] = source(g, m_tmesh); Triangle t1 = triangle_functor( get(m_vpmap, hv[0]), get(m_vpmap, hv[1]), get(m_vpmap, hv[2])); @@ -259,37 +256,41 @@ struct TriangleTriangle { } }; - +//TODO: use the same code for the linear pass? // The functor for doing all geometric tests in parallel template -struct AllPairs { - const TM& m_tmesh; - const VertexPointMap m_vpmap; - typename Kernel::Construct_segment_3 segment_functor; - typename Kernel::Construct_triangle_3 triangle_functor; - typename Kernel::Do_intersect_3 do_intersect_3_functor; +struct AllPairs +{ +// types typedef typename Kernel::Segment_3 Segment; typedef typename Kernel::Triangle_3 Triangle; - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; + +// data members + const TM& m_tmesh; + const VertexPointMap m_vpmap; const std::vector >& seq_faces; std::vector& dointersect; - + typename Kernel::Construct_segment_3 segment_functor; + typename Kernel::Construct_triangle_3 triangle_functor; + typename Kernel::Do_intersect_3 do_intersect_3_functor; + + AllPairs(const std::vector >& seq_faces, std::vector& dointersect, const TM& tmesh, VertexPointMap vpmap, const Kernel& kernel) - : seq_faces(seq_faces), - dointersect(dointersect), - m_tmesh(tmesh), - m_vpmap(vpmap), - triangle_functor(kernel.construct_triangle_3_object()), - do_intersect_3_functor(kernel.do_intersect_3_object()) + : m_tmesh(tmesh) + , m_vpmap(vpmap) + , seq_faces(seq_faces) + , dointersect(dointersect) + , triangle_functor(kernel.construct_triangle_3_object()) + , do_intersect_3_functor(kernel.do_intersect_3_object()) {} - + void operator()(const tbb::blocked_range &r) const { for (std::size_t ri = r.begin(); ri != r.end(); ++ri) { @@ -302,7 +303,7 @@ struct AllPairs { { const std::pair& ff = seq_faces[ri]; halfedge_descriptor h = halfedge(ff.first, m_tmesh), g = halfedge(ff.second, m_tmesh); - + vertex_descriptor hv[3], gv[3]; hv[0] = target(h, m_tmesh); hv[1] = target(next(h, m_tmesh), m_tmesh); @@ -310,8 +311,8 @@ struct AllPairs { gv[0] = target(g, m_tmesh); gv[1] = target(next(g, m_tmesh), m_tmesh); - gv[2] = source(g, m_tmesh); - + gv[2] = source(g, m_tmesh); + halfedge_descriptor opp_h; // check for shared egde @@ -397,7 +398,6 @@ struct AllPairs { } }; - // The functor for filtering pairs of faces that share an edge or vertex template info(), c->info()); - + } // end operator () }; -// The functor that filters nothing +// The functor that filters nothing template struct All_faces_filter { @@ -465,7 +465,7 @@ struct All_faces_filter void operator()(const Box* b, const Box* c) const { *m_iterator ++ = std::make_pair(b->info(), c->info()); - + } // end operator () }; @@ -510,7 +510,7 @@ struct Intersect_facets_incident_to_vertex { for (std::size_t i = r.begin(); i != r.end(); ++i) { vertex_descriptor vd(i); - + halfedge_descriptor hd = halfedge(vd, m_tmesh), done(hd); if(is_border(hd, m_tmesh)){ hd = prev(opposite(hd,m_tmesh),m_tmesh); @@ -521,9 +521,8 @@ struct Intersect_facets_incident_to_vertex Point q = get(m_vpmap, target(next(hd,m_tmesh), m_tmesh)); Point r = get(m_vpmap, source(hd,m_tmesh)); - - Triangle th = triangle_functor(p, q, r); - + Triangle th = triangle_functor(p, q, r); + // first look at the directly shared edges halfedge_descriptor ohd = opposite(hd, m_tmesh); if((! is_border(ohd,m_tmesh)) && (hd < ohd)){ @@ -558,10 +557,9 @@ struct Intersect_facets_incident_to_vertex }while(hd != done); } } - }; // end struct Intersect_facets_incident_to_vertex #endif - + struct Throw_at_output { class Throw_at_output_exception: public std::exception { }; @@ -574,97 +572,20 @@ struct Throw_at_output { }// namespace internal - - namespace Polygon_mesh_processing { -#ifndef DOXYGEN_RUNNING -template -OutputIterator -self_intersections( const FaceRange& face_range, - const TriangleMesh& tmesh, - OutputIterator out, - const NamedParameters& np, - ConcurrencyTag); -#endif - - -/** - * \ingroup PMP_intersection_grp - * detects and records self-intersections of a triangulated surface mesh. - * This function depends on the package \ref PkgBoxIntersectionD - * @pre `CGAL::is_triangle_mesh(tmesh)` - * - * @tparam TriangleMesh a model of `FaceListGraph` - * @tparam OutputIterator a model of `OutputIterator` holding objects of type - * `std::pair::%face_descriptor, boost::graph_traits::%face_descriptor>` - * @tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" - * - * @param tmesh the triangulated surface mesh to be checked - * @param out output iterator to be filled with all pairs of non-adjacent faces that intersect. - In case `tmesh` contains some degenerate faces, for each degenerate face `f` a pair `(f,f)` - will be put in `out` before any other self intersection between non-degenerate faces. - These are the only pairs where degenerate faces will be reported. - * @param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below - * - * \cgalNamedParamsBegin - * \cgalParamBegin{vertex_point_map} the property map with the points associated to the vertices of `pmesh`. - * If this parameter is omitted, an internal property map for - * `CGAL::vertex_point_t` must be available in `TriangleMesh`\cgalParamEnd - * \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `PMPSelfIntersectionTraits` \cgalParamEnd - * \cgalNamedParamsEnd - * - * @return `out` - */ - -template < class ConcurrencyTag = Sequential_tag - , class TriangleMesh - , class OutputIterator -#ifdef DOXYGEN_RUNNING - , class NamedParameters> -#else //avoid ambiguity with self_intersections(faces, tmesh, out) - , class P, class T, class R> -#endif - - -OutputIterator -self_intersections(const TriangleMesh& tmesh - , OutputIterator out -#ifdef DOXYGEN_RUNNING - , const NamedParameters& np -#else - , const Named_function_parameters& np -#endif - ) - -{ - return self_intersections(faces(tmesh), tmesh, out, np, ConcurrencyTag()); -} - -/// \cond SKIP_IN_MANUAL -template -OutputIterator -self_intersections(const TriangleMesh& tmesh, OutputIterator out) -{ - return self_intersections(faces(tmesh), tmesh, out, - CGAL::Polygon_mesh_processing::parameters::all_default(), ConcurrencyTag()); -} - - -/// \endcond - /*! * \ingroup PMP_intersection_grp - * Same as above but the self-intersections reported - * are only limited to the faces in `face_range`. + * collects intersections between a subset of faces of a triangulated surface mesh. + * Two faces are said to intersect if the corresponding triangles intersect + * and the intersection is not an edge nor a vertex incident to both faces. + * + * This function depends on the package \ref PkgBoxIntersectionD * * @pre `CGAL::is_triangle_mesh(tmesh)` * + * @tparam ConcurrencyTag enables sequential versus parallel algorithm. + * Possible values are `Sequential_tag` and `Parallel_tag`. * @tparam FaceRange range of `boost::graph_traits::%face_descriptor`, * model of `Range`. * Its iterator type is `RandomAccessIterator`. @@ -684,19 +605,17 @@ self_intersections(const TriangleMesh& tmesh, OutputIterator out) * `CGAL::vertex_point_t` must be available in `TriangleMesh`\cgalParamEnd * \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `PMPSelfIntersectionTraits` \cgalParamEnd * \cgalNamedParamsEnd - */ -template +template < class ConcurrencyTag = Sequential_tag, + class TriangleMesh, + class FaceRange, + class OutputIterator, + class NamedParameters> OutputIterator self_intersections( const FaceRange& face_range, const TriangleMesh& tmesh, - OutputIterator out, - const NamedParameters& np, - Sequential_tag) + OutputIterator out, + const NamedParameters& np) { CGAL_precondition(CGAL::is_triangle_mesh(tmesh)); @@ -704,7 +623,7 @@ self_intersections( const FaceRange& face_range, typedef typename boost::graph_traits::face_descriptor face_descriptor; typedef typename CGAL::Box_intersection_d::Box_with_info_d Box; - // make one box per facet + // make one box per face std::vector boxes; boxes.reserve( std::distance( boost::begin(face_range), boost::end(face_range) ) @@ -733,7 +652,45 @@ self_intersections( const FaceRange& face_range, for(Box& b : boxes) box_ptr.push_back(&b); - // compute self-intersections filtered out by boxes +#if !defined(CGAL_LINKED_WITH_TBB) + CGAL_static_assertion_msg (!(boost::is_convertible::value), + "Parallel_tag is enabled but TBB is unavailable."); +#else + if (boost::is_convertible::value) + { + // (Parallel version of the code) + // (A) Sequentially write all pairs of faces with intersecting bbox into a std::vector + std::ptrdiff_t cutoff = 2000; + typedef std::vector >SeqV; + typedef std::back_insert_iterator SeqVI; + SeqV face_pairs; + internal::All_faces_filter all_faces_filter(std::back_inserter(face_pairs)); + CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(),all_faces_filter,cutoff); + + // (B) Parallel: perform the geometric tests + typedef typename GetGeomTraits::type GeomTraits; + + std::vector dointersect(face_pairs.size(),0); + + CGAL::internal::AllPairs + all_pairs(face_pairs, + dointersect, + tmesh, + vpmap, + parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits), GeomTraits())); + + tbb::parallel_for(tbb::blocked_range(0, face_pairs.size()), all_pairs); + + // (C) Sequentially: Copy from the concurent container to the output iterator + for(int i=0; i < dointersect.size(); ++i){ + if(dointersect[i]) + *out ++= face_pairs[i]; + } + return out; + } +#endif + + // (Sequential version of the code) compute self-intersections filtered out by boxes typedef typename GetGeomTraits::type GeomTraits; CGAL::internal::Intersect_facets intersect_facets(tmesh, out, vpmap, @@ -744,8 +701,80 @@ self_intersections( const FaceRange& face_range, return intersect_facets.m_iterator; } -#ifdef CGAL_LINKED_WITH_TBB - +/// \cond SKIP_IN_MANUAL +template +OutputIterator +self_intersections(const FaceRange& face_range, + const TriangleMesh& tmesh, + OutputIterator out) +{ + return self_intersections(face_range, tmesh, out, + CGAL::Polygon_mesh_processing::parameters::all_default(), + ConcurrencyTag()); +} +/// \endcond + + +/** + * \ingroup PMP_intersection_grp + * collects intersections between all the faces of a triangulated surface mesh. + * Two faces are said to intersect if the corresponding triangles intersect + * and the intersection is not an edge nor a vertex incident to both faces. + * + * This function depends on the package \ref PkgBoxIntersectionD + * + * @pre `CGAL::is_triangle_mesh(tmesh)` + * + * @tparam ConcurrencyTag enables sequential versus parallel algorithm. + * Possible values are `Sequential_tag` and `Parallel_tag`. + * @tparam TriangleMesh a model of `FaceListGraph` + * @tparam OutputIterator a model of `OutputIterator` holding objects of type + * `std::pair::%face_descriptor, boost::graph_traits::%face_descriptor>` + * @tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" + * + * @param tmesh the triangulated surface mesh to be checked + * @param out output iterator to be filled with all pairs of non-adjacent faces that intersect. + In case `tmesh` contains some degenerate faces, for each degenerate face `f` a pair `(f,f)` + will be put in `out` before any other self intersection between non-degenerate faces. + These are the only pairs where degenerate faces will be reported. + * @param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below + * + * \cgalNamedParamsBegin + * \cgalParamBegin{vertex_point_map} the property map with the points associated to the vertices of `pmesh`. + * If this parameter is omitted, an internal property map for + * `CGAL::vertex_point_t` must be available in `TriangleMesh`\cgalParamEnd + * \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `PMPSelfIntersectionTraits` \cgalParamEnd + * \cgalNamedParamsEnd + * + * @return `out` + */ +template < class ConcurrencyTag = Sequential_tag + , class TriangleMesh + , class OutputIterator + , class CGAL_PMP_NP_TEMPLATE_PARAMETERS> +OutputIterator +self_intersections(const TriangleMesh& tmesh, + OutputIterator out, + const CGAL_PMP_NP_CLASS& np) +{ + return self_intersections(faces(tmesh), tmesh, out, np, ConcurrencyTag()); +} + +/// \cond SKIP_IN_MANUAL +template +OutputIterator +self_intersections(const TriangleMesh& tmesh, OutputIterator out) +{ + return self_intersections(faces(tmesh), tmesh, out, parameters::all_default()); +} +/// \endcond + +// experimental code for parallel processing on vertices +// (slower than general parallel on boxes). To be removed. +#if 0 template ::face_descriptor face_descriptor; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename CGAL::Box_intersection_d::Box_with_info_d Box; // make one box per facet @@ -812,7 +840,7 @@ self_intersections( const FaceRange& face_range, Real_timer rt; rt.start(); #endif - + tbb::parallel_for(tbb::blocked_range(0, num_vertices(tmesh)), intersect_facets_incident_to_vertex); // Copy from the concurent container to the output iterator @@ -823,13 +851,13 @@ self_intersections( const FaceRange& face_range, std::cout << "(A) Parallel: faces incident to each vertex " << rt.time() << "sec."<< std::endl; rt.reset(); #endif - + // (B) Sequential: Look at pairs of triangles with intersecting bbox // Copy the pairs which do not share an edge or a vertex into a std::vector typedef std::vector >SeqV; SeqV seq_v_faces; typedef std::back_insert_iterator SeqVI; - + CGAL::internal::Incident_faces_filter incident_faces_filter(tmesh, std::back_inserter(seq_v_faces)); @@ -840,7 +868,7 @@ self_intersections( const FaceRange& face_range, std::cout << "(B) Sequential: boxes that intersect " << rt.time() << "sec."<< std::endl; rt.reset(); #endif - + // (C) Parallel: Perform geometric test on pairs not sharing an edge or a vertex std::vector dointersect(seq_v_faces.size()); bool result(false); @@ -863,104 +891,7 @@ self_intersections( const FaceRange& face_range, #endif return out; } - - -template -OutputIterator -self_intersections( const FaceRange& face_range, - const TriangleMesh& tmesh, - OutputIterator out, - const NamedParameters& np, - Parallel_tag) -{ - CGAL_precondition(CGAL::is_triangle_mesh(tmesh)); - - typedef TriangleMesh TM; - typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename CGAL::Box_intersection_d::Box_with_info_d Box; - - // make one box per facet - std::vector boxes; - boxes.reserve( - std::distance( boost::begin(face_range), boost::end(face_range) ) - ); - - typedef typename GetVertexPointMap::const_type VertexPointMap; - VertexPointMap vpmap = parameters::choose_parameter(parameters::get_parameter(np, internal_np::vertex_point), - get_const_property_map(boost::vertex_point, tmesh)); - - for(face_descriptor f : face_range) - { - typename boost::property_traits::reference - p = get(vpmap, target(halfedge(f,tmesh),tmesh)), - q = get(vpmap, target(next(halfedge(f, tmesh), tmesh), tmesh)), - r = get(vpmap, target(next(next(halfedge(f, tmesh), tmesh), tmesh), tmesh)); - - if ( collinear(p, q, r) ) - *out++= std::make_pair(f,f); - else - boxes.push_back(Box(p.bbox() + q.bbox() + r.bbox(), f)); - } - // generate box pointers - std::vector box_ptr; - box_ptr.reserve(boxes.size()); - - for(Box& b : boxes) - box_ptr.push_back(&b); - - // (A) Sequentially write all pairs of faces with intersecting bbox into a std::vector - std::ptrdiff_t cutoff = 2000; - typedef std::vector >SeqV; - typedef std::back_insert_iterator SeqVI; - SeqV face_pairs; - internal::All_faces_filter all_faces_filter(std::back_inserter(face_pairs)); - CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(),all_faces_filter,cutoff); - - - // (B) Parallel: perform the geometric tests - typedef typename GetGeomTraits::type GeomTraits; - - std::vector dointersect(face_pairs.size(),0); - - CGAL::internal::AllPairs - all_pairs(face_pairs, - dointersect, - tmesh, - vpmap, - parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits), GeomTraits())); - - tbb::parallel_for(tbb::blocked_range(0, face_pairs.size()), all_pairs); - - // (C) Sequentially: Copy from the concurent container to the output iterator - for(int i=0; i < dointersect.size(); ++i){ - if(dointersect[i]) - *out ++= face_pairs[i]; - } - return out; -} #endif // CGAL_LINKED_WITH_TBB - - -/// \cond SKIP_IN_MANUAL -template -OutputIterator self_intersections(const FaceRange& face_range, - const TriangleMesh& tmesh, - OutputIterator out) -{ - return self_intersections(face_range, tmesh, out, - CGAL::Polygon_mesh_processing::parameters::all_default(), - ConcurrencyTag()); -} -/// \endcond /** * \ingroup PMP_intersection_grp From 45cd4dc8bff29aa50fd4b0ae87175357d5ae741f Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 14 Nov 2019 11:21:40 +0100 Subject: [PATCH 028/185] remove parameter; Add ConcurrencyTag to does_self_intersect --- .../self_intersections.h | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index 098c17ebfa1..c036990cc08 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -751,7 +751,7 @@ self_intersections(const FaceRange& face_range, * * @return `out` */ -template < class ConcurrencyTag = Sequential_tag +template @@ -760,7 +760,7 @@ self_intersections(const TriangleMesh& tmesh, OutputIterator out, const CGAL_PMP_NP_CLASS& np) { - return self_intersections(faces(tmesh), tmesh, out, np, ConcurrencyTag()); + return self_intersections(faces(tmesh), tmesh, out, np); } /// \cond SKIP_IN_MANUAL @@ -899,6 +899,8 @@ self_intersections( const FaceRange& face_range, * This function depends on the package \ref PkgBoxIntersectionD * @pre `CGAL::is_triangle_mesh(tmesh)` * + * @tparam ConcurrencyTag enables sequential versus parallel algorithm. + * Possible values are `Sequential_tag` and `Parallel_tag`. * @tparam TriangleMesh a model of `FaceListGraph` * @tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" * @@ -914,7 +916,8 @@ self_intersections( const FaceRange& face_range, * * @return `true` if `tmesh` self-intersects */ -template bool does_self_intersect(const TriangleMesh& tmesh @@ -925,7 +928,7 @@ bool does_self_intersect(const TriangleMesh& tmesh try { typedef boost::function_output_iterator OutputIterator; - self_intersections(tmesh, OutputIterator(), np); + self_intersections(tmesh, OutputIterator(), np); } catch( CGAL::internal::Throw_at_output::Throw_at_output_exception& ) { return true; } @@ -956,7 +959,8 @@ bool does_self_intersect(const TriangleMesh& tmesh * * @return `true` if the faces in `face_range` self-intersect */ -template @@ -969,7 +973,7 @@ bool does_self_intersect(const FaceRange& face_range, try { typedef boost::function_output_iterator OutputIterator; - self_intersections(face_range, tmesh, OutputIterator(), np); + self_intersections(face_range, tmesh, OutputIterator(), np); } catch( CGAL::internal::Throw_at_output::Throw_at_output_exception& ) { return true; } @@ -978,18 +982,18 @@ bool does_self_intersect(const FaceRange& face_range, } /// \cond SKIP_IN_MANUAL -template +template bool does_self_intersect(const TriangleMesh& tmesh) { - return does_self_intersect(tmesh, + return does_self_intersect(tmesh, CGAL::Polygon_mesh_processing::parameters::all_default()); } -template +template bool does_self_intersect(const FaceRange& face_range, const TriangleMesh& tmesh) { - return does_self_intersect(face_range, tmesh, + return does_self_intersect(face_range, tmesh, CGAL::Polygon_mesh_processing::parameters::all_default()); } From 899b9ec3843df08c40b4f160c1676fe252a40074 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 14 Nov 2019 11:31:50 +0100 Subject: [PATCH 029/185] Remove experimental code --- .../self_intersections.h | 321 +----------------- 1 file changed, 1 insertion(+), 320 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index c036990cc08..12fb916727e 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -193,69 +193,8 @@ struct Intersect_facets } // end operator () }; // end struct Intersect_facets + #ifdef CGAL_LINKED_WITH_TBB -// The functor for testing only triangles that do not share an edge or vertex in parallel -// TO BE REMOVED? -template -struct TriangleTriangle { - const TM& m_tmesh; - const VertexPointMap m_vpmap; - typename Kernel::Construct_triangle_3 triangle_functor; - typename Kernel::Do_intersect_3 do_intersect_3_functor; - typedef typename Kernel::Triangle_3 Triangle; - - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::face_descriptor face_descriptor; - const std::vector >& seq_v_faces; - std::vector& dointersect; - bool& result; - - TriangleTriangle(const std::vector >& seq_v_faces, - std::vector& dointersect, - bool& result, - const TM& tmesh, VertexPointMap vpmap, const Kernel& kernel) - : seq_v_faces(seq_v_faces), - m_tmesh(tmesh), - m_vpmap(vpmap), - triangle_functor(kernel.construct_triangle_3_object()), - do_intersect_3_functor(kernel.do_intersect_3_object()), - dointersect(dointersect), - result(result) - {} - - void operator()(const tbb::blocked_range &r) const - { - for (std::size_t i = r.begin(); i != r.end(); ++i) { - const std::pair& tt = seq_v_faces[i]; - - halfedge_descriptor h = halfedge(tt.first, m_tmesh); - halfedge_descriptor g = halfedge(tt.second ,m_tmesh); - - vertex_descriptor hv[3], gv[3]; - hv[0] = target(h, m_tmesh); - hv[1] = target(next(h, m_tmesh), m_tmesh); - hv[2] = source(h, m_tmesh); - - gv[0] = target(g, m_tmesh); - gv[1] = target(next(g, m_tmesh), m_tmesh); - gv[2] = source(g, m_tmesh); - Triangle t1 = triangle_functor( get(m_vpmap, hv[0]), - get(m_vpmap, hv[1]), - get(m_vpmap, hv[2])); - Triangle t2 = triangle_functor( get(m_vpmap, gv[0]), - get(m_vpmap, gv[1]), - get(m_vpmap, gv[2])); - if(do_intersect_3_functor(t1, t2)){ - dointersect[i] = true; - result = true; - } - } - } -}; - //TODO: use the same code for the linear pass? // The functor for doing all geometric tests in parallel template -struct Incident_faces_filter -{ -// typedefs - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - -// members - const TM& m_tmesh; - mutable OutputIterator m_iterator; - - Incident_faces_filter(const TM& tmesh, OutputIterator it) - : m_tmesh(tmesh), - m_iterator(it) - {} - - void operator()(const Box* b, const Box* c) const - { - halfedge_descriptor h = halfedge(b->info(), m_tmesh); - halfedge_descriptor g = halfedge(c->info(),m_tmesh); - - vertex_descriptor hv[3], gv[3]; - hv[0] = target(h, m_tmesh); - hv[1] = target(next(h, m_tmesh), m_tmesh); - hv[2] = source(h, m_tmesh); - - gv[0] = target(g, m_tmesh); - gv[1] = target(next(g, m_tmesh), m_tmesh); - gv[2] = source(g, m_tmesh); - - halfedge_descriptor opp_h; - - // ignore shared vertex as already dealt with - - halfedge_descriptor v; - - int i(0),j(0); - for(; i < 3; ++i){ - for(j = 0; j < 3; ++j){ - if(hv[i]==gv[j]){ - return; - } - } - } - *m_iterator++ = std::make_pair(b->info(), c->info()); - - } // end operator () -}; // The functor that filters nothing template @@ -470,94 +358,6 @@ struct All_faces_filter }; -// The functor that computes intersections for faces incident to a vertex -template -struct Intersect_facets_incident_to_vertex -{ -// typedefs - typedef typename Kernel::Point_3 Point; - typedef typename Kernel::Segment_3 Segment; - typedef typename Kernel::Triangle_3 Triangle; - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::property_map::const_type Ppmap; - -// members - const TM& m_tmesh; - const VertexPointMap m_vpmap; - mutable OutputIterator m_iterator; - - typename Kernel::Construct_segment_3 segment_functor; - typename Kernel::Construct_triangle_3 triangle_functor; - typename Kernel::Do_intersect_3 do_intersect_3_functor; - - - Intersect_facets_incident_to_vertex(const TM& tmesh, OutputIterator it, VertexPointMap vpmap, const Kernel& kernel) - : - m_tmesh(tmesh), - m_vpmap(vpmap), - m_iterator(it), - segment_functor(kernel.construct_segment_3_object()), - triangle_functor(kernel.construct_triangle_3_object()), - do_intersect_3_functor(kernel.do_intersect_3_object()) - { } - - void operator()(const tbb::blocked_range &r) const - { - for (std::size_t i = r.begin(); i != r.end(); ++i) { - vertex_descriptor vd(i); - - halfedge_descriptor hd = halfedge(vd, m_tmesh), done(hd); - if(is_border(hd, m_tmesh)){ - hd = prev(opposite(hd,m_tmesh),m_tmesh); - } - - do { //for each hd with vd as target look at all other faces - Point p = get(m_vpmap, vd); - Point q = get(m_vpmap, target(next(hd,m_tmesh), m_tmesh)); - Point r = get(m_vpmap, source(hd,m_tmesh)); - - Triangle th = triangle_functor(p, q, r); - - // first look at the directly shared edges - halfedge_descriptor ohd = opposite(hd, m_tmesh); - if((! is_border(ohd,m_tmesh)) && (hd < ohd)){ - vertex_descriptor ov = target(next(ohd,m_tmesh), m_tmesh); - Point s = get(m_vpmap, ov); - if(CGAL::coplanar(p,q,r,s) && CGAL::coplanar_orientation(r,p,q,s) == POSITIVE){ - *m_iterator++ = std::make_pair(face(hd,m_tmesh), face(ohd, m_tmesh)); - } - } - ohd = opposite(next(hd,m_tmesh), m_tmesh); - if((! is_border(ohd,m_tmesh)) && (hd < ohd)){ - vertex_descriptor ov = target(next(ohd,m_tmesh), m_tmesh); - Point s = get(m_vpmap, ov); - if(CGAL::coplanar(p,q,r,s) && CGAL::coplanar_orientation(p,q,r,s) == POSITIVE){ - *m_iterator++ = std::make_pair(face(hd,m_tmesh), face(ohd, m_tmesh)); - } - } - halfedge_descriptor po = prev(opposite(hd,m_tmesh),m_tmesh); - halfedge_descriptor op = opposite(next(hd,m_tmesh),m_tmesh); - - for(halfedge_descriptor start : halfedges_around_target(hd,m_tmesh)){ - if((start == hd) || (start == op) || (start == po) || is_border(start, m_tmesh) || (face(hd, m_tmesh) < face(start, m_tmesh))){ - continue; - } - Segment ss = segment_functor(get(m_vpmap, source(start,m_tmesh)), - get(m_vpmap, target(next(start,m_tmesh), m_tmesh))); - if(do_intersect_3_functor(th, ss)){ - *m_iterator++ = std::make_pair(face(hd,m_tmesh), face(start, m_tmesh)); - } - } - hd = prev(opposite(hd,m_tmesh),m_tmesh); - }while(hd != done); - } - } -}; // end struct Intersect_facets_incident_to_vertex #endif struct Throw_at_output { @@ -772,126 +572,7 @@ self_intersections(const TriangleMesh& tmesh, OutputIterator out) } /// \endcond -// experimental code for parallel processing on vertices -// (slower than general parallel on boxes). To be removed. -#if 0 -template -OutputIterator -self_intersections( const FaceRange& face_range, - const TriangleMesh& tmesh, - OutputIterator out, - const NamedParameters& np, - int) -{ - CGAL_precondition(CGAL::is_triangle_mesh(tmesh)); - typedef TriangleMesh TM; - typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename CGAL::Box_intersection_d::Box_with_info_d Box; - - // make one box per facet - std::vector boxes; - boxes.reserve( - std::distance( boost::begin(face_range), boost::end(face_range) ) - ); - - typedef typename GetVertexPointMap::const_type VertexPointMap; - VertexPointMap vpmap = parameters::choose_parameter(parameters::get_parameter(np, internal_np::vertex_point), - get_const_property_map(boost::vertex_point, tmesh)); - - for(face_descriptor f : face_range) - { - typename boost::property_traits::reference - p = get(vpmap, target(halfedge(f,tmesh),tmesh)), - q = get(vpmap, target(next(halfedge(f, tmesh), tmesh), tmesh)), - r = get(vpmap, target(next(next(halfedge(f, tmesh), tmesh), tmesh), tmesh)); - - if ( collinear(p, q, r) ) - *out++= std::make_pair(f,f); - else - boxes.push_back(Box(p.bbox() + q.bbox() + r.bbox(), f)); - } - // generate box pointers - std::vector box_ptr; - box_ptr.reserve(boxes.size()); - - for(Box& b : boxes) - box_ptr.push_back(&b); - - - // (A) Parallel: look at each vertex and its incident faces - // Intersections are written into a concurrent vector - typedef typename GetGeomTraits::type GeomTraits; - - typedef tbb::concurrent_vector > CV; - CV cv_faces; - typedef std::back_insert_iterator CVI; - - CGAL::internal::Intersect_facets_incident_to_vertex - intersect_facets_incident_to_vertex(tmesh, - std::back_inserter(cv_faces), // result - vpmap, - parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits), GeomTraits())); -#ifdef CGAL_PMP_SI_DEBUG - Real_timer rt; - rt.start(); -#endif - - tbb::parallel_for(tbb::blocked_range(0, num_vertices(tmesh)), intersect_facets_incident_to_vertex); - - // Copy from the concurent container to the output iterator - for(typename CV::iterator it = cv_faces.begin(); it != cv_faces.end(); ++it){ - *out ++= *it; - } -#ifdef CGAL_PMP_SI_DEBUG - std::cout << "(A) Parallel: faces incident to each vertex " << rt.time() << "sec."<< std::endl; - rt.reset(); -#endif - - // (B) Sequential: Look at pairs of triangles with intersecting bbox - // Copy the pairs which do not share an edge or a vertex into a std::vector - typedef std::vector >SeqV; - SeqV seq_v_faces; - typedef std::back_insert_iterator SeqVI; - - CGAL::internal::Incident_faces_filter - incident_faces_filter(tmesh, - std::back_inserter(seq_v_faces)); - - std::ptrdiff_t cutoff = 2000; - CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(),incident_faces_filter,cutoff); -#ifdef CGAL_PMP_SI_DEBUG - std::cout << "(B) Sequential: boxes that intersect " << rt.time() << "sec."<< std::endl; - rt.reset(); -#endif - - // (C) Parallel: Perform geometric test on pairs not sharing an edge or a vertex - std::vector dointersect(seq_v_faces.size()); - bool result(false); - CGAL::internal::TriangleTriangle tt(seq_v_faces, - dointersect, - result, - tmesh, - vpmap, - parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits), GeomTraits())); - tbb::parallel_for(tbb::blocked_range(0, seq_v_faces.size()), tt); - if(result){ - for(int i = 0; i < seq_v_faces.size(); ++i){ - if(dointersect[i]){ - *out ++= seq_v_faces[i]; - } - } - } -#ifdef CGAL_PMP_SI_DEBUG - std::cout << "(C) Parallel: Filter triangles that intersect " << rt.time() << "sec."<< std::endl; -#endif - return out; -} -#endif // CGAL_LINKED_WITH_TBB /** * \ingroup PMP_intersection_grp From f033e0a2447f4b493e2607ee0b4cf5cdc340e634 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 14 Nov 2019 11:45:37 +0100 Subject: [PATCH 030/185] Cleanup --- .../self_intersections_example.cpp | 18 +++-------- .../self_intersections.h | 32 +++++++------------ 2 files changed, 16 insertions(+), 34 deletions(-) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp index 25c75967ee3..011e642891e 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp @@ -1,11 +1,7 @@ -struct Parallel_tag_bis {}; - #include #include #include -#include -#include #include @@ -26,23 +22,17 @@ int main(int argc, char* argv[]) std::cerr << "Not a valid input file." << std::endl; return 1; } - /* - bool intersecting = PMP::does_self_intersect(mesh, + + bool intersecting = PMP::does_self_intersect(mesh, PMP::parameters::vertex_point_map(get(CGAL::vertex_point, mesh))); std::cout << (intersecting ? "There are self-intersections." : "There is no self-intersection.") << std::endl; - */ - CGAL::Real_timer rtimer; - CGAL::Timer timer; - rtimer.start(); - timer.start(); - std::vector > intersected_tris; - PMP::self_intersections(mesh, std::back_inserter(intersected_tris)); - std::cout << std::endl << "Total: " << rtimer.time() << " " << timer.time() << " sec." << std::endl; + PMP::self_intersections(faces(mesh),mesh, std::back_inserter(intersected_tris)); + std::cout << intersected_tris.size() << " pairs of triangles intersect." << std::endl; return 0; diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index 12fb916727e..9eb4ee03988 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -212,19 +212,19 @@ struct AllPairs // data members const TM& m_tmesh; const VertexPointMap m_vpmap; - const std::vector >& seq_faces; + const std::vector >& face_pairs; std::vector& dointersect; typename Kernel::Construct_segment_3 segment_functor; typename Kernel::Construct_triangle_3 triangle_functor; typename Kernel::Do_intersect_3 do_intersect_3_functor; - AllPairs(const std::vector >& seq_faces, + AllPairs(const std::vector >& face_pairs, std::vector& dointersect, const TM& tmesh, VertexPointMap vpmap, const Kernel& kernel) : m_tmesh(tmesh) , m_vpmap(vpmap) - , seq_faces(seq_faces) + , face_pairs(face_pairs) , dointersect(dointersect) , triangle_functor(kernel.construct_triangle_3_object()) , do_intersect_3_functor(kernel.do_intersect_3_object()) @@ -240,7 +240,7 @@ struct AllPairs void operator()(std::size_t ri) const { - const std::pair& ff = seq_faces[ri]; + const std::pair& ff = face_pairs[ri]; halfedge_descriptor h = halfedge(ff.first, m_tmesh), g = halfedge(ff.second, m_tmesh); vertex_descriptor hv[3], gv[3]; @@ -296,9 +296,9 @@ struct AllPairs break; } } - if (shared) { - break; - } + if (shared) { + break; + } } if(shared){ // found shared vertex: @@ -316,11 +316,7 @@ struct AllPairs Segment s2 = segment_functor( get(m_vpmap, gv[(j+1)%3]), get(m_vpmap, gv[(j+2)%3])); - if(do_intersect_3_functor(t1,s2)){ - dointersect[ri] = true; - } else if(do_intersect_3_functor(t2,s1)){ - dointersect[ri] = true; - } + dointersect[ri] = (do_intersect_3_functor(t1, s2)) || do_intersect_3_functor(t2, s1); return; } @@ -331,9 +327,7 @@ struct AllPairs Triangle t2 = triangle_functor( get(m_vpmap, gv[0]), get(m_vpmap, gv[1]), get(m_vpmap, gv[2])); - if(do_intersect_3_functor(t1, t2)){ - dointersect[ri] = true; - } + dointersect[ri] = do_intersect_3_functor(t1, t2); } }; @@ -425,8 +419,7 @@ self_intersections( const FaceRange& face_range, // make one box per face std::vector boxes; - boxes.reserve( - std::distance( boost::begin(face_range), boost::end(face_range) ) + boxes.reserve( std::distance( boost::begin(face_range), boost::end(face_range) ) ); typedef typename GetVertexPointMap::const_type VertexPointMap; @@ -511,9 +504,8 @@ self_intersections(const FaceRange& face_range, const TriangleMesh& tmesh, OutputIterator out) { - return self_intersections(face_range, tmesh, out, - CGAL::Polygon_mesh_processing::parameters::all_default(), - ConcurrencyTag()); + return self_intersections(face_range, tmesh, out, + CGAL::Polygon_mesh_processing::parameters::all_default()); } /// \endcond From 9c9284fbb4133b928d7c3bedf71ebea2b403e6ea Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 14 Nov 2019 12:17:46 +0100 Subject: [PATCH 031/185] make typedef public --- .../include/CGAL/internal/Static_filters/Static_filters.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Filtered_kernel/include/CGAL/internal/Static_filters/Static_filters.h b/Filtered_kernel/include/CGAL/internal/Static_filters/Static_filters.h index 95216db79f9..6fd346434fb 100644 --- a/Filtered_kernel/include/CGAL/internal/Static_filters/Static_filters.h +++ b/Filtered_kernel/include/CGAL/internal/Static_filters/Static_filters.h @@ -98,8 +98,8 @@ class Static_filters : public K_base { typedef Static_filters Self; - typedef Static_filters_predicates::Coplanar_3 Coplanar_3; public: + typedef Static_filters_predicates::Coplanar_3 Coplanar_3; #ifndef CGAL_NO_EQUAL_3_STATIC_FILTERS typedef Static_filters_predicates::Equal_2 Equal_2; typedef Static_filters_predicates::Equal_3 Equal_3; From 3caad9bc88ed30652b99364dfede876a52c0289e Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 14 Nov 2019 13:26:47 +0100 Subject: [PATCH 032/185] Remove #include --- .../include/CGAL/Polygon_mesh_processing/self_intersections.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index 9eb4ee03988..325f7c028be 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -48,7 +48,6 @@ #ifdef CGAL_LINKED_WITH_TBB #include #include -#include #endif #ifdef DOXYGEN_RUNNING From ff960adea0290cf8845faaf21b01e0873ec7b16c Mon Sep 17 00:00:00 2001 From: Mael Date: Thu, 14 Nov 2019 17:08:58 +0100 Subject: [PATCH 033/185] Fix namespace lookup issue (and a warning) --- .../include/CGAL/Polygon_mesh_processing/self_intersections.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index 9eb4ee03988..b80b7069550 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -457,7 +457,7 @@ self_intersections( const FaceRange& face_range, typedef std::vector >SeqV; typedef std::back_insert_iterator SeqVI; SeqV face_pairs; - internal::All_faces_filter all_faces_filter(std::back_inserter(face_pairs)); + CGAL::internal::All_faces_filter all_faces_filter(std::back_inserter(face_pairs)); CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(),all_faces_filter,cutoff); // (B) Parallel: perform the geometric tests @@ -475,7 +475,7 @@ self_intersections( const FaceRange& face_range, tbb::parallel_for(tbb::blocked_range(0, face_pairs.size()), all_pairs); // (C) Sequentially: Copy from the concurent container to the output iterator - for(int i=0; i < dointersect.size(); ++i){ + for(std::size_t i=0; i < dointersect.size(); ++i){ if(dointersect[i]) *out ++= face_pairs[i]; } From 744413b3d5b83c4107fe8a84e83f114300a10ab2 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 15 Nov 2019 08:10:57 +0100 Subject: [PATCH 034/185] CGAL::use() parameters --- Spatial_sorting/include/CGAL/Hilbert_sort_base.h | 1 + Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h | 4 +++- Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h | 9 ++++++--- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_base.h b/Spatial_sorting/include/CGAL/Hilbert_sort_base.h index e33f2499eaf..f5a0b3a9efe 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_base.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_base.h @@ -15,6 +15,7 @@ #include #include #include +#include namespace CGAL { diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h b/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h index a3d176b4d56..7012743dfee 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h @@ -145,7 +145,9 @@ public: template void sort (RandomAccessIterator begin, RandomAccessIterator end, Parallel_tag) const { -#ifndef CGAL_LINKED_WITH_TBB +#ifndef CGAL_LINKED_WITH_TBB + CGAL::use(begin); + CGAL::use(end); CGAL_static_assertion_msg (!(boost::is_convertible::value), "Parallel_tag is enabled but TBB is unavailable."); #else diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h b/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h index e92e8421b13..75bd0a82068 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h @@ -170,9 +170,12 @@ public: template void sort (RandomAccessIterator begin, RandomAccessIterator end, Parallel_tag) const { -#ifndef CGAL_LINKED_WITH_TBB - CGAL_static_assertion_msg (!(boost::is_convertible::value), - "Parallel_tag is enabled but TBB is unavailable."); +#ifndef CGAL_LINKED_WITH_TBB + + CGAL::use(begin); + CGAL::use(end); + CGAL_static_assertion_msg (!(boost::is_convertible::value), + "Parallel_tag is enabled but TBB is unavailable."); #else const int y = (x + 1) % 3, z = (x + 2) % 3; if ((end - begin) <= _limit) return; From 642348feffb78d03b093af779ddc3f29b60ccdc9 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 15 Nov 2019 08:24:32 +0100 Subject: [PATCH 035/185] Add example --- .../doc/Spatial_sorting/Spatial_sorting.txt | 6 ++++++ Spatial_sorting/doc/Spatial_sorting/examples.txt | 2 +- Spatial_sorting/examples/Spatial_sorting/parallel.cpp | 10 ++++++---- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt b/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt index 3feb361c595..3d4329c9f6d 100644 --- a/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt +++ b/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt @@ -213,6 +213,12 @@ using the indices of the points in a vector of pairs of points and integers. The Hilbert sort and spatial sort functions when using the median policy and with TBB enabled, are parallized and use up to four/eight threads for 2D/3D. +By default the sequential version is used. The parallel version is used +by adding the template parameter `CGAL::Parallel_tag`. + +\cgalExample{Spatial_sorting/parallel_spatial_sort_2.cpp} + + \section Spatial_sortingDesign Design and Implementation History The first implementation of Hilbert and spatial sorting (2D and 3D) in CGAL was done by Cristophe Delage. Then, Olivier Devillers improved its design, diff --git a/Spatial_sorting/doc/Spatial_sorting/examples.txt b/Spatial_sorting/doc/Spatial_sorting/examples.txt index 557e126b519..2b187d153b5 100644 --- a/Spatial_sorting/doc/Spatial_sorting/examples.txt +++ b/Spatial_sorting/doc/Spatial_sorting/examples.txt @@ -1,5 +1,5 @@ /*! -\example Spatial_sorting/parallel.cpp +\example Spatial_sorting/parallel_spatial_sort_2.cpp \example Spatial_sorting/hilbert.cpp \example Spatial_sorting/hilbert_policies.cpp \example Spatial_sorting/small_example_delaunay_2.cpp diff --git a/Spatial_sorting/examples/Spatial_sorting/parallel.cpp b/Spatial_sorting/examples/Spatial_sorting/parallel.cpp index 2914be56562..3d040677f67 100644 --- a/Spatial_sorting/examples/Spatial_sorting/parallel.cpp +++ b/Spatial_sorting/examples/Spatial_sorting/parallel.cpp @@ -24,11 +24,13 @@ int main() for (int i = 0; i < 2000; ++i){ points.push_back (*gen++); } -#ifdef CGAL_LINKED_WITH_TBB - CGAL::spatial_sort(points.begin(),points.end()); -#else + + // By default sequential CGAL::spatial_sort(points.begin(),points.end()); -#endif + + // Add the template argument to switch on parallelism + // You will get a compile time warning in case TBB is not enabled + CGAL::spatial_sort(points.begin(),points.end()); return 0; } From 2a31497c003dc9240e7ba250ae8a878d9ae96a31 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 15 Nov 2019 08:25:20 +0100 Subject: [PATCH 036/185] Add example --- .../Spatial_sorting/{parallel.cpp => parallel_spatial_sort_2.cpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Spatial_sorting/examples/Spatial_sorting/{parallel.cpp => parallel_spatial_sort_2.cpp} (100%) diff --git a/Spatial_sorting/examples/Spatial_sorting/parallel.cpp b/Spatial_sorting/examples/Spatial_sorting/parallel_spatial_sort_2.cpp similarity index 100% rename from Spatial_sorting/examples/Spatial_sorting/parallel.cpp rename to Spatial_sorting/examples/Spatial_sorting/parallel_spatial_sort_2.cpp From ee5478c905c79ce23710a9b3e904ef7d32810242 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 15 Nov 2019 08:27:21 +0100 Subject: [PATCH 037/185] polish --- .../examples/Spatial_sorting/parallel_spatial_sort_2.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Spatial_sorting/examples/Spatial_sorting/parallel_spatial_sort_2.cpp b/Spatial_sorting/examples/Spatial_sorting/parallel_spatial_sort_2.cpp index 3d040677f67..eb9ffed6303 100644 --- a/Spatial_sorting/examples/Spatial_sorting/parallel_spatial_sort_2.cpp +++ b/Spatial_sorting/examples/Spatial_sorting/parallel_spatial_sort_2.cpp @@ -1,4 +1,3 @@ - #include #include @@ -9,7 +8,6 @@ #include - typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef K::Point_3 Point_3; typedef CGAL::Creator_uniform_3 Creator_3; From f23f3c0979072a163e194a70b2f26324533d90ee Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 15 Nov 2019 08:32:40 +0100 Subject: [PATCH 038/185] polish --- Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_2.h | 2 +- Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_3.h | 2 +- Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h | 6 +++--- Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_2.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_2.h index 15dbdec157f..1dc58ed45b3 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_2.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_2.h @@ -13,7 +13,7 @@ or the middle depending on the `PolicyTag`. \tparam PolicyTag must be `Hilbert_sort_median_policy` or `Hilbert_sort_middle_policy`. -\tparam ConcurrencyTag must be `Sequential_tag`or `Parallel_tag`. With `Parallel_tag` +\tparam ConcurrencyTag must be `Sequential_tag` or `Parallel_tag`. With `Parallel_tag` and TBB enabled, for the median policy up to four threads are used in parallel. */ template< typename Traits, typename PolicyTag, typename ConcurrencyTag = Sequential_tag > diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_3.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_3.h index 6ee0d8deb6a..e08f0b4a39c 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_3.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_3.h @@ -11,7 +11,7 @@ or the middle depending on the `PolicyTag`. \tparam PolicyTag must be `Hilbert_sort_median_policy` or `Hilbert_sort_middle_policy`. -\tparam ConcurrencyTag must be `Sequential_tag`or `Parallel_tag`. With `Parallel_tag` +\tparam ConcurrencyTag must be `Sequential_tag` or `Parallel_tag`. With `Parallel_tag` and TBB enabled, for the median policy up to eight threads are used in parallel. */ template< typename Traits, typename PolicyTag, typename ConcurrencyTag = Sequential_tag > diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h index c416b65f945..7a157472620 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h @@ -8,9 +8,9 @@ along a Hilbert curve. It sorts the range `[begin, end)` in place. - -\tparam ConcurrencyTag With `ConcurrencyTag = Parallel_tag` and with TBB found, the sorting will be -done in 4 threads in 2D, and in 8 threads in 3D with the default policy. +\tparam ConcurrencyTag must be `Sequential_tag` or `Parallel_tag`. +With `Parallel_tag` and TBB enabled, the sorting will be +done using up to four threads in 2D, and up to eight threads in 3D with the median policy. \tparam RandomAccessIterator `std::iterator_traits::%value_type` must be convertible to diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h index 6c29794f6a9..7d5d15b83c6 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h @@ -10,7 +10,7 @@ of being close in the order. It sorts the range `[begin, end)` in place. -\tparam ConcurrencyTag must be `Sequential_tag`or `Parallel_tag`. +\tparam ConcurrencyTag must be `Sequential_tag` or `Parallel_tag`. With `Parallel_tag` and TBB enabled, the sorting will be done using up to four threads in 2D, and up to eight threads in 3D with the median policy. From f8217182dd6f12e576c588272b3c856db3ea7d15 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 15 Nov 2019 10:11:30 +0100 Subject: [PATCH 039/185] Fix CMakeLists.txt --- Spatial_sorting/examples/Spatial_sorting/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Spatial_sorting/examples/Spatial_sorting/CMakeLists.txt b/Spatial_sorting/examples/Spatial_sorting/CMakeLists.txt index a285126fbe6..7b34b2a525f 100644 --- a/Spatial_sorting/examples/Spatial_sorting/CMakeLists.txt +++ b/Spatial_sorting/examples/Spatial_sorting/CMakeLists.txt @@ -18,7 +18,7 @@ if ( CGAL_FOUND ) find_package( TBB QUIET ) if( TBB_FOUND ) include( CGAL_target_use_TBB ) - CGAL_target_use_TBB( parallel ) + CGAL_target_use_TBB( parallel_spatial_sort_2 ) endif() else() From 45846c48a461070c600bf34c39116f23ee2f997c Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 15 Nov 2019 12:10:13 +0100 Subject: [PATCH 040/185] Remove empty section --- Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h index 7a157472620..89b94118aea 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h @@ -24,11 +24,6 @@ The default traits class `Default_traits` is the kernel in which the type \tparam PolicyTag The default policy is `Hilbert_sort_median_policy()` and the other option is `Hilbert_sort_middle_policy()`. -\cgalHeading{Requirements} - -
      - -
    \cgalHeading{Implementation} From cbe11f6e5bb46ca0e8fb8330c8a7da6131bd828c Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 15 Nov 2019 12:48:16 +0100 Subject: [PATCH 041/185] CGAL:: Add Parallel_if_available_tag --- STL_Extension/include/CGAL/tags.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/STL_Extension/include/CGAL/tags.h b/STL_Extension/include/CGAL/tags.h index 4b033abaf32..2b88992794b 100644 --- a/STL_Extension/include/CGAL/tags.h +++ b/STL_Extension/include/CGAL/tags.h @@ -26,7 +26,7 @@ namespace CGAL { struct Void {}; // Boolean_tag is a model of the Boost Integral Constant concept. -// https://www.boost.org/libs/mpl/doc/refmanual/integral-constant.html +// https://www.boost.org/libs/mpl/doc/refmanual/integral-constant.html template struct Boolean_tag { typedef boost::mpl::integral_c_tag tag; @@ -58,6 +58,13 @@ struct Null_functor { struct Sequential_tag {}; struct Parallel_tag : public Sequential_tag {}; +#ifdef CGAL_LINKED_WITH_TBB +typedef CGAL::Parallel_tag Parallel_if_available_tag; +#else +typedef CGAL::Sequential_tag Parallel_if_available_tag; +#endif + + // A function that asserts a specific compile time tag // forcing its two arguments to have equal type. template From d6a89652a152ae956e35a9a9ef61ab5d6c978d13 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 15 Nov 2019 12:48:16 +0100 Subject: [PATCH 042/185] CGAL:: Add Parallel_if_available_tag --- STL_Extension/include/CGAL/tags.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/STL_Extension/include/CGAL/tags.h b/STL_Extension/include/CGAL/tags.h index 4b033abaf32..2b88992794b 100644 --- a/STL_Extension/include/CGAL/tags.h +++ b/STL_Extension/include/CGAL/tags.h @@ -26,7 +26,7 @@ namespace CGAL { struct Void {}; // Boolean_tag is a model of the Boost Integral Constant concept. -// https://www.boost.org/libs/mpl/doc/refmanual/integral-constant.html +// https://www.boost.org/libs/mpl/doc/refmanual/integral-constant.html template struct Boolean_tag { typedef boost::mpl::integral_c_tag tag; @@ -58,6 +58,13 @@ struct Null_functor { struct Sequential_tag {}; struct Parallel_tag : public Sequential_tag {}; +#ifdef CGAL_LINKED_WITH_TBB +typedef CGAL::Parallel_tag Parallel_if_available_tag; +#else +typedef CGAL::Sequential_tag Parallel_if_available_tag; +#endif + + // A function that asserts a specific compile time tag // forcing its two arguments to have equal type. template From 363f77145c2aee9b4697b7819a8363207102d7eb Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 15 Nov 2019 14:24:09 +0100 Subject: [PATCH 043/185] Do first self-intersection tests in parallel in the demo --- Polyhedron/demo/Polyhedron/CMakeLists.txt | 8 +++++++- .../demo/Polyhedron/Scene_polyhedron_selection_item.cpp | 2 +- Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/CMakeLists.txt b/Polyhedron/demo/Polyhedron/CMakeLists.txt index fc4afa3bb09..bce7f8b0b9c 100644 --- a/Polyhedron/demo/Polyhedron/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/CMakeLists.txt @@ -250,7 +250,10 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND) add_item(scene_edit_box_item Plugins/PCA/Scene_edit_box_item.cpp ) add_item(scene_image_item Scene_image_item.cpp) add_item(scene_surface_mesh_item Scene_surface_mesh_item.cpp) - + + if(TBB_FOUND) + CGAL_target_use_TBB(scene_surface_mesh_item) + endif() # special add_item(scene_item_decorator Scene_polyhedron_item_decorator.cpp ) @@ -261,6 +264,9 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND) add_item(scene_selection_item Scene_polyhedron_selection_item.cpp) target_link_libraries(scene_selection_item PUBLIC scene_item_decorator scene_k_ring_selection) + if(TBB_FOUND) + CGAL_target_use_TBB(scene_selection_item) + endif() add_item(scene_shortest_path_item Plugins/Surface_mesh/Scene_polyhedron_shortest_path_item.cpp) target_link_libraries(scene_shortest_path_item PUBLIC scene_item_decorator scene_surface_mesh_item scene_polylines_item) diff --git a/Polyhedron/demo/Polyhedron/Scene_polyhedron_selection_item.cpp b/Polyhedron/demo/Polyhedron/Scene_polyhedron_selection_item.cpp index 8c8a1dcab5f..342349af861 100644 --- a/Polyhedron/demo/Polyhedron/Scene_polyhedron_selection_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_polyhedron_selection_item.cpp @@ -2497,7 +2497,7 @@ QString Scene_polyhedron_selection_item::computeStats(int type) return QString("n/a"); if(is_triangle_mesh(*d->poly)){ bool self_intersect - = CGAL::Polygon_mesh_processing::does_self_intersect(*(d->poly)); + = CGAL::Polygon_mesh_processing::does_self_intersect(*(d->poly)); if (self_intersect) return QString("Yes"); else diff --git a/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp b/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp index 09dd204eff6..88365d2667d 100644 --- a/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp @@ -1656,7 +1656,7 @@ QString Scene_surface_mesh_item::computeStats(int type) { //todo : add a test about cache validity if(is_triangle_mesh(*d->smesh_)) - d->self_intersect = CGAL::Polygon_mesh_processing::does_self_intersect(*(d->smesh_)); + d->self_intersect = CGAL::Polygon_mesh_processing::does_self_intersect(*(d->smesh_)); if (d->self_intersect) return QString("Yes"); else if(is_triangle_mesh(*d->smesh_)) From bef2b5f1b8343e922fff3d48de02d7f8e46eb546 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 15 Nov 2019 16:21:25 +0100 Subject: [PATCH 044/185] Parallelize using 2 or 4 parallel threads --- .../CGAL/Box_intersection_d/segment_tree.h | 15 +--- .../include/CGAL/box_intersection_d.h | 72 ++++++++++++++++--- .../self_intersections_example.cpp | 9 ++- .../self_intersections.h | 30 +++++--- 4 files changed, 91 insertions(+), 35 deletions(-) diff --git a/Box_intersection_d/include/CGAL/Box_intersection_d/segment_tree.h b/Box_intersection_d/include/CGAL/Box_intersection_d/segment_tree.h index 5c31223d85a..d9fccef3776 100644 --- a/Box_intersection_d/include/CGAL/Box_intersection_d/segment_tree.h +++ b/Box_intersection_d/include/CGAL/Box_intersection_d/segment_tree.h @@ -16,7 +16,6 @@ #include - #include #include @@ -24,9 +23,6 @@ #include #include -#ifdef CGAL_LINKED_WITH_TBB -#include -#endif #include #include #include @@ -96,13 +92,9 @@ void one_way_scan( RandomAccessIter1 p_begin, RandomAccessIter1 p_end, { typedef typename Traits::Compare Compare; -#ifdef CGAL_LINKED_WITH_TBB - tbb::parallel_sort( p_begin, p_end, Compare( 0 ) ); - tbb::parallel_sort( i_begin, i_end, Compare( 0 ) ); -#else + // Putting a parallel sort here slows down the overall parallel algorithm std::sort( p_begin, p_end, Compare( 0 ) ); std::sort( i_begin, i_end, Compare( 0 ) ); -#endif // for each box viewed as interval i for( RandomAccessIter2 i = i_begin; i != i_end; ++i ) { @@ -141,13 +133,8 @@ void modified_two_way_scan( { typedef typename Traits::Compare Compare; -#ifdef CGAL_LINKED_WITH_TBB - tbb::parallel_sort( p_begin, p_end, Compare( 0 ) ); - tbb::parallel_sort( i_begin, i_end, Compare( 0 ) ); -#else std::sort( p_begin, p_end, Compare( 0 ) ); std::sort( i_begin, i_end, Compare( 0 ) ); -#endif // for each box viewed as interval while( i_begin != i_end && p_begin != p_end ) { diff --git a/Box_intersection_d/include/CGAL/box_intersection_d.h b/Box_intersection_d/include/CGAL/box_intersection_d.h index bf5a8f3d62a..1d210d76f90 100644 --- a/Box_intersection_d/include/CGAL/box_intersection_d.h +++ b/Box_intersection_d/include/CGAL/box_intersection_d.h @@ -25,6 +25,7 @@ #include #include +#include "tbb/parallel_invoke.h" #include @@ -178,14 +179,69 @@ void box_self_intersection_d( std::ptrdiff_t cutoff, Box_intersection_d::Topology topology) { - // Copying rather than calling 'box_intersection_d(begin, end, begin, end, ...' - // is necessary because the 'std::partition' and range splits on the first range - // would be messed up by sorts on the second range otherwise. - typedef typename std::iterator_traits::value_type val_t; - std::vector< val_t> i( begin, end); - box_intersection_d( begin, end, i.begin(), i.end(), - callback, box_traits, cutoff, topology, - Box_intersection_d::COMPLETE); + // Copying rather than calling 'box_intersection_d(begin, end, begin, end, ...' + // is necessary because the 'std::partition' and range splits on the first range + // would be messed up by sorts on the second range otherwise. + typedef typename std::iterator_traits::value_type val_t; + std::vector< val_t> i( begin, end); +#ifndef CGAL_LINKED_WITH_TBB + box_intersection_d( begin, end, i.begin(), i.end(), + callback, box_traits, cutoff, topology, + Box_intersection_d::COMPLETE); +#else + + // TODO: Check which of the two following approaches is better + // The first one makes three copies of the vector and performs + // four parallel tasks + // The second one makes one copy and performs two times two parallel tasks +#ifdef CGAL_BI_FOR_SPEED + + + std::vector< val_t> j( begin, end); + std::vector< val_t> k( begin, end); + + RandomAccessIter mid = begin; + std::advance(mid, std::distance(begin,end)/2); + typename std::vector< val_t>::iterator midi = i.begin(); + std::advance(midi, std::distance(begin,end)/2); + typename std::vector< val_t>::iterator midj = j.begin(); + std::advance(midj, std::distance(begin,end)/2); + typename std::vector< val_t>::iterator midk = k.begin(); + std::advance(midk, std::distance(begin,end)/2); + + tbb::parallel_invoke([&]{ box_intersection_d( begin, mid, i.begin(), midi, + callback, box_traits, cutoff, topology, + Box_intersection_d::COMPLETE); }, + [&]{ box_intersection_d( mid, end, midi, i.end(), + callback, box_traits, cutoff, topology, + Box_intersection_d::COMPLETE); }, + [&]{ box_intersection_d( j.begin(), midj, midk, k.end(), + callback, box_traits, cutoff, topology, + Box_intersection_d::COMPLETE); }, + [&]{ box_intersection_d( midj, j.end(), k.begin(), midk, + callback, box_traits, cutoff, topology, + Box_intersection_d::COMPLETE); } ); +#else + RandomAccessIter mid = begin; + std::advance(mid, std::distance(begin,end)/2); + typename std::vector< val_t>::iterator midi = i.begin(); + std::advance(midi, std::distance(begin,end)/2); + + tbb::parallel_invoke([&]{ box_intersection_d( begin, mid, i.begin(), midi, + callback, box_traits, cutoff, topology, + Box_intersection_d::COMPLETE); }, + [&]{ box_intersection_d( mid, end, midi, i.end(), + callback, box_traits, cutoff, topology, + Box_intersection_d::COMPLETE); } ); + tbb::parallel_invoke([&]{box_intersection_d( begin, mid, midi, i.end(), + callback, box_traits, cutoff, topology, + Box_intersection_d::COMPLETE); }, + [&]{ box_intersection_d( mid, end, i.begin(), midi, + callback, box_traits, cutoff, topology, + Box_intersection_d::COMPLETE); } ); +#endif + +#endif } template< class RandomAccessIter, class Callback, class BoxTraits > diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp index 011e642891e..28249397952 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp @@ -2,6 +2,7 @@ #include #include +#include #include @@ -22,17 +23,21 @@ int main(int argc, char* argv[]) std::cerr << "Not a valid input file." << std::endl; return 1; } - + + CGAL::Real_timer rt; + rt.start(); + /* bool intersecting = PMP::does_self_intersect(mesh, PMP::parameters::vertex_point_map(get(CGAL::vertex_point, mesh))); std::cout << (intersecting ? "There are self-intersections." : "There is no self-intersection.") << std::endl; - + */ std::vector > intersected_tris; PMP::self_intersections(faces(mesh),mesh, std::back_inserter(intersected_tris)); + std::cout << rt.time() << " sec." << std::endl; std::cout << intersected_tris.size() << " pairs of triangles intersect." << std::endl; return 0; diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index 55adf9ab558..c6a4b42925b 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -48,6 +48,7 @@ #ifdef CGAL_LINKED_WITH_TBB #include #include +#include #endif #ifdef DOXYGEN_RUNNING @@ -197,6 +198,7 @@ struct Intersect_facets //TODO: use the same code for the linear pass? // The functor for doing all geometric tests in parallel template struct AllPairs @@ -211,14 +213,14 @@ struct AllPairs // data members const TM& m_tmesh; const VertexPointMap m_vpmap; - const std::vector >& face_pairs; + const FacePairs& face_pairs; std::vector& dointersect; typename Kernel::Construct_segment_3 segment_functor; typename Kernel::Construct_triangle_3 triangle_functor; typename Kernel::Do_intersect_3 do_intersect_3_functor; - AllPairs(const std::vector >& face_pairs, + AllPairs(const FacePairs& face_pairs, std::vector& dointersect, const TM& tmesh, VertexPointMap vpmap, const Kernel& kernel) : m_tmesh(tmesh) @@ -345,7 +347,7 @@ struct All_faces_filter template void operator()(const Box* b, const Box* c) const { - *m_iterator ++ = std::make_pair(b->info(), c->info()); + *m_iterator ++ = std::make_pair(b->info(), c->info()); } // end operator () }; @@ -378,7 +380,7 @@ namespace Polygon_mesh_processing { * @pre `CGAL::is_triangle_mesh(tmesh)` * * @tparam ConcurrencyTag enables sequential versus parallel algorithm. - * Possible values are `Sequential_tag` and `Parallel_tag`. + * Possible values are `Sequential_tag`, `Parallel_tag`, and `Parallel_if_available_tag`. * @tparam FaceRange range of `boost::graph_traits::%face_descriptor`, * model of `Range`. * Its iterator type is `RandomAccessIterator`. @@ -453,10 +455,14 @@ self_intersections( const FaceRange& face_range, // (Parallel version of the code) // (A) Sequentially write all pairs of faces with intersecting bbox into a std::vector std::ptrdiff_t cutoff = 2000; - typedef std::vector >SeqV; - typedef std::back_insert_iterator SeqVI; - SeqV face_pairs; - CGAL::internal::All_faces_filter all_faces_filter(std::back_inserter(face_pairs)); +#if 0 + typedef std::vector >FacePairs; +#else + typedef tbb::concurrent_vector >FacePairs; +#endif + typedef std::back_insert_iterator FacePairsI; + FacePairs face_pairs; + CGAL::internal::All_faces_filter all_faces_filter(std::back_inserter(face_pairs)); CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(),all_faces_filter,cutoff); // (B) Parallel: perform the geometric tests @@ -464,7 +470,7 @@ self_intersections( const FaceRange& face_range, std::vector dointersect(face_pairs.size(),0); - CGAL::internal::AllPairs + CGAL::internal::AllPairs all_pairs(face_pairs, dointersect, tmesh, @@ -520,7 +526,7 @@ self_intersections(const FaceRange& face_range, * @pre `CGAL::is_triangle_mesh(tmesh)` * * @tparam ConcurrencyTag enables sequential versus parallel algorithm. - * Possible values are `Sequential_tag` and `Parallel_tag`. + * Possible values are `Sequential_tag`, `Parallel_tag`, and `Parallel_if_available_tag`. * @tparam TriangleMesh a model of `FaceListGraph` * @tparam OutputIterator a model of `OutputIterator` holding objects of type * `std::pair::%face_descriptor, boost::graph_traits::%face_descriptor>` @@ -572,7 +578,7 @@ self_intersections(const TriangleMesh& tmesh, OutputIterator out) * @pre `CGAL::is_triangle_mesh(tmesh)` * * @tparam ConcurrencyTag enables sequential versus parallel algorithm. - * Possible values are `Sequential_tag` and `Parallel_tag`. + * Possible values are `Sequential_tag`, `Parallel_tag`, and `Parallel_if_available_tag`. * @tparam TriangleMesh a model of `FaceListGraph` * @tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" * @@ -614,6 +620,8 @@ bool does_self_intersect(const TriangleMesh& tmesh * This function depends on the package \ref PkgBoxIntersectionD * @pre `CGAL::is_triangle_mesh(tmesh)` * + * @tparam ConcurrencyTag enables sequential versus parallel algorithm. + * Possible values are `Sequential_tag`, `Parallel_tag`, and `Parallel_if_available_tag`. * @tparam FaceRange a range of `face_descriptor` * @tparam TriangleMesh a model of `FaceListGraph` * @tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" From a44674a694456d98f1af9040ae4ff82d670910ae Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 15 Nov 2019 21:45:19 +0100 Subject: [PATCH 045/185] Add ConcurrencyTag in Box_intersection_d --- .../include/CGAL/box_intersection_d.h | 76 ++++++++++++++----- .../self_intersections_example.cpp | 11 +-- .../self_intersections.h | 13 ++-- 3 files changed, 65 insertions(+), 35 deletions(-) diff --git a/Box_intersection_d/include/CGAL/box_intersection_d.h b/Box_intersection_d/include/CGAL/box_intersection_d.h index 1d210d76f90..51c41cd5156 100644 --- a/Box_intersection_d/include/CGAL/box_intersection_d.h +++ b/Box_intersection_d/include/CGAL/box_intersection_d.h @@ -25,7 +25,9 @@ #include #include -#include "tbb/parallel_invoke.h" +#ifdef CGAL_LINKED_WITH_TBB +#include +#endif #include @@ -177,26 +179,46 @@ void box_self_intersection_d( Callback callback, BoxTraits box_traits, std::ptrdiff_t cutoff, - Box_intersection_d::Topology topology) + Box_intersection_d::Topology topology, + Sequential_tag) { // Copying rather than calling 'box_intersection_d(begin, end, begin, end, ...' // is necessary because the 'std::partition' and range splits on the first range // would be messed up by sorts on the second range otherwise. typedef typename std::iterator_traits::value_type val_t; std::vector< val_t> i( begin, end); -#ifndef CGAL_LINKED_WITH_TBB + box_intersection_d( begin, end, i.begin(), i.end(), - callback, box_traits, cutoff, topology, - Box_intersection_d::COMPLETE); + callback, box_traits, cutoff, topology, + Box_intersection_d::COMPLETE); +} + + +template< class RandomAccessIter, class Callback, class BoxTraits > +void box_self_intersection_d( + RandomAccessIter begin, RandomAccessIter end, + Callback callback, + BoxTraits box_traits, + std::ptrdiff_t cutoff, + Box_intersection_d::Topology topology, + Parallel_tag) +{ +#if !defined(CGAL_LINKED_WITH_TBB) + use(begin); use(end); use(callback); use(box_traits); use(cutoff); use(topology); + CGAL_static_assertion_msg (!(boost::is_convertible::value), + "Parallel_tag is enabled but TBB is unavailable."); #else + // Copying rather than calling 'box_intersection_d(begin, end, begin, end, ...' + // is necessary because the 'std::partition' and range splits on the first range + // would be messed up by sorts on the second range otherwise. + typedef typename std::iterator_traits::value_type val_t; + std::vector< val_t> i( begin, end); // TODO: Check which of the two following approaches is better // The first one makes three copies of the vector and performs // four parallel tasks // The second one makes one copy and performs two times two parallel tasks #ifdef CGAL_BI_FOR_SPEED - - std::vector< val_t> j( begin, end); std::vector< val_t> k( begin, end); @@ -221,7 +243,7 @@ void box_self_intersection_d( [&]{ box_intersection_d( midj, j.end(), k.begin(), midk, callback, box_traits, cutoff, topology, Box_intersection_d::COMPLETE); } ); -#else +#else RandomAccessIter mid = begin; std::advance(mid, std::distance(begin,end)/2); typename std::vector< val_t>::iterator midi = i.begin(); @@ -239,44 +261,58 @@ void box_self_intersection_d( [&]{ box_intersection_d( mid, end, i.begin(), midi, callback, box_traits, cutoff, topology, Box_intersection_d::COMPLETE); } ); -#endif +#endif -#endif +#endif +} + +// Generic call with box traits parameter, specialized for self-intersection. +// - make all default parameters explicit overloads (workaround) +template< class ConcurrencyTag = Sequential_tag, class RandomAccessIter, class Callback, class BoxTraits > +void box_self_intersection_d( + RandomAccessIter begin, RandomAccessIter end, + Callback callback, + BoxTraits box_traits, + std::ptrdiff_t cutoff, + Box_intersection_d::Topology topology) +{ + box_self_intersection_d(begin,end, callback, box_traits, cutoff, topology, ConcurrencyTag()); } -template< class RandomAccessIter, class Callback, class BoxTraits > + +template< class ConcurrencyTag = Sequential_tag, class RandomAccessIter, class Callback, class BoxTraits > void box_self_intersection_d( RandomAccessIter begin, RandomAccessIter end, Callback callback, BoxTraits box_traits, std::ptrdiff_t cutoff) { - return box_self_intersection_d(begin, end, callback, box_traits, cutoff, + return box_self_intersection_d(begin, end, callback, box_traits, cutoff, Box_intersection_d::CLOSED); } -template< class RandomAccessIter, class Callback, class BoxTraits > +template< class ConcurrencyTag = Sequential_tag, class RandomAccessIter, class Callback, class BoxTraits > void box_self_intersection_d( RandomAccessIter begin, RandomAccessIter end, Callback callback, BoxTraits box_traits) { - return box_self_intersection_d(begin, end, callback, box_traits, 10); + return box_self_intersection_d(begin, end, callback, box_traits, 10); } // Specialized call with default box traits, specialized for self-intersection. // - make all default parameters explicit overloads (workaround) -template< class RandomAccessIter, class Callback > +template< class ConcurrencyTag = Sequential_tag, class RandomAccessIter, class Callback > void box_self_intersection_d( RandomAccessIter begin, RandomAccessIter end, Callback callback) { typedef typename std::iterator_traits::value_type val_t; typedef Box_intersection_d::Box_traits_d< val_t> Box_traits; - box_self_intersection_d(begin, end, callback, Box_traits()); + box_self_intersection_d(begin, end, callback, Box_traits()); } -template< class RandomAccessIter, class Callback > +template< class ConcurrencyTag = Sequential_tag, class RandomAccessIter, class Callback > void box_self_intersection_d( RandomAccessIter begin, RandomAccessIter end, Callback callback, @@ -284,10 +320,10 @@ void box_self_intersection_d( { typedef typename std::iterator_traits::value_type val_t; typedef Box_intersection_d::Box_traits_d< val_t> Box_traits; - box_self_intersection_d(begin, end, callback, Box_traits(), cutoff); + box_self_intersection_d(begin, end, callback, Box_traits(), cutoff); } -template< class RandomAccessIter, class Callback > + template< class ConcurrencyTag = Sequential_tag, class RandomAccessIter, class Callback > void box_self_intersection_d( RandomAccessIter begin, RandomAccessIter end, Callback callback, @@ -296,7 +332,7 @@ void box_self_intersection_d( { typedef typename std::iterator_traits::value_type val_t; typedef Box_intersection_d::Box_traits_d< val_t> Box_traits; - box_self_intersection_d(begin, end, callback, + box_self_intersection_d(begin, end, callback, Box_traits(), cutoff, topology ); } diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp index 28249397952..240632ee690 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp @@ -2,7 +2,6 @@ #include #include -#include #include @@ -24,20 +23,16 @@ int main(int argc, char* argv[]) return 1; } - CGAL::Real_timer rt; - rt.start(); - /* - bool intersecting = PMP::does_self_intersect(mesh, + bool intersecting = PMP::does_self_intersect(mesh, PMP::parameters::vertex_point_map(get(CGAL::vertex_point, mesh))); std::cout << (intersecting ? "There are self-intersections." : "There is no self-intersection.") << std::endl; - */ + std::vector > intersected_tris; - PMP::self_intersections(faces(mesh),mesh, std::back_inserter(intersected_tris)); + PMP::self_intersections(faces(mesh),mesh, std::back_inserter(intersected_tris)); - std::cout << rt.time() << " sec." << std::endl; std::cout << intersected_tris.size() << " pairs of triangles intersect." << std::endl; return 0; diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index c6a4b42925b..156569ad1ab 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -450,20 +450,19 @@ self_intersections( const FaceRange& face_range, CGAL_static_assertion_msg (!(boost::is_convertible::value), "Parallel_tag is enabled but TBB is unavailable."); #else + if (boost::is_convertible::value) { - // (Parallel version of the code) + // (Parallel version of the code) // (A) Sequentially write all pairs of faces with intersecting bbox into a std::vector std::ptrdiff_t cutoff = 2000; -#if 0 - typedef std::vector >FacePairs; -#else + typedef tbb::concurrent_vector >FacePairs; -#endif + typedef std::back_insert_iterator FacePairsI; FacePairs face_pairs; CGAL::internal::All_faces_filter all_faces_filter(std::back_inserter(face_pairs)); - CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(),all_faces_filter,cutoff); + CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(),all_faces_filter,cutoff); // (B) Parallel: perform the geometric tests typedef typename GetGeomTraits::type GeomTraits; @@ -557,7 +556,7 @@ self_intersections(const TriangleMesh& tmesh, OutputIterator out, const CGAL_PMP_NP_CLASS& np) { - return self_intersections(faces(tmesh), tmesh, out, np); + return self_intersections(faces(tmesh), tmesh, out, np); } /// \cond SKIP_IN_MANUAL From 84c4c16f7015fadf7e21cb15b7e4d444d28edefe Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 18 Nov 2019 14:12:20 +0100 Subject: [PATCH 046/185] use -> USE --- Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h | 4 ++-- Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h b/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h index 7012743dfee..a75f93e7646 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h @@ -146,8 +146,8 @@ public: void sort (RandomAccessIterator begin, RandomAccessIterator end, Parallel_tag) const { #ifndef CGAL_LINKED_WITH_TBB - CGAL::use(begin); - CGAL::use(end); + CGAL::USE(begin); + CGAL::USE(end); CGAL_static_assertion_msg (!(boost::is_convertible::value), "Parallel_tag is enabled but TBB is unavailable."); #else diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h b/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h index 75bd0a82068..e59024c9968 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h @@ -172,8 +172,8 @@ public: { #ifndef CGAL_LINKED_WITH_TBB - CGAL::use(begin); - CGAL::use(end); + CGAL::USE(begin); + CGAL::USE(end); CGAL_static_assertion_msg (!(boost::is_convertible::value), "Parallel_tag is enabled but TBB is unavailable."); #else From a682dcb3602d9f3a195d2e79791899083a5e9fae Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 18 Nov 2019 14:21:21 +0100 Subject: [PATCH 047/185] use -> USE --- Box_intersection_d/include/CGAL/box_intersection_d.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Box_intersection_d/include/CGAL/box_intersection_d.h b/Box_intersection_d/include/CGAL/box_intersection_d.h index 51c41cd5156..ce8b81b854e 100644 --- a/Box_intersection_d/include/CGAL/box_intersection_d.h +++ b/Box_intersection_d/include/CGAL/box_intersection_d.h @@ -204,7 +204,7 @@ void box_self_intersection_d( Parallel_tag) { #if !defined(CGAL_LINKED_WITH_TBB) - use(begin); use(end); use(callback); use(box_traits); use(cutoff); use(topology); + USE(begin); USE(end); USE(callback); USE(box_traits); USE(cutoff); USE(topology); CGAL_static_assertion_msg (!(boost::is_convertible::value), "Parallel_tag is enabled but TBB is unavailable."); #else From 287a2747e14de79c5ff6f755d61184b6a20c1359 Mon Sep 17 00:00:00 2001 From: Mael Date: Mon, 18 Nov 2019 15:40:24 +0100 Subject: [PATCH 048/185] fix CGAL_USE usage --- Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h b/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h index a75f93e7646..d66144c8158 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h @@ -146,8 +146,8 @@ public: void sort (RandomAccessIterator begin, RandomAccessIterator end, Parallel_tag) const { #ifndef CGAL_LINKED_WITH_TBB - CGAL::USE(begin); - CGAL::USE(end); + CGAL_USE(begin); + CGAL_USE(end); CGAL_static_assertion_msg (!(boost::is_convertible::value), "Parallel_tag is enabled but TBB is unavailable."); #else From a6957659fda34c750307a69608d113a1c3849469 Mon Sep 17 00:00:00 2001 From: Mael Date: Mon, 18 Nov 2019 15:40:51 +0100 Subject: [PATCH 049/185] fix CGAL_USE usage --- Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h b/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h index e59024c9968..38d03ff6299 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h @@ -172,8 +172,8 @@ public: { #ifndef CGAL_LINKED_WITH_TBB - CGAL::USE(begin); - CGAL::USE(end); + CGAL_USE(begin); + CGAL_USE(end); CGAL_static_assertion_msg (!(boost::is_convertible::value), "Parallel_tag is enabled but TBB is unavailable."); #else From d33eb65cbf5688b713ea690e7ff2198707b1eeaf Mon Sep 17 00:00:00 2001 From: Mael Date: Mon, 18 Nov 2019 15:43:04 +0100 Subject: [PATCH 050/185] fix CGAL_USE usage --- Box_intersection_d/include/CGAL/box_intersection_d.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Box_intersection_d/include/CGAL/box_intersection_d.h b/Box_intersection_d/include/CGAL/box_intersection_d.h index ce8b81b854e..3759f2584b9 100644 --- a/Box_intersection_d/include/CGAL/box_intersection_d.h +++ b/Box_intersection_d/include/CGAL/box_intersection_d.h @@ -25,6 +25,8 @@ #include #include +#include + #ifdef CGAL_LINKED_WITH_TBB #include #endif @@ -204,7 +206,7 @@ void box_self_intersection_d( Parallel_tag) { #if !defined(CGAL_LINKED_WITH_TBB) - USE(begin); USE(end); USE(callback); USE(box_traits); USE(cutoff); USE(topology); + CGAL_USE(begin); CGAL_USE(end); CGAL_USE(callback); CGAL_USE(box_traits); CGAL_USE(cutoff); CGAL_USE(topology); CGAL_static_assertion_msg (!(boost::is_convertible::value), "Parallel_tag is enabled but TBB is unavailable."); #else From 4bbaafe80830d35530a28c8315a2d6e60b82a6bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 19 Nov 2019 11:56:10 +0100 Subject: [PATCH 051/185] Fix using undefined type --- Box_intersection_d/include/CGAL/box_intersection_d.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Box_intersection_d/include/CGAL/box_intersection_d.h b/Box_intersection_d/include/CGAL/box_intersection_d.h index 3759f2584b9..89effb7ce06 100644 --- a/Box_intersection_d/include/CGAL/box_intersection_d.h +++ b/Box_intersection_d/include/CGAL/box_intersection_d.h @@ -207,8 +207,7 @@ void box_self_intersection_d( { #if !defined(CGAL_LINKED_WITH_TBB) CGAL_USE(begin); CGAL_USE(end); CGAL_USE(callback); CGAL_USE(box_traits); CGAL_USE(cutoff); CGAL_USE(topology); - CGAL_static_assertion_msg (!(boost::is_convertible::value), - "Parallel_tag is enabled but TBB is unavailable."); + CGAL_static_assertion_msg(false, "Parallel_tag is enabled but TBB is unavailable."); #else // Copying rather than calling 'box_intersection_d(begin, end, begin, end, ...' // is necessary because the 'std::partition' and range splits on the first range From 44e2b52ca7a2c958550f8c9ed7c0992c14efb833 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 19 Nov 2019 12:50:21 +0100 Subject: [PATCH 052/185] Clean superfluous overloads --- .../include/CGAL/box_intersection_d.h | 171 ++++++++---------- 1 file changed, 74 insertions(+), 97 deletions(-) diff --git a/Box_intersection_d/include/CGAL/box_intersection_d.h b/Box_intersection_d/include/CGAL/box_intersection_d.h index 89effb7ce06..41da730d747 100644 --- a/Box_intersection_d/include/CGAL/box_intersection_d.h +++ b/Box_intersection_d/include/CGAL/box_intersection_d.h @@ -172,101 +172,6 @@ void box_intersection_d( Box_intersection_d::BIPARTITE); } - -// Generic call with box traits parameter, specialized for self-intersection. -// - make all default parameters explicit overloads (workaround) -template< class RandomAccessIter, class Callback, class BoxTraits > -void box_self_intersection_d( - RandomAccessIter begin, RandomAccessIter end, - Callback callback, - BoxTraits box_traits, - std::ptrdiff_t cutoff, - Box_intersection_d::Topology topology, - Sequential_tag) -{ - // Copying rather than calling 'box_intersection_d(begin, end, begin, end, ...' - // is necessary because the 'std::partition' and range splits on the first range - // would be messed up by sorts on the second range otherwise. - typedef typename std::iterator_traits::value_type val_t; - std::vector< val_t> i( begin, end); - - box_intersection_d( begin, end, i.begin(), i.end(), - callback, box_traits, cutoff, topology, - Box_intersection_d::COMPLETE); -} - - -template< class RandomAccessIter, class Callback, class BoxTraits > -void box_self_intersection_d( - RandomAccessIter begin, RandomAccessIter end, - Callback callback, - BoxTraits box_traits, - std::ptrdiff_t cutoff, - Box_intersection_d::Topology topology, - Parallel_tag) -{ -#if !defined(CGAL_LINKED_WITH_TBB) - CGAL_USE(begin); CGAL_USE(end); CGAL_USE(callback); CGAL_USE(box_traits); CGAL_USE(cutoff); CGAL_USE(topology); - CGAL_static_assertion_msg(false, "Parallel_tag is enabled but TBB is unavailable."); -#else - // Copying rather than calling 'box_intersection_d(begin, end, begin, end, ...' - // is necessary because the 'std::partition' and range splits on the first range - // would be messed up by sorts on the second range otherwise. - typedef typename std::iterator_traits::value_type val_t; - std::vector< val_t> i( begin, end); - - // TODO: Check which of the two following approaches is better - // The first one makes three copies of the vector and performs - // four parallel tasks - // The second one makes one copy and performs two times two parallel tasks -#ifdef CGAL_BI_FOR_SPEED - std::vector< val_t> j( begin, end); - std::vector< val_t> k( begin, end); - - RandomAccessIter mid = begin; - std::advance(mid, std::distance(begin,end)/2); - typename std::vector< val_t>::iterator midi = i.begin(); - std::advance(midi, std::distance(begin,end)/2); - typename std::vector< val_t>::iterator midj = j.begin(); - std::advance(midj, std::distance(begin,end)/2); - typename std::vector< val_t>::iterator midk = k.begin(); - std::advance(midk, std::distance(begin,end)/2); - - tbb::parallel_invoke([&]{ box_intersection_d( begin, mid, i.begin(), midi, - callback, box_traits, cutoff, topology, - Box_intersection_d::COMPLETE); }, - [&]{ box_intersection_d( mid, end, midi, i.end(), - callback, box_traits, cutoff, topology, - Box_intersection_d::COMPLETE); }, - [&]{ box_intersection_d( j.begin(), midj, midk, k.end(), - callback, box_traits, cutoff, topology, - Box_intersection_d::COMPLETE); }, - [&]{ box_intersection_d( midj, j.end(), k.begin(), midk, - callback, box_traits, cutoff, topology, - Box_intersection_d::COMPLETE); } ); -#else - RandomAccessIter mid = begin; - std::advance(mid, std::distance(begin,end)/2); - typename std::vector< val_t>::iterator midi = i.begin(); - std::advance(midi, std::distance(begin,end)/2); - - tbb::parallel_invoke([&]{ box_intersection_d( begin, mid, i.begin(), midi, - callback, box_traits, cutoff, topology, - Box_intersection_d::COMPLETE); }, - [&]{ box_intersection_d( mid, end, midi, i.end(), - callback, box_traits, cutoff, topology, - Box_intersection_d::COMPLETE); } ); - tbb::parallel_invoke([&]{box_intersection_d( begin, mid, midi, i.end(), - callback, box_traits, cutoff, topology, - Box_intersection_d::COMPLETE); }, - [&]{ box_intersection_d( mid, end, i.begin(), midi, - callback, box_traits, cutoff, topology, - Box_intersection_d::COMPLETE); } ); -#endif - -#endif -} - // Generic call with box traits parameter, specialized for self-intersection. // - make all default parameters explicit overloads (workaround) template< class ConcurrencyTag = Sequential_tag, class RandomAccessIter, class Callback, class BoxTraits > @@ -277,10 +182,82 @@ void box_self_intersection_d( std::ptrdiff_t cutoff, Box_intersection_d::Topology topology) { - box_self_intersection_d(begin,end, callback, box_traits, cutoff, topology, ConcurrencyTag()); +#ifndef CGAL_LINKED_WITH_TBB + CGAL_static_assertion_msg (!(boost::is_convertible::value), + "Parallel_tag is enabled but TBB is unavailable."); +#else // CGAL_LINKED_WITH_TBB + if(boost::is_convertible::value) + { + // Copying rather than calling 'box_intersection_d(begin, end, begin, end, ...' + // is necessary because the 'std::partition' and range splits on the first range + // would be messed up by sorts on the second range otherwise. + typedef typename std::iterator_traits::value_type val_t; + std::vector< val_t> i( begin, end); + + // TODO: Check which of the two following approaches is better + // The first one makes three copies of the vector and performs four parallel tasks + // The second one makes one copy, but must perform two times two parallel tasks (can't + // do all four at the same time otherwise the sort / split will conflict) +#ifdef CGAL_BOX_INTER_FOUR_RANGES + std::vector< val_t> j( begin, end); + std::vector< val_t> k( begin, end); + + RandomAccessIter mid = begin; + std::advance(mid, std::distance(begin,end)/2); + typename std::vector< val_t>::iterator midi = i.begin(); + std::advance(midi, std::distance(begin,end)/2); + typename std::vector< val_t>::iterator midj = j.begin(); + std::advance(midj, std::distance(begin,end)/2); + typename std::vector< val_t>::iterator midk = k.begin(); + std::advance(midk, std::distance(begin,end)/2); + + tbb::parallel_invoke([&]{ box_intersection_d( begin, mid, i.begin(), midi, + callback, box_traits, cutoff, topology, + Box_intersection_d::COMPLETE); }, + [&]{ box_intersection_d( mid, end, midi, i.end(), + callback, box_traits, cutoff, topology, + Box_intersection_d::COMPLETE); }, + [&]{ box_intersection_d( j.begin(), midj, midk, k.end(), + callback, box_traits, cutoff, topology, + Box_intersection_d::COMPLETE); }, + [&]{ box_intersection_d( midj, j.end(), k.begin(), midk, + callback, box_traits, cutoff, topology, + Box_intersection_d::COMPLETE); } ); +#else // CGAL_BOX_INTER_FOUR_RANGES + RandomAccessIter mid = begin; + std::advance(mid, std::distance(begin,end)/2); + typename std::vector< val_t>::iterator midi = i.begin(); + std::advance(midi, std::distance(begin,end)/2); + + tbb::parallel_invoke([&]{ box_intersection_d( begin, mid, i.begin(), midi, + callback, box_traits, cutoff, topology, + Box_intersection_d::COMPLETE); }, + [&]{ box_intersection_d( mid, end, midi, i.end(), + callback, box_traits, cutoff, topology, + Box_intersection_d::COMPLETE); } ); + tbb::parallel_invoke([&]{box_intersection_d( begin, mid, midi, i.end(), + callback, box_traits, cutoff, topology, + Box_intersection_d::COMPLETE); }, + [&]{ box_intersection_d( mid, end, i.begin(), midi, + callback, box_traits, cutoff, topology, + Box_intersection_d::COMPLETE); } ); +#endif // CGAL_BOX_INTER_FOUR_RANGES + } + else +#endif // CGAL_LINKED_WITH_TBB + { + // Copying rather than calling 'box_intersection_d(begin, end, begin, end, ...' + // is necessary because the 'std::partition' and range splits on the first range + // would be messed up by sorts on the second range otherwise. + typedef typename std::iterator_traits::value_type val_t; + std::vector< val_t> i( begin, end); + + box_intersection_d( begin, end, i.begin(), i.end(), + callback, box_traits, cutoff, topology, + Box_intersection_d::COMPLETE); + } } - template< class ConcurrencyTag = Sequential_tag, class RandomAccessIter, class Callback, class BoxTraits > void box_self_intersection_d( RandomAccessIter begin, RandomAccessIter end, From ac86fadd7a60059db65e7fec5eb6c84649067e5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 19 Nov 2019 12:51:17 +0100 Subject: [PATCH 053/185] Misc code formatting improvements --- .../include/CGAL/box_intersection_d.h | 4 +- .../internal/Static_filters/Static_filters.h | 29 ++-- .../self_intersections_example.cpp | 24 ++-- .../self_intersections.h | 126 ++++++++---------- STL_Extension/include/CGAL/tags.h | 1 - 5 files changed, 79 insertions(+), 105 deletions(-) diff --git a/Box_intersection_d/include/CGAL/box_intersection_d.h b/Box_intersection_d/include/CGAL/box_intersection_d.h index 41da730d747..7521802ba49 100644 --- a/Box_intersection_d/include/CGAL/box_intersection_d.h +++ b/Box_intersection_d/include/CGAL/box_intersection_d.h @@ -266,7 +266,7 @@ void box_self_intersection_d( std::ptrdiff_t cutoff) { return box_self_intersection_d(begin, end, callback, box_traits, cutoff, - Box_intersection_d::CLOSED); + Box_intersection_d::CLOSED); } template< class ConcurrencyTag = Sequential_tag, class RandomAccessIter, class Callback, class BoxTraits > @@ -311,7 +311,7 @@ void box_self_intersection_d( typedef typename std::iterator_traits::value_type val_t; typedef Box_intersection_d::Box_traits_d< val_t> Box_traits; box_self_intersection_d(begin, end, callback, - Box_traits(), cutoff, topology ); + Box_traits(), cutoff, topology ); } diff --git a/Filtered_kernel/include/CGAL/internal/Static_filters/Static_filters.h b/Filtered_kernel/include/CGAL/internal/Static_filters/Static_filters.h index 6fd346434fb..55bd1d3778b 100644 --- a/Filtered_kernel/include/CGAL/internal/Static_filters/Static_filters.h +++ b/Filtered_kernel/include/CGAL/internal/Static_filters/Static_filters.h @@ -41,9 +41,6 @@ #endif // CGAL_DISABLE_STATIC_FILTERS_ADDED_2011 - -# include - #ifndef CGAL_NO_EQUAL_3_STATIC_FILTERS # include # include @@ -67,6 +64,7 @@ # include #endif // NOT NOT CGAL_NO_DO_INTERSECT_STATIC_FILTERS +#include #include #include #include @@ -99,7 +97,6 @@ class Static_filters : public K_base typedef Static_filters Self; public: - typedef Static_filters_predicates::Coplanar_3 Coplanar_3; #ifndef CGAL_NO_EQUAL_3_STATIC_FILTERS typedef Static_filters_predicates::Equal_2 Equal_2; typedef Static_filters_predicates::Equal_3 Equal_3; @@ -124,6 +121,7 @@ public: typedef Static_filters_predicates::Side_of_oriented_circle_2 Side_of_oriented_circle_2; typedef Static_filters_predicates::Side_of_oriented_sphere_3 Side_of_oriented_sphere_3; typedef Static_filters_predicates::Compare_squared_radius_3 Compare_squared_radius_3; + typedef Static_filters_predicates::Coplanar_3 Coplanar_3; typedef Static_filters_predicates::Compare_weighted_squared_radius_3 Compare_weighted_squared_radius_3; typedef Static_filters_predicates::Power_side_of_oriented_power_sphere_3 Power_side_of_oriented_power_sphere_3; @@ -140,35 +138,29 @@ public: collinear_3_object() const { return Collinear_3(); } - Coplanar_3 - coplanar_3_object() const - { - return Coplanar_3(); - } - #ifndef CGAL_NO_EQUAL_3_STATIC_FILTERS - Equal_2 + Equal_2 equal_2_object() const { return Equal_2(); } - Equal_3 + Equal_3 equal_3_object() const { return Equal_3(); } #endif // NOT CGAL_NO_EQUAL_3_STATIC_FILTERS #ifndef CGAL_NO_COMPARE_X_2_STATIC_FILTERS - Compare_x_2 + Compare_x_2 compare_x_2_object() const { return Compare_x_2(); } -Compare_y_2 + Compare_y_2 compare_y_2_object() const { return Compare_y_2(); } #endif // NOT CGAL_NO_COMPARE_Y_2_STATIC_FILTERS #ifndef CGAL_NO_IS_DEGENERATE_3_STATIC_FILTERS - Is_degenerate_3 + Is_degenerate_3 is_degenerate_3_object() const { return Is_degenerate_3(); } #endif // NOT CGAL_NO_IS_DEGENERATE_3_STATIC_FILTERS @@ -191,7 +183,12 @@ Compare_y_2 compare_squared_radius_3_object() const { return Compare_squared_radius_3(); } - Power_side_of_oriented_power_sphere_3 power_side_of_oriented_power_sphere_3_object() const + Coplanar_3 + coplanar_3_object() const + { return Coplanar_3(); } + + Power_side_of_oriented_power_sphere_3 + power_side_of_oriented_power_sphere_3_object() const { return Power_side_of_oriented_power_sphere_3();} Compare_weighted_squared_radius_3 diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp index 240632ee690..1ce5501e5cb 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp @@ -2,12 +2,13 @@ #include #include +#include #include typedef CGAL::Exact_predicates_inexact_constructions_kernel K; -typedef CGAL::Surface_mesh Mesh; -typedef boost::graph_traits::face_descriptor face_descriptor; +typedef CGAL::Surface_mesh Mesh; +typedef boost::graph_traits::face_descriptor face_descriptor; namespace PMP = CGAL::Polygon_mesh_processing; @@ -20,20 +21,17 @@ int main(int argc, char* argv[]) if (!input || !(input >> mesh) || !CGAL::is_triangle_mesh(mesh)) { std::cerr << "Not a valid input file." << std::endl; - return 1; + return EXIT_FAILURE; } - bool intersecting = PMP::does_self_intersect(mesh, - PMP::parameters::vertex_point_map(get(CGAL::vertex_point, mesh))); + bool intersecting = PMP::does_self_intersect( + mesh, CGAL::parameters::vertex_point_map(get(CGAL::vertex_point, mesh))); + + std::cout << (intersecting ? "There are self-intersections." : "There is no self-intersection.") << std::endl; - std::cout - << (intersecting ? "There are self-intersections." : "There is no self-intersection.") - << std::endl; - std::vector > intersected_tris; - PMP::self_intersections(faces(mesh),mesh, std::back_inserter(intersected_tris)); - + PMP::self_intersections(faces(mesh), mesh, std::back_inserter(intersected_tris)); std::cout << intersected_tris.size() << " pairs of triangles intersect." << std::endl; - - return 0; + + return EXIT_SUCCESS; } diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index 156569ad1ab..0aef552862a 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -57,10 +57,9 @@ #endif namespace CGAL { - namespace internal { - template ::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; typedef typename boost::property_map::const_type Ppmap; // members @@ -97,7 +96,7 @@ struct Intersect_facets void operator()(const Box* b, const Box* c) const { halfedge_descriptor h = halfedge(b->info(), m_tmesh); - halfedge_descriptor g = halfedge(c->info(),m_tmesh); + halfedge_descriptor g = halfedge(c->info(), m_tmesh); vertex_descriptor hv[3], gv[3]; hv[0] = target(h, m_tmesh); @@ -116,10 +115,10 @@ struct Intersect_facets if(face(opp_h, m_tmesh) == c->info()){ // there is an intersection if the four points are coplanar and // the triangles overlap - get(m_vpmap, hv[i]); - get(m_vpmap, hv[(i + 1) % 3]); - get(m_vpmap, hv[(i + 2) % 3]); - get(m_vpmap, target(next(opp_h, m_tmesh), m_tmesh)); + get(m_vpmap, hv[i]); + get(m_vpmap, hv[(i + 1) % 3]); + get(m_vpmap, hv[(i + 2) % 3]); + get(m_vpmap, target(next(opp_h, m_tmesh), m_tmesh)); if(CGAL::coplanar(get(m_vpmap, hv[i]), get(m_vpmap, hv[(i+1)%3]), @@ -158,7 +157,8 @@ struct Intersect_facets } if(shared){ // found shared vertex: - assert(hv[i] == gv[j]); + CGAL_assertion(hv[i] == gv[j]); + // geometric check if the opposite segments intersect the triangles Triangle t1 = triangle_functor( get(m_vpmap, hv[0]), get(m_vpmap, hv[1]), @@ -223,18 +223,17 @@ struct AllPairs AllPairs(const FacePairs& face_pairs, std::vector& dointersect, const TM& tmesh, VertexPointMap vpmap, const Kernel& kernel) - : m_tmesh(tmesh) - , m_vpmap(vpmap) - , face_pairs(face_pairs) - , dointersect(dointersect) - , triangle_functor(kernel.construct_triangle_3_object()) - , do_intersect_3_functor(kernel.do_intersect_3_object()) + : m_tmesh(tmesh), + m_vpmap(vpmap), + face_pairs(face_pairs), + dointersect(dointersect), + triangle_functor(kernel.construct_triangle_3_object()), + do_intersect_3_functor(kernel.do_intersect_3_object()) {} void operator()(const tbb::blocked_range &r) const { for (std::size_t ri = r.begin(); ri != r.end(); ++ri) { - this->operator()(ri); } } @@ -261,10 +260,10 @@ struct AllPairs if(face(opp_h, m_tmesh) == ff.second){ // there is an intersection if the four points are coplanar and // the triangles overlap - get(m_vpmap, hv[i]); - get(m_vpmap, hv[(i + 1) % 3]); - get(m_vpmap, hv[(i + 2) % 3]); - get(m_vpmap, target(next(opp_h, m_tmesh), m_tmesh)); + get(m_vpmap, hv[i]); + get(m_vpmap, hv[(i + 1) % 3]); + get(m_vpmap, hv[(i + 2) % 3]); + get(m_vpmap, target(next(opp_h, m_tmesh), m_tmesh)); if(CGAL::coplanar(get(m_vpmap, hv[i]), get(m_vpmap, hv[(i+1)%3]), @@ -303,7 +302,8 @@ struct AllPairs } if(shared){ // found shared vertex: - assert(hv[i] == gv[j]); + CGAL_assertion(hv[i] == gv[j]); + // geometric check if the opposite segments intersect the triangles Triangle t1 = triangle_functor( get(m_vpmap, hv[0]), get(m_vpmap, hv[1]), @@ -328,7 +328,7 @@ struct AllPairs Triangle t2 = triangle_functor( get(m_vpmap, gv[0]), get(m_vpmap, gv[1]), get(m_vpmap, gv[2])); - dointersect[ri] = do_intersect_3_functor(t1, t2); + dointersect[ri] = do_intersect_3_functor(t1, t2); } }; @@ -339,17 +339,13 @@ struct All_faces_filter { mutable OutputIterator m_iterator; - - All_faces_filter(OutputIterator it) - : m_iterator(it) - {} + All_faces_filter(OutputIterator it) : m_iterator(it) {} template void operator()(const Box* b, const Box* c) const { *m_iterator ++ = std::make_pair(b->info(), c->info()); - - } // end operator () + } }; @@ -414,19 +410,21 @@ self_intersections( const FaceRange& face_range, { CGAL_precondition(CGAL::is_triangle_mesh(tmesh)); - typedef TriangleMesh TM; - typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef TriangleMesh TM; + typedef typename boost::graph_traits::face_descriptor face_descriptor; typedef typename CGAL::Box_intersection_d::Box_with_info_d Box; - // make one box per face - std::vector boxes; - boxes.reserve( std::distance( boost::begin(face_range), boost::end(face_range) ) - ); + typedef typename GetGeomTraits::type GeomTraits; + GeomTraits gt = parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits), GeomTraits()); typedef typename GetVertexPointMap::const_type VertexPointMap; VertexPointMap vpmap = parameters::choose_parameter(parameters::get_parameter(np, internal_np::vertex_point), get_const_property_map(boost::vertex_point, tmesh)); + // make one box per face + std::vector boxes; + boxes.reserve(std::distance(boost::begin(face_range), boost::end(face_range))); + for(face_descriptor f : face_range) { typename boost::property_traits::reference @@ -439,6 +437,7 @@ self_intersections( const FaceRange& face_range, else boxes.push_back(Box(p.bbox() + q.bbox() + r.bbox(), f)); } + // generate box pointers std::vector box_ptr; box_ptr.reserve(boxes.size()); @@ -450,31 +449,22 @@ self_intersections( const FaceRange& face_range, CGAL_static_assertion_msg (!(boost::is_convertible::value), "Parallel_tag is enabled but TBB is unavailable."); #else - - if (boost::is_convertible::value) + if (boost::is_convertible::value) { // (Parallel version of the code) // (A) Sequentially write all pairs of faces with intersecting bbox into a std::vector std::ptrdiff_t cutoff = 2000; - typedef tbb::concurrent_vector >FacePairs; + typedef tbb::concurrent_vector >FacePairs; typedef std::back_insert_iterator FacePairsI; FacePairs face_pairs; CGAL::internal::All_faces_filter all_faces_filter(std::back_inserter(face_pairs)); - CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(),all_faces_filter,cutoff); + CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(), all_faces_filter, cutoff); // (B) Parallel: perform the geometric tests - typedef typename GetGeomTraits::type GeomTraits; - - std::vector dointersect(face_pairs.size(),0); - - CGAL::internal::AllPairs - all_pairs(face_pairs, - dointersect, - tmesh, - vpmap, - parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits), GeomTraits())); + std::vector dointersect(face_pairs.size(), 0); + CGAL::internal::AllPairs all_pairs(face_pairs, dointersect, tmesh, vpmap, gt); tbb::parallel_for(tbb::blocked_range(0, face_pairs.size()), all_pairs); @@ -488,13 +478,11 @@ self_intersections( const FaceRange& face_range, #endif // (Sequential version of the code) compute self-intersections filtered out by boxes - typedef typename GetGeomTraits::type GeomTraits; - CGAL::internal::Intersect_facets - intersect_facets(tmesh, out, vpmap, - parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits), GeomTraits())); + CGAL::internal::Intersect_facets + intersect_facets(tmesh, out, vpmap, gt); std::ptrdiff_t cutoff = 2000; - CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(),intersect_facets,cutoff); + CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(),intersect_facets, cutoff); return intersect_facets.m_iterator; } @@ -508,8 +496,7 @@ self_intersections(const FaceRange& face_range, const TriangleMesh& tmesh, OutputIterator out) { - return self_intersections(face_range, tmesh, out, - CGAL::Polygon_mesh_processing::parameters::all_default()); + return self_intersections(face_range, tmesh, out, CGAL::parameters::all_default()); } /// \endcond @@ -547,10 +534,10 @@ self_intersections(const FaceRange& face_range, * * @return `out` */ -template +template OutputIterator self_intersections(const TriangleMesh& tmesh, OutputIterator out, @@ -568,8 +555,6 @@ self_intersections(const TriangleMesh& tmesh, OutputIterator out) } /// \endcond - - /** * \ingroup PMP_intersection_grp * tests if a triangulated surface mesh self-intersects. @@ -594,11 +579,10 @@ self_intersections(const TriangleMesh& tmesh, OutputIterator out) * @return `true` if `tmesh` self-intersects */ template -bool does_self_intersect(const TriangleMesh& tmesh - , const CGAL_PMP_NP_CLASS& np) + class TriangleMesh, + class CGAL_PMP_NP_TEMPLATE_PARAMETERS> +bool does_self_intersect(const TriangleMesh& tmesh, + const CGAL_PMP_NP_CLASS& np) { CGAL_precondition(CGAL::is_triangle_mesh(tmesh)); @@ -641,8 +625,7 @@ bool does_self_intersect(const TriangleMesh& tmesh template + class NamedParameters> bool does_self_intersect(const FaceRange& face_range, const TriangleMesh& tmesh, const NamedParameters& np) @@ -664,18 +647,15 @@ bool does_self_intersect(const FaceRange& face_range, template bool does_self_intersect(const TriangleMesh& tmesh) { - return does_self_intersect(tmesh, - CGAL::Polygon_mesh_processing::parameters::all_default()); + return does_self_intersect(tmesh, CGAL::parameters::all_default()); } template bool does_self_intersect(const FaceRange& face_range, const TriangleMesh& tmesh) { - return does_self_intersect(face_range, tmesh, - CGAL::Polygon_mesh_processing::parameters::all_default()); + return does_self_intersect(face_range, tmesh, CGAL::parameters::all_default()); } - /// \endcond }// end namespace Polygon_mesh_processing diff --git a/STL_Extension/include/CGAL/tags.h b/STL_Extension/include/CGAL/tags.h index 2b88992794b..8feef206784 100644 --- a/STL_Extension/include/CGAL/tags.h +++ b/STL_Extension/include/CGAL/tags.h @@ -63,7 +63,6 @@ typedef CGAL::Parallel_tag Parallel_if_available_tag; #else typedef CGAL::Sequential_tag Parallel_if_available_tag; #endif - // A function that asserts a specific compile time tag // forcing its two arguments to have equal type. From 9ef1c976c61ccdac5269f5984944deb3c62d4f6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 19 Nov 2019 12:51:36 +0100 Subject: [PATCH 054/185] Use one of the tests of self_intersection.h to test the parallel tags --- .../self_intersection_surface_mesh_test.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/self_intersection_surface_mesh_test.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/self_intersection_surface_mesh_test.cpp index 3addd6c9323..6d468a267d1 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/self_intersection_surface_mesh_test.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/self_intersection_surface_mesh_test.cpp @@ -1,16 +1,16 @@ -#include -#include -#include -#include - #include #include #include #include - +#include #include +#include +#include +#include +#include + typedef CGAL::Exact_predicates_inexact_constructions_kernel Epic; typedef CGAL::Exact_predicates_exact_constructions_kernel Epec; @@ -35,17 +35,17 @@ test_self_intersections(const char* filename, const bool expected) timer.start(); std::vector > intersected_tris; - CGAL::Polygon_mesh_processing::self_intersections( + CGAL::Polygon_mesh_processing::self_intersections( m, std::back_inserter(intersected_tris), - CGAL::Polygon_mesh_processing::parameters::vertex_index_map(get(CGAL::vertex_point, m))); + CGAL::parameters::vertex_index_map(get(CGAL::vertex_point, m))); bool intersecting_1 = !intersected_tris.empty(); std::cout << "self_intersections test took " << timer.time() << " sec." << std::endl; std::cout << intersected_tris.size() << " pairs of triangles are intersecting." << std::endl; timer.reset(); - bool intersecting_2 = CGAL::Polygon_mesh_processing::does_self_intersect(m, + bool intersecting_2 = CGAL::Polygon_mesh_processing::does_self_intersect(m, CGAL::Polygon_mesh_processing::parameters::vertex_index_map(get(CGAL::vertex_point, m))); std::cout << "does_self_intersect test took " << timer.time() << " sec." << std::endl; From b7d20e00332b322d650bf5b73a2467ca5f4b297c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 19 Nov 2019 14:40:30 +0100 Subject: [PATCH 055/185] Move range splitting higher to also parallelize 'box_intersection_d()' --- .../include/CGAL/box_intersection_d.h | 291 ++++++++++-------- 1 file changed, 158 insertions(+), 133 deletions(-) diff --git a/Box_intersection_d/include/CGAL/box_intersection_d.h b/Box_intersection_d/include/CGAL/box_intersection_d.h index 7521802ba49..0f4088b50b6 100644 --- a/Box_intersection_d/include/CGAL/box_intersection_d.h +++ b/Box_intersection_d/include/CGAL/box_intersection_d.h @@ -26,17 +26,103 @@ #include #include +#include #ifdef CGAL_LINKED_WITH_TBB #include #endif +#include #include namespace CGAL { +namespace internal { // Generic call with custom predicate traits parameter. -template< class RandomAccessIter1, class RandomAccessIter2, +template< class ConcurrencyTag, + class RandomAccessIter1, class RandomAccessIter2, + class Callback, class Traits > +void box_intersection_segment_tree_d( + RandomAccessIter1 begin1, RandomAccessIter1 end1, + RandomAccessIter2 begin2, RandomAccessIter2 end2, + Callback callback, + const Traits& traits, + const std::ptrdiff_t cutoff, + const bool in_order) +{ + typedef typename Traits::NT NT; + + CGAL_assertion(Traits::dimension() > 0); + const int dim = Traits::dimension() - 1; + + const NT inf = Box_intersection_d::box_limits::inf(); + const NT sup = Box_intersection_d::box_limits::sup(); + +#ifndef CGAL_LINKED_WITH_TBB + CGAL_static_assertion_msg (!(boost::is_convertible::value), + "Parallel_tag is enabled but TBB is unavailable."); +#else // CGAL_LINKED_WITH_TBB + if(boost::is_convertible::value) + { + typename std::iterator_traits::difference_type r1hs = std::distance(begin1, end1) / 2; + typename std::iterator_traits::difference_type r2hs = std::distance(begin2, end2) / 2; + + // TODO: Check which of the two following approaches is better + // The first one makes three copies of the vector and performs four parallel tasks + // The second one makes one copy, but must perform two times two parallel tasks (can't + // do all four at the same time otherwise the sort / split will conflict) +#ifdef CGAL_BOX_INTER_FOUR_RANGES + typedef typename std::iterator_traits::value_type val_t; + + std::vector< val_t> r3( begin1, end1); + std::vector< val_t> r4( begin2, end2); + + RandomAccessIter1 mid1 = begin1; + std::advance(mid1, r1hs); + RandomAccessIter2 mid2 = begin2; + std::advance(mid2, r2hs); + typename std::vector< val_t>::iterator mid3 = r3.begin(); + std::advance(mid3, r1hs); + typename std::vector< val_t>::iterator mid4 = r4.begin(); + std::advance(mid4, r2hs); + + tbb::parallel_invoke([&]{ Box_intersection_d::segment_tree( begin1, mid1, begin2, mid2, inf, sup, + callback, traits, cutoff, dim, in_order); }, + [&]{ Box_intersection_d::segment_tree( mid1, end1, mid2, end2, inf, sup, + callback, traits, cutoff, dim, in_order); }, + [&]{ Box_intersection_d::segment_tree( r3.begin(), mid3, mid4, r4.end(), inf, sup, + callback, traits, cutoff, dim, in_order); }, + [&]{ Box_intersection_d::segment_tree( mid3, r3.end(), r4.begin(), mid4, inf, sup, + callback, traits, cutoff, dim, in_order); } ); +#else // CGAL_BOX_INTER_FOUR_RANGES + RandomAccessIter1 mid1 = begin1; + std::advance(mid1, r1hs); + RandomAccessIter2 mid2 = begin2; + std::advance(mid2, r2hs); + + tbb::parallel_invoke([&]{ Box_intersection_d::segment_tree( begin1, mid1, begin2, mid2, inf, sup, + callback, traits, cutoff, dim, in_order); }, + [&]{ Box_intersection_d::segment_tree( mid1, end1, mid2, end2, inf, sup, + callback, traits, cutoff, dim, in_order); } ); + tbb::parallel_invoke([&]{ Box_intersection_d::segment_tree( begin1, mid1, mid2, end2, inf, sup, + callback, traits, cutoff, dim, in_order); }, + [&]{ Box_intersection_d::segment_tree( mid1, end1, begin2, mid2, inf, sup, + callback, traits, cutoff, dim, in_order); } ); + +#endif // CGAL_BOX_INTER_FOUR_RANGES + } + else +#endif // CGAL_LINKED_WITH_TBB + { + Box_intersection_d::segment_tree(begin1, end1, begin2, end2, inf, sup, callback, traits, cutoff, dim, in_order); + } +} + +} // namespace internal + +// Generic call with custom predicate traits parameter. +template< class ConcurrencyTag = Sequential_tag, + class RandomAccessIter1, class RandomAccessIter2, class Callback, class BoxPredicateTraits > void box_intersection_custom_predicates_d( RandomAccessIter1 begin1, RandomAccessIter1 end1, @@ -46,24 +132,15 @@ void box_intersection_custom_predicates_d( std::ptrdiff_t cutoff = 10, Box_intersection_d::Setting setting = Box_intersection_d::BIPARTITE) { - typedef BoxPredicateTraits Traits; - typedef typename Traits::NT NT; - CGAL_assertion( Traits::dimension() > 0 ); - const int dim = Traits::dimension() - 1; - const NT inf = Box_intersection_d::box_limits::inf(); - const NT sup = Box_intersection_d::box_limits::sup(); - Box_intersection_d::segment_tree(begin1, end1, begin2, end2, - inf, sup, callback, traits, cutoff, dim, true); - if(setting == Box_intersection_d::BIPARTITE) - Box_intersection_d::segment_tree(begin2, end2, begin1, end1, - inf, sup, callback, traits, cutoff, dim, false); - + internal::box_intersection_segment_tree_d(begin1, end1, begin2, end2, callback, traits, cutoff, true); + if(setting == Box_intersection_d::BIPARTITE) + internal::box_intersection_segment_tree_d(begin2, end2, begin1, end1, callback, traits, cutoff, false); } - // Generic call with box traits parameter. // - make all default parameters explicit overloads (workaround) -template< class RandomAccessIter1, class RandomAccessIter2, +template< class ConcurrencyTag = Sequential_tag, + class RandomAccessIter1, class RandomAccessIter2, class Callback, class BoxTraits > void box_intersection_d( RandomAccessIter1 begin1, RandomAccessIter1 end1, @@ -74,18 +151,19 @@ void box_intersection_d( Box_intersection_d::Topology topology, Box_intersection_d::Setting setting) { - if (topology == Box_intersection_d::CLOSED) { - typedef Box_intersection_d::Predicate_traits_d Traits; - box_intersection_custom_predicates_d(begin1, end1, begin2, end2, - callback, Traits(), cutoff, setting); - } else { - typedef Box_intersection_d::Predicate_traits_d Traits; - box_intersection_custom_predicates_d(begin1, end1, begin2, end2, - callback, Traits(), cutoff, setting); - } + if (topology == Box_intersection_d::CLOSED) { + typedef Box_intersection_d::Predicate_traits_d Traits; + box_intersection_custom_predicates_d(begin1, end1, begin2, end2, + callback, Traits(), cutoff, setting); + } else { + typedef Box_intersection_d::Predicate_traits_d Traits; + box_intersection_custom_predicates_d(begin1, end1, begin2, end2, + callback, Traits(), cutoff, setting); + } } -template< class RandomAccessIter1, class RandomAccessIter2, +template< class ConcurrencyTag = Sequential_tag, + class RandomAccessIter1, class RandomAccessIter2, class Callback, class BoxTraits > void box_intersection_d( RandomAccessIter1 begin1, RandomAccessIter1 end1, @@ -93,35 +171,39 @@ void box_intersection_d( Callback callback, BoxTraits box_traits, std::ptrdiff_t cutoff, Box_intersection_d::Topology topology) { - box_intersection_d( begin1, end1, begin2, end2, callback, box_traits, - cutoff, topology, Box_intersection_d::BIPARTITE); + box_intersection_d( begin1, end1, begin2, end2, callback, box_traits, + cutoff, topology, Box_intersection_d::BIPARTITE); } -template< class RandomAccessIter1, class RandomAccessIter2, +template< class ConcurrencyTag = Sequential_tag, + class RandomAccessIter1, class RandomAccessIter2, class Callback, class BoxTraits > void box_intersection_d( RandomAccessIter1 begin1, RandomAccessIter1 end1, RandomAccessIter2 begin2, RandomAccessIter2 end2, Callback callback, BoxTraits box_traits, std::ptrdiff_t cutoff) { - box_intersection_d( begin1, end1, begin2, end2, callback, box_traits, - cutoff, Box_intersection_d::CLOSED, - Box_intersection_d::BIPARTITE); + box_intersection_d( begin1, end1, begin2, end2, callback, box_traits, + cutoff, Box_intersection_d::CLOSED, + Box_intersection_d::BIPARTITE); } -template< class RandomAccessIter1, class RandomAccessIter2, + +template< class ConcurrencyTag = Sequential_tag, + class RandomAccessIter1, class RandomAccessIter2, class Callback, class BoxTraits > void box_intersection_d( RandomAccessIter1 begin1, RandomAccessIter1 end1, RandomAccessIter2 begin2, RandomAccessIter2 end2, Callback callback, BoxTraits box_traits) { - box_intersection_d( begin1, end1, begin2, end2, callback, box_traits, - 10, Box_intersection_d::CLOSED, - Box_intersection_d::BIPARTITE); + box_intersection_d( begin1, end1, begin2, end2, callback, box_traits, + 10, Box_intersection_d::CLOSED, + Box_intersection_d::BIPARTITE); } // Specialized call with default box traits. // - make all default parameters explicit overloads (workaround) -template< class RandomAccessIter1, class RandomAccessIter2, class Callback > +template< class ConcurrencyTag = Sequential_tag, + class RandomAccessIter1, class RandomAccessIter2, class Callback > void box_intersection_d( RandomAccessIter1 begin1, RandomAccessIter1 end1, RandomAccessIter2 begin2, RandomAccessIter2 end2, @@ -129,52 +211,58 @@ void box_intersection_d( Box_intersection_d::Topology topology, Box_intersection_d::Setting setting) { - typedef typename std::iterator_traits::value_type val_t; - typedef Box_intersection_d::Box_traits_d< val_t> Box_traits; - box_intersection_d( begin1, end1, begin2, end2, callback, Box_traits(), - cutoff, topology, setting); + typedef typename std::iterator_traits::value_type val_t; + typedef Box_intersection_d::Box_traits_d< val_t> Box_traits; + + box_intersection_d( begin1, end1, begin2, end2, callback, Box_traits(), + cutoff, topology, setting); } -template< class RandomAccessIter1, class RandomAccessIter2, class Callback > +template< class ConcurrencyTag = Sequential_tag, + class RandomAccessIter1, class RandomAccessIter2, class Callback > void box_intersection_d( RandomAccessIter1 begin1, RandomAccessIter1 end1, RandomAccessIter2 begin2, RandomAccessIter2 end2, Callback callback, std::ptrdiff_t cutoff, Box_intersection_d::Topology topology) { - typedef typename std::iterator_traits::value_type val_t; - typedef Box_intersection_d::Box_traits_d< val_t> Box_traits; - box_intersection_d( begin1, end1, begin2, end2, callback, Box_traits(), - cutoff, topology, Box_intersection_d::BIPARTITE); + typedef typename std::iterator_traits::value_type val_t; + typedef Box_intersection_d::Box_traits_d< val_t> Box_traits; + + box_intersection_d( begin1, end1, begin2, end2, callback, Box_traits(), + cutoff, topology, Box_intersection_d::BIPARTITE); } -template< class RandomAccessIter1, class RandomAccessIter2, class Callback > +template< class ConcurrencyTag = Sequential_tag, + class RandomAccessIter1, class RandomAccessIter2, class Callback > void box_intersection_d( RandomAccessIter1 begin1, RandomAccessIter1 end1, RandomAccessIter2 begin2, RandomAccessIter2 end2, Callback callback, std::ptrdiff_t cutoff) { - typedef typename std::iterator_traits::value_type val_t; - typedef Box_intersection_d::Box_traits_d< val_t> Box_traits; - box_intersection_d( begin1, end1, begin2, end2, callback, Box_traits(), - cutoff, Box_intersection_d::CLOSED, - Box_intersection_d::BIPARTITE); + typedef typename std::iterator_traits::value_type val_t; + typedef Box_intersection_d::Box_traits_d< val_t> Box_traits; + box_intersection_d( begin1, end1, begin2, end2, callback, Box_traits(), + cutoff, Box_intersection_d::CLOSED, + Box_intersection_d::BIPARTITE); } -template< class RandomAccessIter1, class RandomAccessIter2, class Callback > +template< class ConcurrencyTag = Sequential_tag, + class RandomAccessIter1, class RandomAccessIter2, class Callback > void box_intersection_d( RandomAccessIter1 begin1, RandomAccessIter1 end1, RandomAccessIter2 begin2, RandomAccessIter2 end2, Callback callback) { - typedef typename std::iterator_traits::value_type val_t; - typedef Box_intersection_d::Box_traits_d< val_t> Box_traits; - box_intersection_d( begin1, end1, begin2, end2, callback, Box_traits(), - 10, Box_intersection_d::CLOSED, - Box_intersection_d::BIPARTITE); + typedef typename std::iterator_traits::value_type val_t; + typedef Box_intersection_d::Box_traits_d< val_t> Box_traits; + box_intersection_d( begin1, end1, begin2, end2, callback, Box_traits(), + 10, Box_intersection_d::CLOSED, + Box_intersection_d::BIPARTITE); } // Generic call with box traits parameter, specialized for self-intersection. // - make all default parameters explicit overloads (workaround) -template< class ConcurrencyTag = Sequential_tag, class RandomAccessIter, class Callback, class BoxTraits > +template< class ConcurrencyTag = Sequential_tag, + class RandomAccessIter, class Callback, class BoxTraits > void box_self_intersection_d( RandomAccessIter begin, RandomAccessIter end, Callback callback, @@ -182,83 +270,19 @@ void box_self_intersection_d( std::ptrdiff_t cutoff, Box_intersection_d::Topology topology) { -#ifndef CGAL_LINKED_WITH_TBB - CGAL_static_assertion_msg (!(boost::is_convertible::value), - "Parallel_tag is enabled but TBB is unavailable."); -#else // CGAL_LINKED_WITH_TBB - if(boost::is_convertible::value) - { - // Copying rather than calling 'box_intersection_d(begin, end, begin, end, ...' - // is necessary because the 'std::partition' and range splits on the first range - // would be messed up by sorts on the second range otherwise. - typedef typename std::iterator_traits::value_type val_t; - std::vector< val_t> i( begin, end); + // Copying rather than calling 'box_intersection_d(begin, end, begin, end, ...' + // is necessary because the 'std::partition' and range splits on the first range + // would be messed up by sorts on the second range otherwise. + typedef typename std::iterator_traits::value_type val_t; + std::vector< val_t> i( begin, end); - // TODO: Check which of the two following approaches is better - // The first one makes three copies of the vector and performs four parallel tasks - // The second one makes one copy, but must perform two times two parallel tasks (can't - // do all four at the same time otherwise the sort / split will conflict) -#ifdef CGAL_BOX_INTER_FOUR_RANGES - std::vector< val_t> j( begin, end); - std::vector< val_t> k( begin, end); - - RandomAccessIter mid = begin; - std::advance(mid, std::distance(begin,end)/2); - typename std::vector< val_t>::iterator midi = i.begin(); - std::advance(midi, std::distance(begin,end)/2); - typename std::vector< val_t>::iterator midj = j.begin(); - std::advance(midj, std::distance(begin,end)/2); - typename std::vector< val_t>::iterator midk = k.begin(); - std::advance(midk, std::distance(begin,end)/2); - - tbb::parallel_invoke([&]{ box_intersection_d( begin, mid, i.begin(), midi, - callback, box_traits, cutoff, topology, - Box_intersection_d::COMPLETE); }, - [&]{ box_intersection_d( mid, end, midi, i.end(), - callback, box_traits, cutoff, topology, - Box_intersection_d::COMPLETE); }, - [&]{ box_intersection_d( j.begin(), midj, midk, k.end(), - callback, box_traits, cutoff, topology, - Box_intersection_d::COMPLETE); }, - [&]{ box_intersection_d( midj, j.end(), k.begin(), midk, - callback, box_traits, cutoff, topology, - Box_intersection_d::COMPLETE); } ); -#else // CGAL_BOX_INTER_FOUR_RANGES - RandomAccessIter mid = begin; - std::advance(mid, std::distance(begin,end)/2); - typename std::vector< val_t>::iterator midi = i.begin(); - std::advance(midi, std::distance(begin,end)/2); - - tbb::parallel_invoke([&]{ box_intersection_d( begin, mid, i.begin(), midi, - callback, box_traits, cutoff, topology, - Box_intersection_d::COMPLETE); }, - [&]{ box_intersection_d( mid, end, midi, i.end(), - callback, box_traits, cutoff, topology, - Box_intersection_d::COMPLETE); } ); - tbb::parallel_invoke([&]{box_intersection_d( begin, mid, midi, i.end(), - callback, box_traits, cutoff, topology, - Box_intersection_d::COMPLETE); }, - [&]{ box_intersection_d( mid, end, i.begin(), midi, - callback, box_traits, cutoff, topology, - Box_intersection_d::COMPLETE); } ); -#endif // CGAL_BOX_INTER_FOUR_RANGES - } - else -#endif // CGAL_LINKED_WITH_TBB - { - // Copying rather than calling 'box_intersection_d(begin, end, begin, end, ...' - // is necessary because the 'std::partition' and range splits on the first range - // would be messed up by sorts on the second range otherwise. - typedef typename std::iterator_traits::value_type val_t; - std::vector< val_t> i( begin, end); - - box_intersection_d( begin, end, i.begin(), i.end(), - callback, box_traits, cutoff, topology, - Box_intersection_d::COMPLETE); - } + box_intersection_d( begin, end, i.begin(), i.end(), + callback, box_traits, cutoff, topology, + Box_intersection_d::COMPLETE); } -template< class ConcurrencyTag = Sequential_tag, class RandomAccessIter, class Callback, class BoxTraits > +template< class ConcurrencyTag = Sequential_tag, + class RandomAccessIter, class Callback, class BoxTraits > void box_self_intersection_d( RandomAccessIter begin, RandomAccessIter end, Callback callback, @@ -269,7 +293,8 @@ void box_self_intersection_d( Box_intersection_d::CLOSED); } -template< class ConcurrencyTag = Sequential_tag, class RandomAccessIter, class Callback, class BoxTraits > +template< class ConcurrencyTag = Sequential_tag, + class RandomAccessIter, class Callback, class BoxTraits > void box_self_intersection_d( RandomAccessIter begin, RandomAccessIter end, Callback callback, From 52ce0b6ac41d993708e6b0d44a143574bed4698c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 19 Nov 2019 16:40:11 +0100 Subject: [PATCH 056/185] Change Box_with_info to use the policy ID_EXPLICIT by default ID_FROM_BOX_ADDRESS does not work when you pass a range of boxes by value and not by pointers. Since doing that while using ID_FROM_BOX_ADDRESS is completely silent (no errors despite not being compatible), this is super dangerous. Besides, the Box_d has default policy ID_EXPLICIT, so it should have been that in the first place. --- .../CGAL/Box_intersection_d/Box_with_info_d.h | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Box_intersection_d/include/CGAL/Box_intersection_d/Box_with_info_d.h b/Box_intersection_d/include/CGAL/Box_intersection_d/Box_with_info_d.h index 2a53c9db171..990f3dd5fbb 100644 --- a/Box_intersection_d/include/CGAL/Box_intersection_d/Box_with_info_d.h +++ b/Box_intersection_d/include/CGAL/Box_intersection_d/Box_with_info_d.h @@ -16,34 +16,34 @@ #include - #include #include namespace CGAL { - namespace Box_intersection_d { -template -class Box_with_info_d : public Box_d< NT_, N, ID_FROM_BOX_ADDRESS> { +template +class Box_with_info_d + : public Box_d< NT_, N, IdPolicy> +{ protected: Info_ m_info; public: - typedef Box_d< NT_, N, ID_FROM_BOX_ADDRESS> Base; - typedef NT_ NT; - typedef Info_ Info; + typedef Box_d< NT_, N, ID_EXPLICIT> Base; + typedef NT_ NT; + typedef Info_ Info; + Box_with_info_d() {} Box_with_info_d( Info h) : m_info(h) {} Box_with_info_d( bool complete, Info h): Base(complete), m_info(h) {} Box_with_info_d(NT l[N], NT h[N], Info n) : Base( l, h), m_info(n) {} Box_with_info_d( const Bbox_2& b, Info h) : Base( b), m_info(h) {} Box_with_info_d( const Bbox_3& b, Info h) : Base( b), m_info(h) {} + Info info() const { return m_info; } }; -} // end namespace Box_intersection_d +} // namespace Box_intersection_d +} // namespace CGAL - -} //namespace CGAL - -#endif +#endif // CGAL_BOX_INTERSECTION_D_BOX_WITH_INFO_D_H From b6dd62be5213706acd93cbbd9ad965eaad0183ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 19 Nov 2019 17:06:47 +0100 Subject: [PATCH 057/185] Use ID_FROM_BOX_ADDRESS in Box_with_info_d where safe That is, where we are passing box ranges by pointer. See also 52ce0b6ac41d993708e6b0d44a143574bed4698c --- ...ABB_traversal_traits_with_transformation.h | 1 - .../Corefinement/intersection_callbacks.h | 16 +++++++++---- .../internal/Corefinement/intersection_impl.h | 4 ++-- .../internal/repair_extra.h | 3 ++- .../Polygon_mesh_processing/intersection.h | 24 +++++++++++++------ .../self_intersections.h | 4 +++- .../internal/validity.h | 6 +++-- 7 files changed, 40 insertions(+), 18 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_traversal_traits_with_transformation.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_traversal_traits_with_transformation.h index 30377ebaf9c..9e9f488824d 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_traversal_traits_with_transformation.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/AABB_traversal_traits_with_transformation.h @@ -26,7 +26,6 @@ #include #include -#include #include #include diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_callbacks.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_callbacks.h index 56ac7610d26..fdf829e5805 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_callbacks.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_callbacks.h @@ -15,7 +15,7 @@ #include - +#include #include #include #include @@ -38,7 +38,9 @@ protected: typedef boost::graph_traits Graph_traits; typedef typename Graph_traits::face_descriptor face_descriptor; typedef typename Graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename CGAL::Box_intersection_d::Box_with_info_d Box; + + typedef CGAL::Box_intersection_d::ID_FROM_BOX_ADDRESS Box_policy; + typedef CGAL::Box_intersection_d::Box_with_info_d Box; public: Collect_face_bbox_per_edge_bbox( @@ -80,9 +82,12 @@ protected: typedef boost::graph_traits Graph_traits; typedef typename Graph_traits::face_descriptor face_descriptor; typedef typename Graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename CGAL::Box_intersection_d::Box_with_info_d Box; + typedef typename boost::property_traits::reference Point; + typedef CGAL::Box_intersection_d::ID_FROM_BOX_ADDRESS Box_policy; + typedef CGAL::Box_intersection_d::Box_with_info_d Box; + public: Collect_face_bbox_per_edge_bbox_with_coplanar_handling( const TriangleMesh& tm_faces, @@ -162,7 +167,10 @@ protected: typedef typename Graph_traits::face_descriptor face_descriptor; typedef typename Graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename Graph_traits::vertex_descriptor vertex_descriptor; - typedef typename CGAL::Box_intersection_d::Box_with_info_d Box; + + typedef CGAL::Box_intersection_d::ID_FROM_BOX_ADDRESS Box_policy; + typedef CGAL::Box_intersection_d::Box_with_info_d Box; + typedef typename boost::property_traits::reference Point; bool is_edge_target_incident_to_face(halfedge_descriptor hd, diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_impl.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_impl.h index 715dea7057b..0f2f9717be0 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_impl.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_impl.h @@ -18,7 +18,6 @@ #include #include -#include #include #include #include @@ -156,7 +155,8 @@ class Intersection_of_triangle_meshes typedef typename graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename graph_traits::vertex_descriptor vertex_descriptor; - typedef typename CGAL::Box_intersection_d::Box_with_info_d Box; + typedef CGAL::Box_intersection_d::ID_FROM_BOX_ADDRESS Box_policy; + typedef CGAL::Box_intersection_d::Box_with_info_d Box; typedef boost::unordered_set Face_set; typedef boost::unordered_map Edge_to_faces; diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/repair_extra.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/repair_extra.h index c1ee33318a1..0373aefbf8a 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/repair_extra.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/repair_extra.h @@ -110,7 +110,8 @@ void collect_close_stitchable_boundary_edges(PM& pm, typedef boost::unordered_map Halfedge_multiplicity; typedef std::vector > Halfedge_pairs; - typedef typename Box_intersection_d::Box_with_info_d Box; + typedef CGAL::Box_intersection_d::ID_FROM_BOX_ADDRESS Box_policy; + typedef CGAL::Box_intersection_d::Box_with_info_d Box; typedef Union_find UF_vertices; typedef std::map Handle_map; diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/intersection.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/intersection.h index 0d036f3522f..f564c26b304 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/intersection.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/intersection.h @@ -401,8 +401,10 @@ compute_face_face_intersection(const FaceRange& face_range1, typedef TriangleMesh TM; typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename CGAL::Box_intersection_d::Box_with_info_d Box; - + + typedef CGAL::Box_intersection_d::ID_FROM_BOX_ADDRESS Box_policy; + typedef CGAL::Box_intersection_d::Box_with_info_d Box; + CGAL::Bbox_3 b1 = CGAL::Polygon_mesh_processing::bbox(tm1, np1), b2 = CGAL::Polygon_mesh_processing::bbox(tm2, np2); @@ -543,7 +545,8 @@ compute_face_polyline_intersection( const FaceRange& face_range, std::vector faces; faces.reserve(std::distance( boost::begin(face_range), boost::end(face_range) )); - typedef typename CGAL::Box_intersection_d::Box_with_info_d Box; + typedef CGAL::Box_intersection_d::ID_FROM_BOX_ADDRESS Box_policy; + typedef CGAL::Box_intersection_d::Box_with_info_d Box; // make one box per facet std::vector boxes1; @@ -679,7 +682,8 @@ compute_face_polylines_intersection(const FaceRange& face_range, std::vector faces; faces.reserve(std::distance( boost::begin(face_range), boost::end(face_range) )); - typedef typename CGAL::Box_intersection_d::Box_with_info_d > Box; + typedef CGAL::Box_intersection_d::ID_FROM_BOX_ADDRESS Box_policy; + typedef CGAL::Box_intersection_d::Box_with_info_d, Box_policy> Box; // make one box per facet std::vector boxes1; @@ -773,7 +777,9 @@ compute_polyline_polyline_intersection(const Polyline& polyline1, OutputIterator out, const Kernel& K) { - typedef typename CGAL::Box_intersection_d::Box_with_info_d Box; + typedef CGAL::Box_intersection_d::ID_FROM_BOX_ADDRESS Box_policy; + typedef CGAL::Box_intersection_d::Box_with_info_d Box; + typedef typename Kernel::Point_3 Point; // make one box per facet std::vector boxes1; @@ -856,7 +862,9 @@ compute_polylines_polylines_intersection(const PolylineRange& polylines1, const Kernel& K) { //info.first is the index of the polyline in the range, info.second is the index of the point in the polyline - typedef typename CGAL::Box_intersection_d::Box_with_info_d > Box; + typedef CGAL::Box_intersection_d::ID_FROM_BOX_ADDRESS Box_policy; + typedef CGAL::Box_intersection_d::Box_with_info_d, Box_policy> Box; + typedef typename Kernel::Point_3 Point; typedef typename boost::range_value::type Polyline; @@ -1595,7 +1603,9 @@ OutputIterator intersecting_meshes(const TriangleMeshRange& range, bool report_overlap = choose_parameter(get_parameter(np, internal_np::overlap_test),false); - typedef CGAL::Box_intersection_d::Box_with_info_d Mesh_box; + typedef CGAL::Box_intersection_d::ID_FROM_BOX_ADDRESS Box_policy; + typedef CGAL::Box_intersection_d::Box_with_info_d Mesh_box; + std::vector boxes; boxes.reserve(std::distance(range.begin(), range.end())); diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index 0aef552862a..526f143235e 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -412,7 +412,9 @@ self_intersections( const FaceRange& face_range, typedef TriangleMesh TM; typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename CGAL::Box_intersection_d::Box_with_info_d Box; + + typedef CGAL::Box_intersection_d::ID_FROM_BOX_ADDRESS Box_policy; + typedef CGAL::Box_intersection_d::Box_with_info_d Box; typedef typename GetGeomTraits::type GeomTraits; GeomTraits gt = parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits), GeomTraits()); diff --git a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/internal/validity.h b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/internal/validity.h index 49b7895e507..cdf8ce2de80 100644 --- a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/internal/validity.h +++ b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/internal/validity.h @@ -113,7 +113,8 @@ class Intersect_facets typename Kernel::Construct_triangle_2 triangle_functor; typename Kernel::Do_intersect_2 do_intersect_2_functor; - typedef CGAL::Box_intersection_d::Box_with_info_d Box; + typedef CGAL::Box_intersection_d::ID_FROM_BOX_ADDRESS Box_policy; + typedef CGAL::Box_intersection_d::Box_with_info_d Box; const TriangleMesh& mesh; const VertexUVMap uvmap; @@ -250,7 +251,8 @@ bool is_one_to_one_mapping(const TriangleMesh& mesh, typedef typename Kernel::FT NT; typedef typename Kernel::Point_2 Point_2; - typedef CGAL::Box_intersection_d::Box_with_info_d Box; + typedef CGAL::Box_intersection_d::ID_FROM_BOX_ADDRESS Box_policy; + typedef CGAL::Box_intersection_d::Box_with_info_d Box; // Create the corresponding vector of bounding boxes std::vector boxes; From 41bb11cdee456a3a231bd1d9cf7d5b728727f200 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 19 Nov 2019 17:08:25 +0100 Subject: [PATCH 058/185] Make unique indentation style a little less unique (no real changes) --- .../include/CGAL/box_intersection_d.h | 43 ++++--- .../internal/Corefinement/intersection_impl.h | 9 +- .../internal/repair_extra.h | 1 - .../Polygon_mesh_processing/intersection.h | 112 ++++++------------ .../internal/validity.h | 3 +- 5 files changed, 64 insertions(+), 104 deletions(-) diff --git a/Box_intersection_d/include/CGAL/box_intersection_d.h b/Box_intersection_d/include/CGAL/box_intersection_d.h index 0f4088b50b6..cdbf058fcb6 100644 --- a/Box_intersection_d/include/CGAL/box_intersection_d.h +++ b/Box_intersection_d/include/CGAL/box_intersection_d.h @@ -6,7 +6,7 @@ // $URL$ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// +// // // Author(s) : Lutz Kettner // Andreas Meyer @@ -339,24 +339,23 @@ void box_self_intersection_d( Box_traits(), cutoff, topology ); } - // Generic call for trivial all-pairs algorithm with box traits parameter. // - make all default parameters explicit overloads (workaround) template< class ForwardIter1, class ForwardIter2, class Callback, class BoxTraits > -void box_intersection_all_pairs_d( +void box_intersection_all_pairs_d( ForwardIter1 begin1, ForwardIter1 end1, ForwardIter2 begin2, ForwardIter2 end2, Callback callback, BoxTraits) { typedef Box_intersection_d::Predicate_traits_d Traits; - Box_intersection_d::all_pairs( begin1, end1, begin2, end2, + Box_intersection_d::all_pairs( begin1, end1, begin2, end2, callback, Traits()); } template< class ForwardIter1, class ForwardIter2, class Callback, class BoxTraits > -void box_intersection_all_pairs_d( +void box_intersection_all_pairs_d( ForwardIter1 begin1, ForwardIter1 end1, ForwardIter2 begin2, ForwardIter2 end2, Callback callback, BoxTraits, @@ -366,18 +365,18 @@ void box_intersection_all_pairs_d( bool complete_case = (setting != Box_intersection_d::BIPARTITE); if (topology == Box_intersection_d::CLOSED) { typedef Box_intersection_d::Predicate_traits_d Traits; - Box_intersection_d::all_pairs( begin1, end1, begin2, end2, + Box_intersection_d::all_pairs( begin1, end1, begin2, end2, callback, Traits(), complete_case); } else { typedef Box_intersection_d::Predicate_traits_d Traits; - Box_intersection_d::all_pairs( begin1, end1, begin2, end2, + Box_intersection_d::all_pairs( begin1, end1, begin2, end2, callback, Traits(), complete_case); } } template< class ForwardIter1, class ForwardIter2, class Callback, class BoxTraits > -void box_intersection_all_pairs_d( +void box_intersection_all_pairs_d( ForwardIter1 begin1, ForwardIter1 end1, ForwardIter2 begin2, ForwardIter2 end2, Callback callback, BoxTraits traits, @@ -390,20 +389,20 @@ void box_intersection_all_pairs_d( // Specialized call for trivial all-pairs algorithm with default box traits. // - make all default parameters explicit overloads (workaround) template< class ForwardIter1, class ForwardIter2, class Callback > -void box_intersection_all_pairs_d( +void box_intersection_all_pairs_d( ForwardIter1 begin1, ForwardIter1 end1, ForwardIter2 begin2, ForwardIter2 end2, Callback callback) { typedef typename std::iterator_traits::value_type val_t; typedef Box_intersection_d::Box_traits_d< val_t> Box_traits; - box_intersection_all_pairs_d( begin1, end1, begin2, end2, - callback, Box_traits(), - Box_intersection_d::CLOSED ); + box_intersection_all_pairs_d( begin1, end1, begin2, end2, + callback, Box_traits(), + Box_intersection_d::CLOSED ); } template< class ForwardIter1, class ForwardIter2, class Callback > -void box_intersection_all_pairs_d( +void box_intersection_all_pairs_d( ForwardIter1 begin1, ForwardIter1 end1, ForwardIter2 begin2, ForwardIter2 end2, Callback callback, @@ -411,12 +410,12 @@ void box_intersection_all_pairs_d( { typedef typename std::iterator_traits::value_type val_t; typedef Box_intersection_d::Box_traits_d< val_t> Box_traits; - box_intersection_all_pairs_d( begin1, end1, begin2, end2, + box_intersection_all_pairs_d( begin1, end1, begin2, end2, callback, Box_traits(), topology); } template< class ForwardIter1, class ForwardIter2, class Callback > -void box_intersection_all_pairs_d( +void box_intersection_all_pairs_d( ForwardIter1 begin1, ForwardIter1 end1, ForwardIter2 begin2, ForwardIter2 end2, Callback callback, @@ -425,7 +424,7 @@ void box_intersection_all_pairs_d( { typedef typename std::iterator_traits::value_type val_t; typedef Box_intersection_d::Box_traits_d< val_t> Box_traits; - box_intersection_all_pairs_d( begin1, end1, begin2, end2, + box_intersection_all_pairs_d( begin1, end1, begin2, end2, callback, Box_traits(), topology, setting); } @@ -433,7 +432,7 @@ void box_intersection_all_pairs_d( // specialized for self-intersection test. // - make all default parameters explicit overloads (workaround) template< class ForwardIter, class Callback, class BoxTraits > -void box_self_intersection_all_pairs_d( +void box_self_intersection_all_pairs_d( ForwardIter begin1, ForwardIter end1, Callback callback, BoxTraits /* traits */) { typedef Box_intersection_d::Predicate_traits_d Traits; @@ -441,7 +440,7 @@ void box_self_intersection_all_pairs_d( } template< class ForwardIter, class Callback, class BoxTraits > -void box_self_intersection_all_pairs_d( +void box_self_intersection_all_pairs_d( ForwardIter begin1, ForwardIter end1, Callback callback, BoxTraits, Box_intersection_d::Topology topology) { @@ -458,17 +457,17 @@ void box_self_intersection_all_pairs_d( // specialized for self-intersection test. // - make all default parameters explicit overloads (workaround) template< class ForwardIter, class Callback > -void box_self_intersection_all_pairs_d( +void box_self_intersection_all_pairs_d( ForwardIter begin1, ForwardIter end1, Callback callback) { typedef typename std::iterator_traits::value_type val_t; typedef Box_intersection_d::Box_traits_d< val_t> Box_traits; - box_self_intersection_all_pairs_d( begin1, end1, callback, Box_traits(), - Box_intersection_d::CLOSED ); + box_self_intersection_all_pairs_d( begin1, end1, callback, Box_traits(), + Box_intersection_d::CLOSED ); } template< class ForwardIter, class Callback > -void box_self_intersection_all_pairs_d( +void box_self_intersection_all_pairs_d( ForwardIter begin1, ForwardIter end1, Callback callback, Box_intersection_d::Topology topology) { diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_impl.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_impl.h index 0f2f9717be0..0033074f0f4 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_impl.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_impl.h @@ -250,10 +250,11 @@ class Intersection_of_triangle_meshes if (callback_si.self_intersections_found()) throw Self_intersection_exception(); } - else - CGAL::box_intersection_d( face_boxes_ptr.begin(), face_boxes_ptr.end(), - edge_boxes_ptr.begin(), edge_boxes_ptr.end(), - callback, cutoff ); + else { + CGAL::box_intersection_d( face_boxes_ptr.begin(), face_boxes_ptr.end(), + edge_boxes_ptr.begin(), edge_boxes_ptr.end(), + callback, cutoff ); + } } // for autorefinement diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/repair_extra.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/repair_extra.h index 0373aefbf8a..f18ef7186be 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/repair_extra.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/repair_extra.h @@ -142,7 +142,6 @@ void collect_close_stitchable_boundary_edges(PM& pm, for(Box& b : boxes) box_ptrs.push_back(&b); - Halfedge_multiplicity multiplicity; Halfedge_pairs matching_hedges; diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/intersection.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/intersection.h index f564c26b304..13f60f31f03 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/intersection.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/intersection.h @@ -17,20 +17,21 @@ #include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include #include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include + namespace CGAL { namespace Polygon_mesh_processing{ namespace internal { @@ -416,12 +417,8 @@ compute_face_face_intersection(const FaceRange& face_range1, // make one box per facet std::vector boxes1; std::vector boxes2; - boxes1.reserve( - std::distance( boost::begin(face_range1), boost::end(face_range1) ) - ); - boxes2.reserve( - std::distance( boost::begin(face_range2), boost::end(face_range2) ) - ); + boxes1.reserve(std::distance(boost::begin(face_range1), boost::end(face_range1))); + boxes2.reserve(std::distance(boost::begin(face_range2), boost::end(face_range2))); typedef typename GetVertexPointMap::const_type VertexPointMap1; typedef typename GetVertexPointMap::const_type VertexPointMap2; @@ -435,6 +432,7 @@ compute_face_face_intersection(const FaceRange& face_range1, typename boost::property_traits::value_type, typename boost::property_traits::value_type >::value) ); + for(face_descriptor f : face_range1) { boxes1.push_back(Box(Polygon_mesh_processing::face_bbox(f, tm1), f)); @@ -451,7 +449,6 @@ compute_face_face_intersection(const FaceRange& face_range1, std::vector box2_ptr(boost::make_counting_iterator(&boxes2[0]), boost::make_counting_iterator(&boxes2[0]+boxes2.size())); - // compute intersections filtered out by boxes typedef typename GetGeomTraits::type GeomTraits; GeomTraits gt = choose_parameter(get_parameter(np1, internal_np::geom_traits), GeomTraits()); @@ -461,10 +458,7 @@ compute_face_face_intersection(const FaceRange& face_range1, Box, OutputIterator, VertexPointMap1, - VertexPointMap2> Intersect_faces(tm1, tm2, - out, - vpmap1, vpmap2, - gt); + VertexPointMap2> Intersect_faces(tm1, tm2, out, vpmap1, vpmap2, gt); std::ptrdiff_t cutoff = 2000; CGAL::box_intersection_d(box1_ptr.begin(), box1_ptr.end(), @@ -543,7 +537,7 @@ compute_face_polyline_intersection( const FaceRange& face_range, typename boost::range_value::type>::value)); std::vector faces; - faces.reserve(std::distance( boost::begin(face_range), boost::end(face_range) )); + faces.reserve(std::distance(boost::begin(face_range), boost::end(face_range))); typedef CGAL::Box_intersection_d::ID_FROM_BOX_ADDRESS Box_policy; typedef CGAL::Box_intersection_d::Box_with_info_d Box; @@ -551,14 +545,8 @@ compute_face_polyline_intersection( const FaceRange& face_range, // make one box per facet std::vector boxes1; std::vector boxes2; - boxes1.reserve( - std::distance( boost::begin(face_range), boost::end(face_range) ) - ); - - boxes2.reserve( - std::distance( boost::begin(polyline), boost::end(polyline) ) - 1 - ); - + boxes1.reserve(std::distance(boost::begin(face_range), boost::end(face_range))); + boxes2.reserve(std::distance(boost::begin(polyline), boost::end(polyline)) - 1); for(face_descriptor f : face_range) { @@ -574,7 +562,6 @@ compute_face_polyline_intersection( const FaceRange& face_range, } // generate box pointers - std::vector box1_ptr(boost::make_counting_iterator(&boxes1[0]), boost::make_counting_iterator(&boxes1[0]+boxes1.size())); std::vector box2_ptr(boost::make_counting_iterator(&boxes2[0]), @@ -590,12 +577,7 @@ compute_face_polyline_intersection( const FaceRange& face_range, OutputIterator, Polyline, VertexPointMap> - Intersect_face_polyline(tm, - faces, - polyline, - out, - vpmap, - gt); + Intersect_face_polyline(tm, faces, polyline, out, vpmap, gt); std::ptrdiff_t cutoff = 2000; CGAL::box_intersection_d(box1_ptr.begin(), box1_ptr.end(), @@ -675,9 +657,7 @@ compute_face_polylines_intersection(const FaceRange& face_range, get_const_property_map(boost::vertex_point, tm)); typedef typename boost::property_traits::value_type Point; typedef typename boost::range_value::type Polyline; - CGAL_static_assertion( - (boost::is_same::type>::value)); + CGAL_static_assertion((boost::is_same::type>::value)); std::vector faces; faces.reserve(std::distance( boost::begin(face_range), boost::end(face_range) )); @@ -688,22 +668,21 @@ compute_face_polylines_intersection(const FaceRange& face_range, // make one box per facet std::vector boxes1; std::vector boxes2; - boxes1.reserve( - std::distance( boost::begin(face_range), boost::end(face_range) ) - ); + boxes1.reserve(std::distance(boost::begin(face_range), boost::end(face_range))); std::size_t polylines_size = 0; for(Polyline poly : polyline_range) { polylines_size += std::distance( boost::begin(poly), boost::end(poly) ) -1; } - boxes2.reserve( polylines_size ); + boxes2.reserve(polylines_size); for(face_descriptor f : face_range) { faces.push_back(f); boxes1.push_back(Box(Polygon_mesh_processing::face_bbox(f, tm), std::make_pair(0, faces.size()-1))); } + std::size_t range_size = std::distance( boost::begin(polyline_range), boost::end(polyline_range) ); for(std::size_t j = 0; j < range_size; ++j) { @@ -734,12 +713,7 @@ compute_face_polylines_intersection(const FaceRange& face_range, PolylineRange, OutputIterator, VertexPointMap> - Intersect_face_polyline(tm, - faces, - polyline_range, - out, - vpmap, - gt); + Intersect_face_polyline(tm, faces, polyline_range, out, vpmap, gt); std::ptrdiff_t cutoff = 2000; CGAL::box_intersection_d(box1_ptr.begin(), box1_ptr.end(), @@ -784,13 +758,8 @@ compute_polyline_polyline_intersection(const Polyline& polyline1, // make one box per facet std::vector boxes1; std::vector boxes2; - boxes1.reserve( - std::distance( boost::begin(polyline1), boost::end(polyline1) ) - 1 - ); - - boxes2.reserve( - std::distance( boost::begin(polyline2), boost::end(polyline2) ) - 1 - ); + boxes1.reserve(std::distance(boost::begin(polyline1), boost::end(polyline1)) - 1); + boxes2.reserve(std::distance(boost::begin(polyline2), boost::end(polyline2)) - 1); for(std::size_t i =0; i< polyline1.size()-1; ++i) { @@ -819,10 +788,7 @@ compute_polyline_polyline_intersection(const Polyline& polyline1, Kernel, Box, OutputIterator> - intersect_polylines(polyline1, - polyline2, - out, - K); + intersect_polylines(polyline1, polyline2, out, K); std::ptrdiff_t cutoff = 2000; CGAL::box_intersection_d(box1_ptr.begin(), box1_ptr.end(), @@ -879,6 +845,7 @@ compute_polylines_polylines_intersection(const PolylineRange& polylines1, b1 += CGAL::bbox_3(poly.begin(), poly.end()); } boxes1.reserve( polylines_size ); + polylines_size = 0; for(Polyline poly : polylines2) { @@ -886,9 +853,10 @@ compute_polylines_polylines_intersection(const PolylineRange& polylines1, b2 += CGAL::bbox_3(poly.begin(), poly.end()); } boxes2.reserve(polylines_size); - + if(!CGAL::do_overlap(b1,b2)) return out; + std::size_t range_size = std::distance( boost::begin(polylines1), boost::end(polylines1) ); for(std::size_t j = 0; j < range_size; ++j) { @@ -923,15 +891,11 @@ compute_polylines_polylines_intersection(const PolylineRange& polylines1, // compute intersections filtered out by boxes - internal::Intersect_polyline_ranges - intersect_polylines(polylines1, - polylines2, - out, - K); + intersect_polylines(polylines1, polylines2, out, K); std::ptrdiff_t cutoff = 2000; CGAL::box_intersection_d(box1_ptr.begin(), box1_ptr.end(), @@ -1614,21 +1578,18 @@ OutputIterator intersecting_meshes(const TriangleMeshRange& range, boxes.push_back( Mesh_box(Polygon_mesh_processing::bbox(*it), it) ); } - std::vector boxes_ptr( - boost::make_counting_iterator(&boxes[0]), - boost::make_counting_iterator(&boxes[0]+boxes.size())); + std::vector boxes_ptr(boost::make_counting_iterator(&boxes[0]), + boost::make_counting_iterator(&boxes[0]+boxes.size())); typedef typename boost::range_value::type NP_rng; typedef typename boost::range_value::type TriangleMesh; typedef typename GetGeomTraits::type GT; GT gt = choose_parameter(get_parameter(np, internal_np::geom_traits), GT()); - //get all the pairs of meshes intersecting (no strict inclusion test) std::ptrdiff_t cutoff = 2000; internal::Mesh_callback callback(range, out, report_overlap, gt, nps); - CGAL::box_self_intersection_d(boxes_ptr.begin(), boxes_ptr.end(), - callback, cutoff); + CGAL::box_self_intersection_d(boxes_ptr.begin(), boxes_ptr.end(), callback, cutoff); return callback.m_iterator; } @@ -1644,7 +1605,7 @@ OutputIterator intersecting_meshes(const TriangleMeshRange& range, template OutputIterator intersecting_meshes(const TriangleMeshRange& range, - OutputIterator out) + OutputIterator out) { return intersecting_meshes(range, out, parameters::all_default()); } @@ -1837,9 +1798,10 @@ surface_self_intersection(const TriangleMesh& tm, CGAL::Polygon_mesh_processing::parameters::all_default() ); } -} //end of namespace experimental -} } //end of namespace CGAL::Polygon_mesh_processing +} //end of namespace experimental +} //end of namespace Polygon_mesh_processing +} //end of namespace CGAL #include diff --git a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/internal/validity.h b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/internal/validity.h index cdf8ce2de80..2398eff4a91 100644 --- a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/internal/validity.h +++ b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/internal/validity.h @@ -285,8 +285,7 @@ bool is_one_to_one_mapping(const TriangleMesh& mesh, unsigned int counter = 0; Intersect_facets intersect_facets(mesh, uvmap, counter); std::ptrdiff_t cutoff = 2000; - CGAL::box_self_intersection_d(boxes_ptr.begin(), boxes_ptr.end(), - intersect_facets, cutoff); + CGAL::box_self_intersection_d(boxes_ptr.begin(), boxes_ptr.end(), intersect_facets, cutoff); return (counter == 0); } From 16350e84a444815ab4bf33d478b57414e0618c89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 19 Nov 2019 17:12:44 +0100 Subject: [PATCH 059/185] Fix bad typedef --- .../include/CGAL/Box_intersection_d/Box_with_info_d.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Box_intersection_d/include/CGAL/Box_intersection_d/Box_with_info_d.h b/Box_intersection_d/include/CGAL/Box_intersection_d/Box_with_info_d.h index 990f3dd5fbb..eeccd7f9819 100644 --- a/Box_intersection_d/include/CGAL/Box_intersection_d/Box_with_info_d.h +++ b/Box_intersection_d/include/CGAL/Box_intersection_d/Box_with_info_d.h @@ -29,7 +29,7 @@ class Box_with_info_d protected: Info_ m_info; public: - typedef Box_d< NT_, N, ID_EXPLICIT> Base; + typedef Box_d< NT_, N, IdPolicy> Base; typedef NT_ NT; typedef Info_ Info; From 1e6b42d029b5ce96e9822533537a17f58bfbde0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 19 Nov 2019 18:40:03 +0100 Subject: [PATCH 060/185] Add a split in 3 box_intersection_d parallel version --- .../include/CGAL/box_intersection_d.h | 84 ++++++++++++++++--- 1 file changed, 74 insertions(+), 10 deletions(-) diff --git a/Box_intersection_d/include/CGAL/box_intersection_d.h b/Box_intersection_d/include/CGAL/box_intersection_d.h index cdbf058fcb6..ff0698dd780 100644 --- a/Box_intersection_d/include/CGAL/box_intersection_d.h +++ b/Box_intersection_d/include/CGAL/box_intersection_d.h @@ -34,6 +34,7 @@ #include #include +#include namespace CGAL { namespace internal { @@ -64,27 +65,32 @@ void box_intersection_segment_tree_d( #else // CGAL_LINKED_WITH_TBB if(boost::is_convertible::value) { - typename std::iterator_traits::difference_type r1hs = std::distance(begin1, end1) / 2; - typename std::iterator_traits::difference_type r2hs = std::distance(begin2, end2) / 2; + unsigned thread_n = std::thread::hardware_concurrency(); + std::cout << thread_n << " threads" << std::endl; // TODO: Check which of the two following approaches is better // The first one makes three copies of the vector and performs four parallel tasks // The second one makes one copy, but must perform two times two parallel tasks (can't // do all four at the same time otherwise the sort / split will conflict) -#ifdef CGAL_BOX_INTER_FOUR_RANGES +#ifdef CGAL_BOX_INTER_ONE_SPLIT // cuts in 2 --> 2 copies of each vector, 9 pairs + std::cout << "Split in 2" << std::endl; + typedef typename std::iterator_traits::value_type val_t; + typename std::iterator_traits::difference_type r1_half = std::distance(begin1, end1) / 2; + typename std::iterator_traits::difference_type r2_half = std::distance(begin2, end2) / 2; + std::vector< val_t> r3( begin1, end1); std::vector< val_t> r4( begin2, end2); RandomAccessIter1 mid1 = begin1; - std::advance(mid1, r1hs); + std::advance(mid1, r1_half); RandomAccessIter2 mid2 = begin2; - std::advance(mid2, r2hs); + std::advance(mid2, r2_half); typename std::vector< val_t>::iterator mid3 = r3.begin(); - std::advance(mid3, r1hs); + std::advance(mid3, r1_half); typename std::vector< val_t>::iterator mid4 = r4.begin(); - std::advance(mid4, r2hs); + std::advance(mid4, r2_half); tbb::parallel_invoke([&]{ Box_intersection_d::segment_tree( begin1, mid1, begin2, mid2, inf, sup, callback, traits, cutoff, dim, in_order); }, @@ -94,11 +100,69 @@ void box_intersection_segment_tree_d( callback, traits, cutoff, dim, in_order); }, [&]{ Box_intersection_d::segment_tree( mid3, r3.end(), r4.begin(), mid4, inf, sup, callback, traits, cutoff, dim, in_order); } ); -#else // CGAL_BOX_INTER_FOUR_RANGES +#elif defined(CGAL_BOX_INTER_TWO_SPLIT) // cuts in 3 --> 3 copies of each vector, 9 pairs + std::cout << "Split in 3" << std::endl; + + typedef typename std::iterator_traits::value_type val_t; + typedef typename std::vector< val_t>::iterator It; + + typename std::iterator_traits::difference_type r1_third = std::distance(begin1, end1) / 3; + typename std::iterator_traits::difference_type r1_two_third = 2 * std::distance(begin1, end1) / 3; + typename std::iterator_traits::difference_type r2_third = std::distance(begin2, end2) / 3; + typename std::iterator_traits::difference_type r2_two_third = 2 * std::distance(begin2, end2) / 3; + + std::vector< val_t> r3( begin1, end1); + std::vector< val_t> r4( begin2, end2); + std::vector< val_t> r5( begin1, end1); + std::vector< val_t> r6( begin2, end2); + + RandomAccessIter1 r1_left = begin1; std::advance(r1_left, r1_third); + RandomAccessIter2 r2_left = begin2; std::advance(r2_left, r2_third); + It r3_left = r3.begin(); std::advance(r3_left, r1_third); + It r4_left = r4.begin(); std::advance(r4_left, r2_third); + It r5_left = r5.begin(); std::advance(r5_left, r1_third); + It r6_left = r6.begin(); std::advance(r6_left, r2_third); + + RandomAccessIter1 r1_right = begin1; std::advance(r1_right, r1_two_third); + RandomAccessIter2 r2_right = begin2; std::advance(r2_right, r2_two_third); + It r3_right = r3.begin(); std::advance(r3_right, r1_two_third); + It r4_right = r4.begin(); std::advance(r4_right, r2_two_third); + It r5_right = r5.begin(); std::advance(r5_right, r1_two_third); + It r6_right = r6.begin(); std::advance(r6_right, r2_two_third); + + tbb::parallel_invoke([&]{ Box_intersection_d::segment_tree( begin1, r1_left, begin2, r2_left, inf, sup, + callback, traits, cutoff, dim, in_order); }, + [&]{ Box_intersection_d::segment_tree( r1_left, r1_right, r2_left, r2_right, inf, sup, + callback, traits, cutoff, dim, in_order); }, + [&]{ Box_intersection_d::segment_tree( r1_right, end1, r2_right, end2, inf, sup, + callback, traits, cutoff, dim, in_order); }, + + // shifted 1 + [&]{ Box_intersection_d::segment_tree( r3.begin(), r3_left, r4_left, r4_right, inf, sup, + callback, traits, cutoff, dim, in_order); }, + [&]{ Box_intersection_d::segment_tree( r3_left, r3_right, r4_right, r4.end(), inf, sup, + callback, traits, cutoff, dim, in_order); }, + [&]{ Box_intersection_d::segment_tree( r3_right, r3.end(), r4.begin(), r4_left, inf, sup, + callback, traits, cutoff, dim, in_order); }, + + // shifted 2 + [&]{ Box_intersection_d::segment_tree( r5.begin(), r5_left, r6_right, r6.end(), inf, sup, + callback, traits, cutoff, dim, in_order); }, + [&]{ Box_intersection_d::segment_tree( r5_left, r5_right, r6.begin(), r6_left, inf, sup, + callback, traits, cutoff, dim, in_order); }, + [&]{ Box_intersection_d::segment_tree( r5_right, r5.end(), r6_left, r6_right, inf, sup, + callback, traits, cutoff, dim, in_order); } ); + +#else + std::cout << "2x2" << std::endl; + + typename std::iterator_traits::difference_type r1_half = std::distance(begin1, end1) / 2; + typename std::iterator_traits::difference_type r2_half = std::distance(begin2, end2) / 2; + RandomAccessIter1 mid1 = begin1; - std::advance(mid1, r1hs); + std::advance(mid1, r1_half); RandomAccessIter2 mid2 = begin2; - std::advance(mid2, r2hs); + std::advance(mid2, r2_half); tbb::parallel_invoke([&]{ Box_intersection_d::segment_tree( begin1, mid1, begin2, mid2, inf, sup, callback, traits, cutoff, dim, in_order); }, From 47c0ce254ed408b71ebba92df1b907ded5f2c266 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 19 Nov 2019 18:40:34 +0100 Subject: [PATCH 061/185] Enrich example --- .../self_intersections_example.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp index 1ce5501e5cb..a36a5003ae7 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include @@ -24,14 +25,22 @@ int main(int argc, char* argv[]) return EXIT_FAILURE; } + CGAL::Real_timer timer; + timer.start(); + + std::cout << "Using parallel mode? " << std::is_same::value << std::endl; + bool intersecting = PMP::does_self_intersect( mesh, CGAL::parameters::vertex_point_map(get(CGAL::vertex_point, mesh))); - std::cout << (intersecting ? "There are self-intersections." : "There is no self-intersection.") << std::endl; std::vector > intersected_tris; - PMP::self_intersections(faces(mesh), mesh, std::back_inserter(intersected_tris)); + PMP::self_intersections(faces(mesh), mesh, std::back_inserter(intersected_tris)); std::cout << intersected_tris.size() << " pairs of triangles intersect." << std::endl; + timer.stop(); + double t = timer.time(); + std::cout << "Time: " << t << std::endl; + return EXIT_SUCCESS; } From cb74e536f1e7c190e84de117280dc42290f2f7cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 20 Nov 2019 11:42:47 +0100 Subject: [PATCH 062/185] Document the new type --- STL_Extension/doc/STL_Extension/CGAL/tags.h | 11 +++++++++-- .../doc/STL_Extension/PackageDescription.txt | 3 +++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/STL_Extension/doc/STL_Extension/CGAL/tags.h b/STL_Extension/doc/STL_Extension/CGAL/tags.h index 5e102c1d8ca..9a54c36a4fe 100644 --- a/STL_Extension/doc/STL_Extension/CGAL/tags.h +++ b/STL_Extension/doc/STL_Extension/CGAL/tags.h @@ -69,18 +69,25 @@ struct Null_functor { /*! \ingroup PkgSTLExtensionUtilities -Tag used to enable/disable concurrency. +Tag used to disable concurrency. For example, it may be used by a user to request the sequential version of an algorithm. */ struct Sequential_tag {}; /*! \ingroup PkgSTLExtensionUtilities -Tag used to enable/disable concurrency. +Tag used to enable concurrency. For example, it may be used by a user to request the parallel version of an algorithm. */ struct Parallel_tag {}; +/*! +\ingroup PkgSTLExtensionUtilities +This tag is a convenience typedef to `Parallel_tag` if the third party library \ref thirdpartyTBB +has been found and linked, and to `Sequential_tag` otherwise. +*/ +struct Parallel_if_available_tag {}; + /*! \ingroup PkgSTLExtensionUtilities diff --git a/STL_Extension/doc/STL_Extension/PackageDescription.txt b/STL_Extension/doc/STL_Extension/PackageDescription.txt index df921c5c6e0..4372a8f37d3 100644 --- a/STL_Extension/doc/STL_Extension/PackageDescription.txt +++ b/STL_Extension/doc/STL_Extension/PackageDescription.txt @@ -109,6 +109,9 @@ - `CGAL::Tag_false` - `CGAL::Null_tag` - `CGAL::Null_functor` +- `CGAL::Sequential_tag` +- `CGAL::Parallel_tag` +- `CGAL::Parallel_if_available_tag` - `CGAL::Uncertain` - `CGAL::Default` - `CGAL::Fast` From e73b973b62d52a34a20428d6db1420d45cdbb22c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 20 Nov 2019 12:24:54 +0100 Subject: [PATCH 063/185] Use Parallel_if_available_tag to simplify code that used CGAL_LINKED_WITH_TBB --- .../Classification/example_classification.cpp | 8 ++----- .../example_cluster_classification.cpp | 6 +---- .../ETHZ/Random_forest_classifier.h | 8 ++----- .../Classification/Local_eigen_analysis.h | 18 +++++---------- .../Classification/Mesh_feature_generator.h | 6 ++--- .../Point_set_feature_generator.h | 4 +--- .../include/CGAL/Classification/classify.h | 6 ++--- Hash_map/test/Hash_map/Hash.cpp | 3 ++- Mesh_3/doc/Mesh_3/CGAL/Mesh_triangulation_3.h | 4 ++-- .../average_spacing_example.cpp | 7 +----- .../bilateral_smooth_point_set_example.cpp | 7 +----- .../callback_example.cpp | 7 +----- .../edge_aware_upsample_point_set_example.cpp | 7 +----- .../jet_smoothing_example.cpp | 7 +----- .../normal_estimation.cpp | 7 +----- .../normals_example.cpp | 6 +---- .../scale_estimation_example.cpp | 6 +---- ...plify_and_regularize_point_set_example.cpp | 6 +---- .../include/CGAL/bilateral_smooth_point_set.h | 5 ++--- .../include/CGAL/compute_average_spacing.h | 5 ++--- .../CGAL/edge_aware_upsample_point_set.h | 4 ++-- .../include/CGAL/jet_estimate_normals.h | 5 ++--- .../include/CGAL/jet_smooth_point_set.h | 5 ++--- .../include/CGAL/pca_estimate_normals.h | 5 ++--- .../wlop_simplify_and_regularize_point_set.h | 5 ++--- .../Point_set_processing_3/analysis_test.cpp | 7 +----- .../edge_aware_upsample_test.cpp | 7 +----- .../normal_estimation_test.cpp | 7 +----- .../Point_set_processing_3/smoothing_test.cpp | 6 +---- .../hausdorff_distance_remeshing_example.cpp | 6 +---- .../CGAL/Polygon_mesh_processing/distance.h | 3 +-- .../CGAL/internal/compute_confidences.h | 11 ++-------- .../Classification/Cluster_classification.h | 7 +----- .../Point_set_item_classification.h | 8 +------ .../Surface_mesh_item_classification.h | 6 +---- .../Point_set_average_spacing_plugin.cpp | 6 +---- .../Point_set_bilateral_smoothing_plugin.cpp | 6 +---- .../Point_set_interference_plugin.cpp | 7 ++---- .../Point_set_normal_estimation_plugin.cpp | 6 +---- .../Point_set_simplification_plugin.cpp | 6 +---- .../Point_set/Point_set_smoothing_plugin.cpp | 6 +---- .../Point_set/Point_set_upsampling_plugin.cpp | 8 ++----- .../Point_set/Point_set_wlop_plugin.cpp | 6 +---- .../Surface_reconstruction_poisson_impl.cpp | 8 +------ ...urface_reconstruction_scale_space_impl.cpp | 6 +---- .../Plugins/Surface_mesh/VSA_wrapper.h | 22 +++---------------- .../include/run_with_qprogressdialog.h | 7 +----- STL_Extension/include/CGAL/tags.h | 1 - .../Jet_smoother.h | 6 ++--- .../Weighted_PCA_smoother.h | 14 +++++------- .../CGAL/Triangulation_data_structure_3.h | 2 +- .../Concepts/TriangulationDataStructure_3.h | 2 +- 52 files changed, 80 insertions(+), 264 deletions(-) diff --git a/Classification/examples/Classification/example_classification.cpp b/Classification/examples/Classification/example_classification.cpp index 665fb17f064..0475fdfcfb3 100644 --- a/Classification/examples/Classification/example_classification.cpp +++ b/Classification/examples/Classification/example_classification.cpp @@ -11,16 +11,12 @@ #include #include #include - +#include #include #include -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif +typedef CGAL::Parallel_if_available_tag Concurrency_tag; typedef CGAL::Simple_cartesian Kernel; typedef Kernel::Point_3 Point; diff --git a/Classification/examples/Classification/example_cluster_classification.cpp b/Classification/examples/Classification/example_cluster_classification.cpp index e4ff944803a..78f48b8ddde 100644 --- a/Classification/examples/Classification/example_cluster_classification.cpp +++ b/Classification/examples/Classification/example_cluster_classification.cpp @@ -18,11 +18,7 @@ #include #include -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif +typedef CGAL::Parallel_if_available_tag Concurrency_tag; typedef CGAL::Simple_cartesian Kernel; typedef Kernel::Point_3 Point; diff --git a/Classification/include/CGAL/Classification/ETHZ/Random_forest_classifier.h b/Classification/include/CGAL/Classification/ETHZ/Random_forest_classifier.h index 513c939bb8e..62b6dc57d26 100644 --- a/Classification/include/CGAL/Classification/ETHZ/Random_forest_classifier.h +++ b/Classification/include/CGAL/Classification/ETHZ/Random_forest_classifier.h @@ -127,11 +127,7 @@ public: std::size_t num_trees = 25, std::size_t max_depth = 20) { -#ifdef CGAL_LINKED_WITH_TBB - train(ground_truth, reset_trees, num_trees, max_depth); -#else - train(ground_truth, reset_trees, num_trees, max_depth); -#endif + train(ground_truth, reset_trees, num_trees, max_depth); } /// \endcond @@ -146,7 +142,7 @@ public: label. \tparam ConcurrencyTag enables sequential versus parallel - algorithm. Possible values are `Parallel_tag` (default value is + algorithm. Possible values are `Parallel_tag` (default value if %CGAL is linked with TBB) or `Sequential_tag` (default value otherwise). diff --git a/Classification/include/CGAL/Classification/Local_eigen_analysis.h b/Classification/include/CGAL/Classification/Local_eigen_analysis.h index b3849220d54..4ba3ca0661b 100644 --- a/Classification/include/CGAL/Classification/Local_eigen_analysis.h +++ b/Classification/include/CGAL/Classification/Local_eigen_analysis.h @@ -225,7 +225,7 @@ public: is `CGAL::Point_3`. \tparam NeighborQuery model of `NeighborQuery` \tparam ConcurrencyTag enables sequential versus parallel - algorithm. Possible values are `Parallel_tag` (default value is %CGAL + algorithm. Possible values are `Parallel_tag` (default value if %CGAL is linked with TBB) or `Sequential_tag` (default value otherwise). \tparam DiagonalizeTraits model of `DiagonalizeTraits` used for matrix diagonalization. It can be omitted if Eigen 3 (or greater) @@ -241,10 +241,8 @@ public: typename NeighborQuery, #if defined(DOXYGEN_RUNNING) typename ConcurrencyTag, -#elif defined(CGAL_LINKED_WITH_TBB) - typename ConcurrencyTag = CGAL::Parallel_tag, #else - typename ConcurrencyTag = CGAL::Sequential_tag, + typename ConcurrencyTag = CGAL::Parallel_if_available_tag, #endif #if defined(DOXYGEN_RUNNING) typename DiagonalizeTraits> @@ -309,7 +307,7 @@ public: \tparam FaceListGraph model of `FaceListGraph`. \tparam NeighborQuery model of `NeighborQuery` \tparam ConcurrencyTag enables sequential versus parallel - algorithm. Possible values are `Parallel_tag` (default value is %CGAL + algorithm. Possible values are `Parallel_tag` (default value if %CGAL is linked with TBB) or `Sequential_tag` (default value otherwise). \tparam DiagonalizeTraits model of `DiagonalizeTraits` used for matrix diagonalization. It can be omitted: if Eigen 3 (or greater) @@ -324,10 +322,8 @@ public: typename NeighborQuery, #if defined(DOXYGEN_RUNNING) typename ConcurrencyTag, -#elif defined(CGAL_LINKED_WITH_TBB) - typename ConcurrencyTag = CGAL::Parallel_tag, #else - typename ConcurrencyTag = CGAL::Sequential_tag, + typename ConcurrencyTag = CGAL::Parallel_if_available_tag, #endif #if defined(DOXYGEN_RUNNING) typename DiagonalizeTraits> @@ -395,7 +391,7 @@ public: `RandomAccessIterator` and its value type is the key type of `PointMap`. \tparam ConcurrencyTag enables sequential versus parallel - algorithm. Possible values are `Parallel_tag` (default value is %CGAL + algorithm. Possible values are `Parallel_tag` (default value if %CGAL is linked with TBB) or `Sequential_tag` (default value otherwise). \tparam DiagonalizeTraits model of `DiagonalizeTraits` used for matrix diagonalization. It can be omitted: if Eigen 3 (or greater) @@ -408,10 +404,8 @@ public: template diff --git a/Classification/include/CGAL/Classification/Mesh_feature_generator.h b/Classification/include/CGAL/Classification/Mesh_feature_generator.h index 5b90b74b379..ba7832587bd 100644 --- a/Classification/include/CGAL/Classification/Mesh_feature_generator.h +++ b/Classification/include/CGAL/Classification/Mesh_feature_generator.h @@ -79,7 +79,7 @@ namespace Classification { is `GeomTraits::Point_3`. \tparam ConcurrencyTag enables sequential versus parallel computation of `CGAL::Classification::Local_eigen_analysis` - objects. Possible values are `Parallel_tag` (default value is %CGAL + objects. Possible values are `Parallel_tag` (default value if %CGAL is linked with TBB) or `Sequential_tag` (default value otherwise). \tparam DiagonalizeTraits model of `DiagonalizeTraits` used for matrix diagonalization. It can be omitted: if Eigen 3 (or greater) @@ -93,10 +93,8 @@ template > class Mesh_feature_generator diff --git a/Classification/include/CGAL/Classification/Point_set_feature_generator.h b/Classification/include/CGAL/Classification/Point_set_feature_generator.h index 8169e4acec4..58e58bb54dc 100644 --- a/Classification/include/CGAL/Classification/Point_set_feature_generator.h +++ b/Classification/include/CGAL/Classification/Point_set_feature_generator.h @@ -90,10 +90,8 @@ template diff --git a/Classification/include/CGAL/Classification/classify.h b/Classification/include/CGAL/Classification/classify.h index 6fb787a43df..ccd4f585e1a 100644 --- a/Classification/include/CGAL/Classification/classify.h +++ b/Classification/include/CGAL/Classification/classify.h @@ -334,7 +334,7 @@ namespace internal { suboptimal results. \tparam ConcurrencyTag enables sequential versus parallel - algorithm. Possible values are `Parallel_tag` or `Sequential_tag`. + algorithm. Possible values are `Parallel_if_available_tag`, `Parallel_tag` or `Sequential_tag`. \tparam ItemRange model of `ConstRange`. Its iterator type is `RandomAccessIterator`. Its value type depends on the data that is @@ -424,7 +424,7 @@ namespace internal { efficiency and better quality results. \tparam ConcurrencyTag enables sequential versus parallel - algorithm. Possible values are `Parallel_tag` or `Sequential_tag`. + algorithm. Possible values are `Parallel_if_available_tag`, `Parallel_tag` or `Sequential_tag`. \tparam ItemRange model of `ConstRange`. Its iterator type is `RandomAccessIterator`. \tparam ItemMap model of `ReadablePropertyMap` whose key @@ -502,7 +502,7 @@ namespace internal { results. \tparam ConcurrencyTag enables sequential versus parallel - algorithm. Possible values are `Parallel_tag` or `Sequential_tag`. + algorithm. Possible values are `Parallel_if_available_tag`, `Parallel_tag` or `Sequential_tag`. \tparam ItemRange model of `ConstRange`. Its iterator type is `RandomAccessIterator`. \tparam ItemMap model of `ReadablePropertyMap` whose key diff --git a/Hash_map/test/Hash_map/Hash.cpp b/Hash_map/test/Hash_map/Hash.cpp index fc46d118a25..beb15ce87f0 100644 --- a/Hash_map/test/Hash_map/Hash.cpp +++ b/Hash_map/test/Hash_map/Hash.cpp @@ -145,8 +145,9 @@ int main() #ifdef CGAL_LINKED_WITH_TBB Triangulation_3 T3; -fct3(T3); + fct3(T3); #endif + return 0; } diff --git a/Mesh_3/doc/Mesh_3/CGAL/Mesh_triangulation_3.h b/Mesh_3/doc/Mesh_3/CGAL/Mesh_triangulation_3.h index 768c00b1acd..cb8834e9040 100644 --- a/Mesh_3/doc/Mesh_3/CGAL/Mesh_triangulation_3.h +++ b/Mesh_3/doc/Mesh_3/CGAL/Mesh_triangulation_3.h @@ -12,8 +12,8 @@ type to be used for the 3D triangulation embedding the mesh. and defaults to `Kernel_traits::%Kernel`. \tparam Concurrency_tag enables sequential versus parallel meshing and optimization algorithms. - Possible values are `Sequential_tag` (the default) and - `Parallel_tag`. + Possible values are `Sequential_tag` (the default), `Parallel_tag`, + and `Parallel_if_available_tag`. \tparam Vertex_base must be a model of `MeshVertexBase_3` or `Default` and defaults to `Mesh_vertex_base_3`. diff --git a/Point_set_processing_3/examples/Point_set_processing_3/average_spacing_example.cpp b/Point_set_processing_3/examples/Point_set_processing_3/average_spacing_example.cpp index e97432aa79b..776f640c83c 100644 --- a/Point_set_processing_3/examples/Point_set_processing_3/average_spacing_example.cpp +++ b/Point_set_processing_3/examples/Point_set_processing_3/average_spacing_example.cpp @@ -16,12 +16,7 @@ typedef Kernel::Point_3 Point; typedef boost::tuple IndexedPointWithColorTuple; // Concurrency -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif - +typedef CGAL::Parallel_if_available_tag Concurrency_tag; int main(int argc, char*argv[]) { diff --git a/Point_set_processing_3/examples/Point_set_processing_3/bilateral_smooth_point_set_example.cpp b/Point_set_processing_3/examples/Point_set_processing_3/bilateral_smooth_point_set_example.cpp index 956f89cfe80..0f87a437e4a 100644 --- a/Point_set_processing_3/examples/Point_set_processing_3/bilateral_smooth_point_set_example.cpp +++ b/Point_set_processing_3/examples/Point_set_processing_3/bilateral_smooth_point_set_example.cpp @@ -17,12 +17,7 @@ typedef Kernel::Vector_3 Vector; typedef std::pair PointVectorPair; // Concurrency -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif - +typedef CGAL::Parallel_if_available_tag Concurrency_tag; int main(int argc, char*argv[]) { diff --git a/Point_set_processing_3/examples/Point_set_processing_3/callback_example.cpp b/Point_set_processing_3/examples/Point_set_processing_3/callback_example.cpp index 4004c7e832c..addaaeefaa3 100644 --- a/Point_set_processing_3/examples/Point_set_processing_3/callback_example.cpp +++ b/Point_set_processing_3/examples/Point_set_processing_3/callback_example.cpp @@ -18,12 +18,7 @@ typedef Kernel::Point_3 Point; typedef CGAL::Random_points_on_sphere_3 Generator; // Concurrency -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif - +typedef CGAL::Parallel_if_available_tag Concurrency_tag; // instance of std::function struct Progress_to_std_cerr_callback diff --git a/Point_set_processing_3/examples/Point_set_processing_3/edge_aware_upsample_point_set_example.cpp b/Point_set_processing_3/examples/Point_set_processing_3/edge_aware_upsample_point_set_example.cpp index 7ca76b9a055..173c07e9f1c 100644 --- a/Point_set_processing_3/examples/Point_set_processing_3/edge_aware_upsample_point_set_example.cpp +++ b/Point_set_processing_3/examples/Point_set_processing_3/edge_aware_upsample_point_set_example.cpp @@ -16,12 +16,7 @@ typedef Kernel::Vector_3 Vector; typedef std::pair PointVectorPair; // Concurrency -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif - +typedef CGAL::Parallel_if_available_tag Concurrency_tag; int main(int argc, char* argv[]) { diff --git a/Point_set_processing_3/examples/Point_set_processing_3/jet_smoothing_example.cpp b/Point_set_processing_3/examples/Point_set_processing_3/jet_smoothing_example.cpp index f228c8d69f6..85be76af70d 100644 --- a/Point_set_processing_3/examples/Point_set_processing_3/jet_smoothing_example.cpp +++ b/Point_set_processing_3/examples/Point_set_processing_3/jet_smoothing_example.cpp @@ -8,12 +8,7 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; typedef Kernel::Point_3 Point; // Concurrency -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif - +typedef CGAL::Parallel_if_available_tag Concurrency_tag; int main(void) { diff --git a/Point_set_processing_3/examples/Point_set_processing_3/normal_estimation.cpp b/Point_set_processing_3/examples/Point_set_processing_3/normal_estimation.cpp index befba2133f5..5f881c12647 100644 --- a/Point_set_processing_3/examples/Point_set_processing_3/normal_estimation.cpp +++ b/Point_set_processing_3/examples/Point_set_processing_3/normal_estimation.cpp @@ -48,12 +48,7 @@ typedef std::pair PointVectorPair; typedef std::vector PointList; // Concurrency -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif - +typedef CGAL::Parallel_if_available_tag Concurrency_tag; // ---------------------------------------------------------------------------- // Private functions diff --git a/Point_set_processing_3/examples/Point_set_processing_3/normals_example.cpp b/Point_set_processing_3/examples/Point_set_processing_3/normals_example.cpp index 25a28429661..629b836555d 100644 --- a/Point_set_processing_3/examples/Point_set_processing_3/normals_example.cpp +++ b/Point_set_processing_3/examples/Point_set_processing_3/normals_example.cpp @@ -18,11 +18,7 @@ typedef Kernel::Vector_3 Vector; typedef std::pair PointVectorPair; // Concurrency -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif +typedef CGAL::Parallel_if_available_tag Concurrency_tag; int main(int argc, char*argv[]) { diff --git a/Point_set_processing_3/examples/Point_set_processing_3/scale_estimation_example.cpp b/Point_set_processing_3/examples/Point_set_processing_3/scale_estimation_example.cpp index bdd2ebb5730..a85f56bea45 100644 --- a/Point_set_processing_3/examples/Point_set_processing_3/scale_estimation_example.cpp +++ b/Point_set_processing_3/examples/Point_set_processing_3/scale_estimation_example.cpp @@ -12,11 +12,7 @@ #include // Concurrency -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif +typedef CGAL::Parallel_if_available_tag Concurrency_tag; // Types typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; diff --git a/Point_set_processing_3/examples/Point_set_processing_3/wlop_simplify_and_regularize_point_set_example.cpp b/Point_set_processing_3/examples/Point_set_processing_3/wlop_simplify_and_regularize_point_set_example.cpp index e8485c3e5f8..d6ef47246fe 100644 --- a/Point_set_processing_3/examples/Point_set_processing_3/wlop_simplify_and_regularize_point_set_example.cpp +++ b/Point_set_processing_3/examples/Point_set_processing_3/wlop_simplify_and_regularize_point_set_example.cpp @@ -12,11 +12,7 @@ typedef CGAL::Simple_cartesian Kernel; typedef Kernel::Point_3 Point; // Concurrency -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif +typedef CGAL::Parallel_if_available_tag Concurrency_tag; int main(int argc, char** argv) { diff --git a/Point_set_processing_3/include/CGAL/bilateral_smooth_point_set.h b/Point_set_processing_3/include/CGAL/bilateral_smooth_point_set.h index e80d6a9be52..2e287518fb2 100644 --- a/Point_set_processing_3/include/CGAL/bilateral_smooth_point_set.h +++ b/Point_set_processing_3/include/CGAL/bilateral_smooth_point_set.h @@ -349,9 +349,8 @@ public: \pre Normals must be unit vectors \pre k >= 2 - \tparam ConcurrencyTag enables sequential versus parallel algorithm. - Possible values are `Sequential_tag` - And `Parallel_tag`. + \tparam ConcurrencyTag enables sequential versus parallel algorithm. Possible values are `Sequential_tag`, + `Parallel_tag`, and `Parallel_if_available_tag`. \tparam PointRange is a model of `Range`. The value type of its iterator is the key type of the named parameter `point_map`. diff --git a/Point_set_processing_3/include/CGAL/compute_average_spacing.h b/Point_set_processing_3/include/CGAL/compute_average_spacing.h index 01071c3b849..375a8932a03 100644 --- a/Point_set_processing_3/include/CGAL/compute_average_spacing.h +++ b/Point_set_processing_3/include/CGAL/compute_average_spacing.h @@ -150,9 +150,8 @@ compute_average_spacing(const typename Kernel::Point_3& query, ///< 3D point who \pre `k >= 2.` - \tparam ConcurrencyTag enables sequential versus parallel algorithm. - Possible values are `Sequential_tag` - and `Parallel_tag`. + \tparam ConcurrencyTag enables sequential versus parallel algorithm. Possible values are `Sequential_tag`, + `Parallel_tag`, and `Parallel_if_available_tag`. \tparam PointRange is a model of `ConstRange`. The value type of its iterator is the key type of the named parameter `point_map`. diff --git a/Point_set_processing_3/include/CGAL/edge_aware_upsample_point_set.h b/Point_set_processing_3/include/CGAL/edge_aware_upsample_point_set.h index 7097c2daf63..073e7418622 100644 --- a/Point_set_processing_3/include/CGAL/edge_aware_upsample_point_set.h +++ b/Point_set_processing_3/include/CGAL/edge_aware_upsample_point_set.h @@ -280,8 +280,8 @@ update_new_point( Normals of points are required as input. For more details, please refer to \cgalCite{ear-2013}. \tparam ConcurrencyTag enables sequential versus parallel versions - of `compute_average_spacing()` (called internally). Possible - values are `Sequential_tag` and `Parallel_tag`. + of `compute_average_spacing()` (called internally). Possible + values are `Sequential_tag`, `Parallel_tag`, and `Parallel_if_available_tag`. \tparam PointRange is a model of `ConstRange`. The value type of its iterator is the key type of the named parameter `point_map`. \tparam OutputIterator Type of the output iterator. diff --git a/Point_set_processing_3/include/CGAL/jet_estimate_normals.h b/Point_set_processing_3/include/CGAL/jet_estimate_normals.h index 746710d9240..9b6fb4a1869 100644 --- a/Point_set_processing_3/include/CGAL/jet_estimate_normals.h +++ b/Point_set_processing_3/include/CGAL/jet_estimate_normals.h @@ -152,9 +152,8 @@ jet_estimate_normal(const typename Kernel::Point_3& query, ///< point to compute \pre `k >= 2` - \tparam ConcurrencyTag enables sequential versus parallel algorithm. - Possible values are `Sequential_tag` - and `Parallel_tag`. + \tparam ConcurrencyTag enables sequential versus parallel algorithm. Possible values are `Sequential_tag`, + `Parallel_tag`, and `Parallel_if_available_tag`. \tparam PointRange is a model of `Range`. The value type of its iterator is the key type of the named parameter `point_map`. diff --git a/Point_set_processing_3/include/CGAL/jet_smooth_point_set.h b/Point_set_processing_3/include/CGAL/jet_smooth_point_set.h index fbe89bcd072..bde1da19f37 100644 --- a/Point_set_processing_3/include/CGAL/jet_smooth_point_set.h +++ b/Point_set_processing_3/include/CGAL/jet_smooth_point_set.h @@ -156,9 +156,8 @@ jet_smooth_point( \pre `k >= 2` - \tparam ConcurrencyTag enables sequential versus parallel algorithm. - Possible values are `Sequential_tag` - and `Parallel_tag`. + \tparam ConcurrencyTag enables sequential versus parallel algorithm. Possible values are `Sequential_tag`, + `Parallel_tag`, and `Parallel_if_available_tag`. \tparam PointRange is a model of `Range`. The value type of its iterator is the key type of the named parameter `point_map`. diff --git a/Point_set_processing_3/include/CGAL/pca_estimate_normals.h b/Point_set_processing_3/include/CGAL/pca_estimate_normals.h index 6d1fb05eca7..3a6ead3d5fd 100644 --- a/Point_set_processing_3/include/CGAL/pca_estimate_normals.h +++ b/Point_set_processing_3/include/CGAL/pca_estimate_normals.h @@ -142,9 +142,8 @@ pca_estimate_normal(const typename Kernel::Point_3& query, ///< point to compute \pre `k >= 2` - \tparam ConcurrencyTag enables sequential versus parallel algorithm. - Possible values are `Sequential_tag` - and `Parallel_tag`. + \tparam ConcurrencyTag enables sequential versus parallel algorithm. Possible values are `Sequential_tag`, + `Parallel_tag`, and `Parallel_if_available_tag`. \tparam PointRange is a model of `Range`. The value type of its iterator is the key type of the named parameter `point_map`. diff --git a/Point_set_processing_3/include/CGAL/wlop_simplify_and_regularize_point_set.h b/Point_set_processing_3/include/CGAL/wlop_simplify_and_regularize_point_set.h index 3055edc1b9b..cbe5b1ca5fb 100644 --- a/Point_set_processing_3/include/CGAL/wlop_simplify_and_regularize_point_set.h +++ b/Point_set_processing_3/include/CGAL/wlop_simplify_and_regularize_point_set.h @@ -411,9 +411,8 @@ public: See the TBB documentation for more details. - \tparam ConcurrencyTag enables sequential versus parallel algorithm. - Possible values are `Sequential_tag` - and `Parallel_tag`. + \tparam ConcurrencyTag enables sequential versus parallel algorithm. Possible values are `Sequential_tag`, + `Parallel_tag`, and `Parallel_if_available_tag`. \tparam PointRange is a model of `Range`. The value type of its iterator is the key type of the named parameter `point_map`. \tparam OutputIterator Type of the output iterator. diff --git a/Point_set_processing_3/test/Point_set_processing_3/analysis_test.cpp b/Point_set_processing_3/test/Point_set_processing_3/analysis_test.cpp index 63a68155087..df1603f8efc 100644 --- a/Point_set_processing_3/test/Point_set_processing_3/analysis_test.cpp +++ b/Point_set_processing_3/test/Point_set_processing_3/analysis_test.cpp @@ -33,12 +33,7 @@ typedef Kernel::FT FT; typedef Kernel::Point_3 Point; // Concurrency -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif - +typedef CGAL::Parallel_if_available_tag Concurrency_tag; // ---------------------------------------------------------------------------- // Tests diff --git a/Point_set_processing_3/test/Point_set_processing_3/edge_aware_upsample_test.cpp b/Point_set_processing_3/test/Point_set_processing_3/edge_aware_upsample_test.cpp index df0e92efc37..613bf126a06 100644 --- a/Point_set_processing_3/test/Point_set_processing_3/edge_aware_upsample_test.cpp +++ b/Point_set_processing_3/test/Point_set_processing_3/edge_aware_upsample_test.cpp @@ -36,12 +36,7 @@ typedef Kernel::Vector_3 Vector; typedef std::pair PointVectorPair; // Concurrency -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif - +typedef CGAL::Parallel_if_available_tag Concurrency_tag; // ---------------------------------------------------------------------------- // Tests diff --git a/Point_set_processing_3/test/Point_set_processing_3/normal_estimation_test.cpp b/Point_set_processing_3/test/Point_set_processing_3/normal_estimation_test.cpp index 1c640709039..36e0adf0320 100644 --- a/Point_set_processing_3/test/Point_set_processing_3/normal_estimation_test.cpp +++ b/Point_set_processing_3/test/Point_set_processing_3/normal_estimation_test.cpp @@ -45,12 +45,7 @@ typedef CGAL::Point_with_normal_3 Point_with_normal; // position + norma typedef std::vector PointList; // Concurrency -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif - +typedef CGAL::Parallel_if_available_tag Concurrency_tag; // ---------------------------------------------------------------------------- // Tests diff --git a/Point_set_processing_3/test/Point_set_processing_3/smoothing_test.cpp b/Point_set_processing_3/test/Point_set_processing_3/smoothing_test.cpp index 5dad79528f7..e5333343624 100644 --- a/Point_set_processing_3/test/Point_set_processing_3/smoothing_test.cpp +++ b/Point_set_processing_3/test/Point_set_processing_3/smoothing_test.cpp @@ -36,11 +36,7 @@ typedef Kernel::Point_3 Point; typedef Kernel::Vector_3 Vector; // Concurrency -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif +typedef CGAL::Parallel_if_available_tag Concurrency_tag; // ---------------------------------------------------------------------------- // Tests diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/hausdorff_distance_remeshing_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/hausdorff_distance_remeshing_example.cpp index 2830dc77768..1b032454d43 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/hausdorff_distance_remeshing_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/hausdorff_distance_remeshing_example.cpp @@ -3,11 +3,7 @@ #include #include -#if defined(CGAL_LINKED_WITH_TBB) -#define TAG CGAL::Parallel_tag -#else -#define TAG CGAL::Sequential_tag -#endif +#define TAG CGAL::Parallel_if_available_tag typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef K::Point_3 Point; diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/distance.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/distance.h index de52cfac3f2..f6500ea69f0 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/distance.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/distance.h @@ -589,8 +589,7 @@ double approximate_Hausdorff_distance( * for more details. * * @tparam Concurrency_tag enables sequential versus parallel algorithm. - * Possible values are `Sequential_tag` - * and `Parallel_tag`. + * Possible values are `Sequential_tag`, `Parallel_tag`, and `Parallel_if_available_tag`. * @tparam TriangleMesh a model of the concept `FaceListGraph` * @tparam NamedParameters1 a sequence of \ref pmp_namedparameters "Named Parameters" for `tm1` * @tparam NamedParameters2 a sequence of \ref pmp_namedparameters "Named Parameters" for `tm2` diff --git a/Polygonal_surface_reconstruction/include/CGAL/internal/compute_confidences.h b/Polygonal_surface_reconstruction/include/CGAL/internal/compute_confidences.h index 0c2ceafce8d..51eadd3ce7c 100644 --- a/Polygonal_surface_reconstruction/include/CGAL/internal/compute_confidences.h +++ b/Polygonal_surface_reconstruction/include/CGAL/internal/compute_confidences.h @@ -24,17 +24,10 @@ // Concurrency -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif - +typedef CGAL::Parallel_if_available_tag Concurrency_tag; namespace CGAL { - - - namespace internal { +namespace internal { /** * Computes the confidences of the candidate faces. diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.h index fd88c9e7507..090827a4c89 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.h @@ -15,12 +15,7 @@ #include -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif - +typedef CGAL::Parallel_if_available_tag Concurrency_tag; class Cluster_classification : public Item_classification_base { diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h index 3ddee5310c3..3eb2b503a4c 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h @@ -16,13 +16,7 @@ #include -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif - - +typedef CGAL::Parallel_if_available_tag Concurrency_tag; // This class represents a point set in the OpenGL scene class Point_set_item_classification : public Item_classification_base diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.h index e690a208951..0fcc827b04a 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.h @@ -16,11 +16,7 @@ #include -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif +typedef CGAL::Parallel_if_available_tag Concurrency_tag; class Surface_mesh_item_classification : public Item_classification_base { diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_average_spacing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_average_spacing_plugin.cpp index 13e9e0fa7db..037c7b5123d 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_average_spacing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_average_spacing_plugin.cpp @@ -20,11 +20,7 @@ #include "run_with_qprogressdialog.h" // Concurrency -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif +typedef CGAL::Parallel_if_available_tag Concurrency_tag; struct Compute_average_spacing_functor : public Functor_with_signal_callback diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_bilateral_smoothing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_bilateral_smoothing_plugin.cpp index 14c45d7391b..2da04eef9d3 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_bilateral_smoothing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_bilateral_smoothing_plugin.cpp @@ -21,11 +21,7 @@ #include "ui_Point_set_bilateral_smoothing_plugin.h" // Concurrency -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif +typedef CGAL::Parallel_if_available_tag Concurrency_tag; struct Bilateral_smoothing_functor : public Functor_with_signal_callback diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_interference_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_interference_plugin.cpp index c20a2096421..5860a4c7239 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_interference_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_interference_plugin.cpp @@ -16,11 +16,8 @@ #include using namespace CGAL::Three; -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif + +typedef CGAL::Parallel_if_available_tag Concurrency_tag; class Point_set_interference_plugin: public QObject, diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_normal_estimation_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_normal_estimation_plugin.cpp index 89ef88a006a..c8cea0f5343 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_normal_estimation_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_normal_estimation_plugin.cpp @@ -25,11 +25,7 @@ #include "ui_Point_set_normal_estimation_plugin.h" // Concurrency -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif +typedef CGAL::Parallel_if_available_tag Concurrency_tag; struct PCA_estimate_normals_functor : public Functor_with_signal_callback diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_simplification_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_simplification_plugin.cpp index 9d838794b69..b08cbb27860 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_simplification_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_simplification_plugin.cpp @@ -22,11 +22,7 @@ #include "ui_Point_set_simplification_plugin.h" // Concurrency -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif +typedef CGAL::Parallel_if_available_tag Concurrency_tag; struct Compute_average_spacing_functor : public Functor_with_signal_callback diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_smoothing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_smoothing_plugin.cpp index 1436a2b4ae5..ac883acf29f 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_smoothing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_smoothing_plugin.cpp @@ -15,11 +15,7 @@ #include "run_with_qprogressdialog.h" // Concurrency -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif +typedef CGAL::Parallel_if_available_tag Concurrency_tag; struct Jet_smoothing_functor : public Functor_with_signal_callback diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_upsampling_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_upsampling_plugin.cpp index 2fba3abfcb8..ca4042b9949 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_upsampling_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_upsampling_plugin.cpp @@ -19,12 +19,8 @@ #include "ui_Point_set_upsampling_plugin.h" // Concurrency -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif - +typedef CGAL::Parallel_if_available_tag Concurrency_tag; + using namespace CGAL::Three; class Polyhedron_demo_point_set_upsampling_plugin : public QObject, diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_wlop_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_wlop_plugin.cpp index 561b849c4f0..f9ab5c60215 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_wlop_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_wlop_plugin.cpp @@ -20,11 +20,7 @@ #include "ui_Point_set_wlop_plugin.h" // Concurrency -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif +typedef CGAL::Parallel_if_available_tag Concurrency_tag; struct Compute_average_spacing_functor : public Functor_with_signal_callback diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Surface_reconstruction_poisson_impl.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Surface_reconstruction_poisson_impl.cpp index 77511d670f4..8b089d385b6 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Surface_reconstruction_poisson_impl.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Surface_reconstruction_poisson_impl.cpp @@ -25,14 +25,8 @@ #include "SMesh_type.h" #include "Scene_points_with_normal_item.h" - - // Concurrency -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif +typedef CGAL::Parallel_if_available_tag Concurrency_tag; template class Marching_tets diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Surface_reconstruction_scale_space_impl.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Surface_reconstruction_scale_space_impl.cpp index 582bad37820..7f15fb61174 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Surface_reconstruction_scale_space_impl.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Surface_reconstruction_scale_space_impl.cpp @@ -13,11 +13,7 @@ // Concurrency -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif +typedef CGAL::Parallel_if_available_tag Concurrency_tag; typedef CGAL::Scale_space_surface_reconstruction_3 ScaleSpace; typedef CGAL::Scale_space_reconstruction_3::Advancing_front_mesher ScaleSpaceAFM; diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/VSA_wrapper.h b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/VSA_wrapper.h index f43b6c94d48..c876ba84680 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/VSA_wrapper.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/VSA_wrapper.h @@ -38,23 +38,13 @@ class VSA_WRAPPER_EXPORT VSA_wrapper { typedef boost::property_map::type Face_center_map; typedef boost::property_map::type Face_area_map; -#ifdef CGAL_LINKED_WITH_TBB typedef CGAL::Variational_shape_approximation L21_approx; -#else - typedef CGAL::Variational_shape_approximation L21_approx; -#endif + CGAL::Default, EPICK, CGAL::Parallel_if_available_tag> L21_approx; typedef L21_approx::Error_metric L21_metric; typedef VSA::L2_metric_plane_proxy L2_metric; -#ifdef CGAL_LINKED_WITH_TBB typedef CGAL::Variational_shape_approximation L2_approx; -#else - typedef CGAL::Variational_shape_approximation L2_approx; -#endif + L2_metric, EPICK, CGAL::Parallel_if_available_tag> L2_approx; // user defined point-wise compact metric struct Compact_metric_point_proxy { @@ -89,14 +79,8 @@ class VSA_WRAPPER_EXPORT VSA_wrapper { }; typedef Compact_metric_point_proxy Compact_metric; -#ifdef CGAL_LINKED_WITH_TBB typedef CGAL::Variational_shape_approximation Compact_approx; -#else - typedef CGAL::Variational_shape_approximation Compact_approx; -#endif - + Compact_metric, EPICK, CGAL::Parallel_if_available_tag> Compact_approx; public: enum Metric { L21, L2, Compact }; diff --git a/Polyhedron/demo/Polyhedron/include/run_with_qprogressdialog.h b/Polyhedron/demo/Polyhedron/include/run_with_qprogressdialog.h index f1bef8fb5fd..3faa3173db4 100644 --- a/Polyhedron/demo/Polyhedron/include/run_with_qprogressdialog.h +++ b/Polyhedron/demo/Polyhedron/include/run_with_qprogressdialog.h @@ -7,12 +7,7 @@ #include "Callback_signaler.h" -#ifdef CGAL_LINKED_WITH_TBB -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif - +typedef CGAL::Parallel_if_available_tag Concurrency_tag; class Signal_callback { diff --git a/STL_Extension/include/CGAL/tags.h b/STL_Extension/include/CGAL/tags.h index 2b88992794b..8feef206784 100644 --- a/STL_Extension/include/CGAL/tags.h +++ b/STL_Extension/include/CGAL/tags.h @@ -63,7 +63,6 @@ typedef CGAL::Parallel_tag Parallel_if_available_tag; #else typedef CGAL::Sequential_tag Parallel_if_available_tag; #endif - // A function that asserts a specific compile time tag // forcing its two arguments to have equal type. diff --git a/Scale_space_reconstruction_3/include/CGAL/Scale_space_reconstruction_3/Jet_smoother.h b/Scale_space_reconstruction_3/include/CGAL/Scale_space_reconstruction_3/Jet_smoother.h index 49d00554dca..f881e8f23e4 100644 --- a/Scale_space_reconstruction_3/include/CGAL/Scale_space_reconstruction_3/Jet_smoother.h +++ b/Scale_space_reconstruction_3/include/CGAL/Scale_space_reconstruction_3/Jet_smoother.h @@ -39,17 +39,15 @@ namespace Scale_space_reconstruction_3 * `RealEmbeddable` field number type. Generally, * `Exact_predicates_inexact_constructions_kernel` is preferred. * \tparam ConcurrencyTag indicates whether to use concurrent - * processing. It can be omitted: if TBB (or greater) is available + * processing. It can be omitted: if \ref thirdpartyTBB is available * and `CGAL_LINKED_WITH_TBB` is defined then `Parallel_tag` is * used. Otherwise, `Sequential_tag` is used. */ template -#elif CGAL_LINKED_WITH_TBB - typename ConcurrencyTag = CGAL::Parallel_tag> #else - typename ConcurrencyTag = CGAL::Sequential_tag> + typename ConcurrencyTag = CGAL::Parallel_if_available_tag> #endif class Jet_smoother { diff --git a/Scale_space_reconstruction_3/include/CGAL/Scale_space_reconstruction_3/Weighted_PCA_smoother.h b/Scale_space_reconstruction_3/include/CGAL/Scale_space_reconstruction_3/Weighted_PCA_smoother.h index 2b21cae546f..50cc72b4c9c 100644 --- a/Scale_space_reconstruction_3/include/CGAL/Scale_space_reconstruction_3/Weighted_PCA_smoother.h +++ b/Scale_space_reconstruction_3/include/CGAL/Scale_space_reconstruction_3/Weighted_PCA_smoother.h @@ -55,21 +55,17 @@ namespace Scale_space_reconstruction_3 * that case, an overload using `Eigen_diagonalize_traits` is * provided. * \tparam ConcurrencyTag indicates whether to use concurrent - * processing. It can be omitted: if TBB (or greater) is available + * processing. It can be omitted: if \ref thirdpartyTBB is available * and `CGAL_LINKED_WITH_TBB` is defined then `Parallel_tag` is * used. Otherwise, `Sequential_tag` is used. */ template + typename DiagonalizeTraits, + typename ConcurrencyTag> #else // DOXYGEN_RUNNING - typename DiagonalizeTraits - = CGAL::Default_diagonalize_traits, -#ifdef CGAL_LINKED_WITH_TBB - typename ConcurrencyTag = CGAL::Parallel_tag> -#else - typename ConcurrencyTag = CGAL::Sequential_tag> -#endif // CGAL_LINKED_WITH_TBB + typename DiagonalizeTraits = CGAL::Default_diagonalize_traits, + typename ConcurrencyTag = CGAL::Parallel_if_available_tag> #endif // DOXYGEN_RUNNING class Weighted_PCA_smoother { diff --git a/TDS_3/doc/TDS_3/CGAL/Triangulation_data_structure_3.h b/TDS_3/doc/TDS_3/CGAL/Triangulation_data_structure_3.h index 742ea25c03c..a53e0ddb411 100644 --- a/TDS_3/doc/TDS_3/CGAL/Triangulation_data_structure_3.h +++ b/TDS_3/doc/TDS_3/CGAL/Triangulation_data_structure_3.h @@ -26,7 +26,7 @@ They have the default values `Triangulation_ds_vertex_base_3` and The `Concurrency_tag` parameter allows to enable the use of a concurrent container to store vertices and cells. It can be `Sequential_tag` (use of a -`Compact_container` to store vertices and cells) or `Parallel_tag` +`Compact_container` to store vertices and cells) or `Parallel_tag` (use of a `Concurrent_compact_container`). If it is `Parallel_tag`, the following functions can be called concurrently: `create_vertex`, `create_cell`, `delete_vertex`, `delete_cell`. diff --git a/TDS_3/doc/TDS_3/Concepts/TriangulationDataStructure_3.h b/TDS_3/doc/TDS_3/Concepts/TriangulationDataStructure_3.h index 175a64c4e20..7fd2a1a10bc 100644 --- a/TDS_3/doc/TDS_3/Concepts/TriangulationDataStructure_3.h +++ b/TDS_3/doc/TDS_3/Concepts/TriangulationDataStructure_3.h @@ -111,7 +111,7 @@ typedef unspecified_type Vertex_handle; typedef unspecified_type Cell_handle; /*! -Can be `CGAL::Sequential_tag` or `CGAL::Parallel_tag`. If it is +Can be `CGAL::Sequential_tag`, `CGAL::Parallel_tag`, or `Parallel_if_available_tag`. If it is `CGAL::Parallel_tag`, the following functions can be called concurrently: `create_vertex`, `create_cell`, `delete_vertex`, `delete_cell`. */ From 9b598c4ee6f68482a36cf43b9324dc1829d18b16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 20 Nov 2019 12:36:05 +0100 Subject: [PATCH 064/185] Remove mentions of targets that do not exist in CmakeLists of Mesh_3/test --- Mesh_3/test/Mesh_3/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/Mesh_3/test/Mesh_3/CMakeLists.txt b/Mesh_3/test/Mesh_3/CMakeLists.txt index 03f021a7172..731686b660b 100644 --- a/Mesh_3/test/Mesh_3/CMakeLists.txt +++ b/Mesh_3/test/Mesh_3/CMakeLists.txt @@ -65,12 +65,10 @@ if ( CGAL_FOUND ) test_meshing_verbose test_meshing_polyhedron_with_features test_meshing_utilities.h - test_mesh_implicit_domains test_meshing_implicit_function test_meshing_3D_image test_meshing_3D_gray_image test_meshing_unit_tetrahedron - test_backward_compatibility test_meshing_polyhedron test_meshing_polyhedral_complex ) From 6f0bbc90df6b3668f7bc2c3cd5618375f295cad8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 20 Nov 2019 12:38:56 +0100 Subject: [PATCH 065/185] Enable parallel for three tests in Mesh_3/test that relied on CONCURRENT_MESH_3 The macro was never defined and if it had been, the targets would not have been linked properly anyway. --- Mesh_3/test/Mesh_3/CMakeLists.txt | 3 +++ Mesh_3/test/Mesh_3/test_mesh_3_issue_1554.cpp | 6 +----- .../test/Mesh_3/test_mesh_capsule_var_distance_bound.cpp | 6 +----- ...est_mesh_polyhedral_domain_with_features_deprecated.cpp | 7 +------ 4 files changed, 6 insertions(+), 16 deletions(-) diff --git a/Mesh_3/test/Mesh_3/CMakeLists.txt b/Mesh_3/test/Mesh_3/CMakeLists.txt index 731686b660b..525573cbeb4 100644 --- a/Mesh_3/test/Mesh_3/CMakeLists.txt +++ b/Mesh_3/test/Mesh_3/CMakeLists.txt @@ -71,6 +71,9 @@ if ( CGAL_FOUND ) test_meshing_unit_tetrahedron test_meshing_polyhedron test_meshing_polyhedral_complex + test_mesh_capsule_var_distance_bound + test_mesh_3_issue_1554 + test_mesh_polyhedral_domain_with_features_deprecated ) if(TBB_FOUND AND TARGET ${target}) CGAL_target_use_TBB(${target}) diff --git a/Mesh_3/test/Mesh_3/test_mesh_3_issue_1554.cpp b/Mesh_3/test/Mesh_3/test_mesh_3_issue_1554.cpp index 24c7bb6f445..c64f5455ffb 100644 --- a/Mesh_3/test/Mesh_3/test_mesh_3_issue_1554.cpp +++ b/Mesh_3/test/Mesh_3/test_mesh_3_issue_1554.cpp @@ -18,11 +18,7 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef CGAL::Mesh_polyhedron_3::type Polyhedron; typedef CGAL::Polyhedral_mesh_domain_with_features_3 Mesh_domain; -#ifdef CGAL_CONCURRENT_MESH_3 -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif +typedef CGAL::Parallel_if_available_tag Concurrency_tag; // Triangulation typedef CGAL::Mesh_triangulation_3 Mesh_domain; -#ifdef CGAL_CONCURRENT_MESH_3 -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif +typedef CGAL::Parallel_if_available_tag Concurrency_tag; // Triangulation typedef CGAL::Mesh_triangulation_3::type Tr; diff --git a/Mesh_3/test/Mesh_3/test_mesh_polyhedral_domain_with_features_deprecated.cpp b/Mesh_3/test/Mesh_3/test_mesh_polyhedral_domain_with_features_deprecated.cpp index 26e7093cb91..5fd13080c01 100644 --- a/Mesh_3/test/Mesh_3/test_mesh_polyhedral_domain_with_features_deprecated.cpp +++ b/Mesh_3/test/Mesh_3/test_mesh_polyhedral_domain_with_features_deprecated.cpp @@ -14,12 +14,7 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef CGAL::Mesh_polyhedron_3::type Polyhedron; typedef CGAL::Polyhedral_mesh_domain_with_features_3 Mesh_domain; - -#ifdef CGAL_CONCURRENT_MESH_3 -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif +typedef CGAL::Parallel_if_available_tag Concurrency_tag; // Triangulation typedef CGAL::Mesh_triangulation_3::type Tr; From 1287db1138fe768dfa07d13d9ea06b987f8ffa07 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 15 Nov 2019 12:48:16 +0100 Subject: [PATCH 066/185] CGAL:: Add Parallel_if_available_tag --- STL_Extension/include/CGAL/tags.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/STL_Extension/include/CGAL/tags.h b/STL_Extension/include/CGAL/tags.h index 4b033abaf32..2b88992794b 100644 --- a/STL_Extension/include/CGAL/tags.h +++ b/STL_Extension/include/CGAL/tags.h @@ -26,7 +26,7 @@ namespace CGAL { struct Void {}; // Boolean_tag is a model of the Boost Integral Constant concept. -// https://www.boost.org/libs/mpl/doc/refmanual/integral-constant.html +// https://www.boost.org/libs/mpl/doc/refmanual/integral-constant.html template struct Boolean_tag { typedef boost::mpl::integral_c_tag tag; @@ -58,6 +58,13 @@ struct Null_functor { struct Sequential_tag {}; struct Parallel_tag : public Sequential_tag {}; +#ifdef CGAL_LINKED_WITH_TBB +typedef CGAL::Parallel_tag Parallel_if_available_tag; +#else +typedef CGAL::Sequential_tag Parallel_if_available_tag; +#endif + + // A function that asserts a specific compile time tag // forcing its two arguments to have equal type. template From 902183b701646a5d64ffcc535e49382e5d465229 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Sat, 23 Nov 2019 15:20:49 +0100 Subject: [PATCH 067/185] Use Parallel_if_available_tag --- Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_2.h | 2 +- Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_3.h | 2 +- Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h | 4 ++-- Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h | 4 ++-- Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt | 3 ++- .../examples/Spatial_sorting/parallel_spatial_sort_2.cpp | 6 +++--- 6 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_2.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_2.h index 1dc58ed45b3..5f5b006e003 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_2.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_2.h @@ -13,7 +13,7 @@ or the middle depending on the `PolicyTag`. \tparam PolicyTag must be `Hilbert_sort_median_policy` or `Hilbert_sort_middle_policy`. -\tparam ConcurrencyTag must be `Sequential_tag` or `Parallel_tag`. With `Parallel_tag` +\tparam ConcurrencyTag must be `Sequential_tag`, `Parallel_tag`, or `Parallel_if_available_tag. With parallelism and TBB enabled, for the median policy up to four threads are used in parallel. */ template< typename Traits, typename PolicyTag, typename ConcurrencyTag = Sequential_tag > diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_3.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_3.h index e08f0b4a39c..bb366239adc 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_3.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_3.h @@ -11,7 +11,7 @@ or the middle depending on the `PolicyTag`. \tparam PolicyTag must be `Hilbert_sort_median_policy` or `Hilbert_sort_middle_policy`. -\tparam ConcurrencyTag must be `Sequential_tag` or `Parallel_tag`. With `Parallel_tag` +\tparam ConcurrencyTag must be `Sequential_tag`,`Parallel_tag`, or `Parallel_if_available_tag`. With parallelism and TBB enabled, for the median policy up to eight threads are used in parallel. */ template< typename Traits, typename PolicyTag, typename ConcurrencyTag = Sequential_tag > diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h index 89b94118aea..a6d77e5cf80 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h @@ -8,8 +8,8 @@ along a Hilbert curve. It sorts the range `[begin, end)` in place. -\tparam ConcurrencyTag must be `Sequential_tag` or `Parallel_tag`. -With `Parallel_tag` and TBB enabled, the sorting will be +\tparam ConcurrencyTag must be `Sequential_tag`, `Parallel_tag`, or `Parallel_if_available_tag`. +With parallelism and TBB enabled, the sorting will be done using up to four threads in 2D, and up to eight threads in 3D with the median policy. \tparam RandomAccessIterator diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h index 7d5d15b83c6..4beac521426 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h @@ -10,8 +10,8 @@ of being close in the order. It sorts the range `[begin, end)` in place. -\tparam ConcurrencyTag must be `Sequential_tag` or `Parallel_tag`. -With `Parallel_tag` and TBB enabled, the sorting will be +\tparam ConcurrencyTag must be `Sequential_tag`, `Parallel_tag`, or `Parallel_if_available_tag`. +With parallelism and TBB enabled, the sorting will be done using up to four threads in 2D, and up to eight threads in 3D with the median policy. \tparam RandomAccessIterator `std::iterator_traits::%value_type` must be convertible to diff --git a/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt b/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt index 3d4329c9f6d..ec6924332cb 100644 --- a/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt +++ b/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt @@ -214,7 +214,8 @@ The Hilbert sort and spatial sort functions when using the median policy and wit enabled, are parallized and use up to four/eight threads for 2D/3D. By default the sequential version is used. The parallel version is used -by adding the template parameter `CGAL::Parallel_tag`. +by adding the template parameter `CGAL::Parallel_tag`. In case it is not sure +whether TBB is enabled use `CGAL::Parallel_if_available_tag`. \cgalExample{Spatial_sorting/parallel_spatial_sort_2.cpp} diff --git a/Spatial_sorting/examples/Spatial_sorting/parallel_spatial_sort_2.cpp b/Spatial_sorting/examples/Spatial_sorting/parallel_spatial_sort_2.cpp index eb9ffed6303..ee5d788c6ef 100644 --- a/Spatial_sorting/examples/Spatial_sorting/parallel_spatial_sort_2.cpp +++ b/Spatial_sorting/examples/Spatial_sorting/parallel_spatial_sort_2.cpp @@ -26,9 +26,9 @@ int main() // By default sequential CGAL::spatial_sort(points.begin(),points.end()); - // Add the template argument to switch on parallelism - // You will get a compile time warning in case TBB is not enabled - CGAL::spatial_sort(points.begin(),points.end()); + // Add the template argument to switch on parallelism if available + // You can also use Parallel_tag if you know that TBB is enabled + CGAL::spatial_sort(points.begin(),points.end()); return 0; } From d302c56d056521af4a8bdccf0477504a799e062c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 2 Dec 2019 15:01:26 +0100 Subject: [PATCH 068/185] Keep a single version (3 split) of parallel box_intersection_d --- .../include/CGAL/box_intersection_d.h | 87 +++++-------------- 1 file changed, 23 insertions(+), 64 deletions(-) diff --git a/Box_intersection_d/include/CGAL/box_intersection_d.h b/Box_intersection_d/include/CGAL/box_intersection_d.h index ff0698dd780..ca0683a0a67 100644 --- a/Box_intersection_d/include/CGAL/box_intersection_d.h +++ b/Box_intersection_d/include/CGAL/box_intersection_d.h @@ -34,7 +34,10 @@ #include #include -#include + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// THE CALLBACK MUST BE THREADSAFE IF YOU ARE USING THE PARALLEL MODE +//////////////////////////////////////////////////////////////////////////////////////////////// namespace CGAL { namespace internal { @@ -65,51 +68,29 @@ void box_intersection_segment_tree_d( #else // CGAL_LINKED_WITH_TBB if(boost::is_convertible::value) { - unsigned thread_n = std::thread::hardware_concurrency(); - std::cout << thread_n << " threads" << std::endl; - - // TODO: Check which of the two following approaches is better - // The first one makes three copies of the vector and performs four parallel tasks - // The second one makes one copy, but must perform two times two parallel tasks (can't - // do all four at the same time otherwise the sort / split will conflict) -#ifdef CGAL_BOX_INTER_ONE_SPLIT // cuts in 2 --> 2 copies of each vector, 9 pairs - std::cout << "Split in 2" << std::endl; - - typedef typename std::iterator_traits::value_type val_t; - - typename std::iterator_traits::difference_type r1_half = std::distance(begin1, end1) / 2; - typename std::iterator_traits::difference_type r2_half = std::distance(begin2, end2) / 2; - - std::vector< val_t> r3( begin1, end1); - std::vector< val_t> r4( begin2, end2); - - RandomAccessIter1 mid1 = begin1; - std::advance(mid1, r1_half); - RandomAccessIter2 mid2 = begin2; - std::advance(mid2, r2_half); - typename std::vector< val_t>::iterator mid3 = r3.begin(); - std::advance(mid3, r1_half); - typename std::vector< val_t>::iterator mid4 = r4.begin(); - std::advance(mid4, r2_half); - - tbb::parallel_invoke([&]{ Box_intersection_d::segment_tree( begin1, mid1, begin2, mid2, inf, sup, - callback, traits, cutoff, dim, in_order); }, - [&]{ Box_intersection_d::segment_tree( mid1, end1, mid2, end2, inf, sup, - callback, traits, cutoff, dim, in_order); }, - [&]{ Box_intersection_d::segment_tree( r3.begin(), mid3, mid4, r4.end(), inf, sup, - callback, traits, cutoff, dim, in_order); }, - [&]{ Box_intersection_d::segment_tree( mid3, r3.end(), r4.begin(), mid4, inf, sup, - callback, traits, cutoff, dim, in_order); } ); -#elif defined(CGAL_BOX_INTER_TWO_SPLIT) // cuts in 3 --> 3 copies of each vector, 9 pairs - std::cout << "Split in 3" << std::endl; - + // Below takes both box ranges and split each range in 3, and then does cross products + // to get all combinations (9 pairs). + // + // 3 is chosen such that we get 9 tasks in parallel, which is close to the usual number + // of threads (8-12) on a (current) "normal" machine. This could potentially be generalized + // by grabbing the number of available threads (n = std::thread::hardware_concurrency()) and + // splitting in 'i' and 'j' such that i*j=n. + // + // The memory footprint due to having to duplicate box ranges is empirically observed + // to be negligible (as long as a range of pointers is passed) + // typedef typename std::iterator_traits::value_type val_t; - typedef typename std::vector< val_t>::iterator It; + typedef typename std::vector< val_t>::iterator It; typename std::iterator_traits::difference_type r1_third = std::distance(begin1, end1) / 3; - typename std::iterator_traits::difference_type r1_two_third = 2 * std::distance(begin1, end1) / 3; + typename std::iterator_traits::difference_type r1_two_third = 2 * r1_third; typename std::iterator_traits::difference_type r2_third = std::distance(begin2, end2) / 3; - typename std::iterator_traits::difference_type r2_two_third = 2 * std::distance(begin2, end2) / 3; + typename std::iterator_traits::difference_type r2_two_third = 2 * r2_third; + + CGAL_assertion(0 <= r1_third && r1_third <= r1_two_third && + (r1_two_third < std::distance(begin1, end1) || std::distance(begin1, end1) == 0)); + CGAL_assertion(0 <= r2_third && r2_third <= r2_two_third && + (r2_two_third < std::distance(begin2, end2) || std::distance(begin2, end2) == 0)); std::vector< val_t> r3( begin1, end1); std::vector< val_t> r4( begin2, end2); @@ -152,28 +133,6 @@ void box_intersection_segment_tree_d( callback, traits, cutoff, dim, in_order); }, [&]{ Box_intersection_d::segment_tree( r5_right, r5.end(), r6_left, r6_right, inf, sup, callback, traits, cutoff, dim, in_order); } ); - -#else - std::cout << "2x2" << std::endl; - - typename std::iterator_traits::difference_type r1_half = std::distance(begin1, end1) / 2; - typename std::iterator_traits::difference_type r2_half = std::distance(begin2, end2) / 2; - - RandomAccessIter1 mid1 = begin1; - std::advance(mid1, r1_half); - RandomAccessIter2 mid2 = begin2; - std::advance(mid2, r2_half); - - tbb::parallel_invoke([&]{ Box_intersection_d::segment_tree( begin1, mid1, begin2, mid2, inf, sup, - callback, traits, cutoff, dim, in_order); }, - [&]{ Box_intersection_d::segment_tree( mid1, end1, mid2, end2, inf, sup, - callback, traits, cutoff, dim, in_order); } ); - tbb::parallel_invoke([&]{ Box_intersection_d::segment_tree( begin1, mid1, mid2, end2, inf, sup, - callback, traits, cutoff, dim, in_order); }, - [&]{ Box_intersection_d::segment_tree( mid1, end1, begin2, mid2, inf, sup, - callback, traits, cutoff, dim, in_order); } ); - -#endif // CGAL_BOX_INTER_FOUR_RANGES } else #endif // CGAL_LINKED_WITH_TBB From 82bf0f22f17e451182424cb575f92b9a48946fd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 2 Dec 2019 15:01:50 +0100 Subject: [PATCH 069/185] Test parallel box_intersection_d and ptr-based box_intersection_d --- .../test/Box_intersection_d/CMakeLists.txt | 19 +- .../test/Box_intersection_d/test_box_grid.cpp | 426 +++++++++++------- 2 files changed, 264 insertions(+), 181 deletions(-) diff --git a/Box_intersection_d/test/Box_intersection_d/CMakeLists.txt b/Box_intersection_d/test/Box_intersection_d/CMakeLists.txt index 1beb02ff8d0..6f4ec1704ce 100644 --- a/Box_intersection_d/test/Box_intersection_d/CMakeLists.txt +++ b/Box_intersection_d/test/Box_intersection_d/CMakeLists.txt @@ -5,20 +5,23 @@ cmake_minimum_required(VERSION 3.1...3.15) project( Box_intersection_d_Tests ) +find_package( CGAL QUIET ) -find_package(CGAL QUIET) +find_package( TBB ) if ( CGAL_FOUND ) - # create a target per cppfile - file(GLOB cppfiles RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) - foreach(cppfile ${cppfiles}) - create_single_source_cgal_program( "${cppfile}" ) - endforeach() + create_single_source_cgal_program( "automated_test.cpp" ) + create_single_source_cgal_program( "benchmark_box_intersection.cpp" ) + create_single_source_cgal_program( "random_set_test.cpp" ) + create_single_source_cgal_program( "test_box_grid.cpp" ) + if( TBB_FOUND ) + CGAL_target_use_TBB( test_box_grid ) + else() + message( STATUS "NOTICE: Intel TBB was not found. Sequential code will be used." ) + endif() else() - message(STATUS "This program requires the CGAL library, and will not be compiled.") - endif() diff --git a/Box_intersection_d/test/Box_intersection_d/test_box_grid.cpp b/Box_intersection_d/test/Box_intersection_d/test_box_grid.cpp index 4d51695b9bd..0b06520214f 100644 --- a/Box_intersection_d/test/Box_intersection_d/test_box_grid.cpp +++ b/Box_intersection_d/test/Box_intersection_d/test_box_grid.cpp @@ -1,217 +1,297 @@ // file: test/Box_intersection_d/box_grid.C // similar to examples/Box_intersection_d/box_grid.C but stricter in checking // and more extensive in what is tested. -#include -#include -#include -#include -#include -typedef CGAL::Box_intersection_d::Box_d Box; +#include +#include + +#include +#include +#include +#include + +#ifdef CGAL_LINKED_WITH_TBB +#include +#endif + +typedef CGAL::Box_intersection_d::Box_d Box; // coordinates for 9 boxes of a grid int p[9*4] = { 0,0,1,1, 1,0,2,1, 2,0,3,1, // lower 0,1,1,2, 1,1,2,2, 2,1,3,2, // middle 0,2,1,3, 1,2,2,3, 2,2,3,3};// upper // 9 boxes + 2 selected boxes as query; center and upper right -Box init_boxes[11] = { Box( p, p+ 2), Box( p+ 4, p+ 6), Box( p+ 8, p+10), - Box( p+12, p+14), Box( p+16, p+18), Box( p+20, p+22), - Box( p+24, p+26), Box( p+28, p+30), Box( p+32, p+34), - Box( p+16, p+18), Box( p+32, p+34)}; +const Box init_boxes[11] = { Box( p, p+ 2), Box( p+ 4, p+ 6), Box( p+ 8, p+10), + Box( p+12, p+14), Box( p+16, p+18), Box( p+20, p+22), + Box( p+24, p+26), Box( p+28, p+30), Box( p+32, p+34), + Box( p+16, p+18), Box( p+32, p+34)}; Box boxes[11]; Box* query = boxes+9; -void init() { - for ( int i = 0; i < 11; ++i) - boxes[i] = init_boxes[i]; +void init() +{ + for ( int i = 0; i < 11; ++i) + boxes[i] = init_boxes[i]; } -void check_result( const char* text, std::vector& result, - const std::size_t* check, std::size_t size) { - // sort, show, and check result - std::sort( result.begin(), result.end()); - std::cout << text << ": got " << result.size() << " elements, expected " - << size << " elements\n got : "; - std::copy( result.begin(), result.end(), - std::ostream_iterator( std::cout, ",")); - std::cout << "\n expected: "; - std::copy( check, check+size, - std::ostream_iterator( std::cout, ",")); - std::cout << '\n' << std::endl; - assert( result.size() == size - && std::equal( check, check+size, result.begin())); +template +void check_result( const char* text, + Vector& result, + const std::size_t* check, + std::size_t size) +{ + // sort, show, and check result + std::sort( result.begin(), result.end()); + std::cout << text << ": got " << result.size() << " elements, expected " + << size << " elements\n got : "; + std::copy( result.begin(), result.end(), + std::ostream_iterator( std::cout, ",")); + std::cout << "\n expected: "; + std::copy( check, check+size, + std::ostream_iterator( std::cout, ",")); + std::cout << '\n' << std::endl; + assert( result.size() == size + && std::equal( check, check+size, result.begin())); } // callback function object writing results to an output iterator -template -struct Report { - OutputIterator it; - Report( OutputIterator i) : it(i) {} // store iterator in object - // We encode both id-numbers in a single number, a.id() + 100 * b.id(), - // and write that number to the output iterator. - void operator()( const Box& a, const Box& b) { *it++ = a.id()+100*b.id(); } +template +struct Report +{ + Container& c_; + + Report(Container& c) : c_(c) {} // store iterator in object + // We encode both id-numbers in a single number, a.id() + 100 * b.id(), + // and write that number to the output iterator. + void operator()(const Box& a, const Box& b) { c_.push_back(a.id()+100*b.id()); } + void operator()(const Box* a, const Box* b) { c_.push_back(a->id()+100*b->id()); } }; -template // helper function to create the function object -Report report( Iter it) { return Report(it); } + +template // helper function to create the function object +Report report(Container& c) { return Report(c); } // --------------------------------------------------------------------- // box_intersection_d // run the intersection algorithms and store results in a vector // --------------------------------------------------------------------- -void test_box_intersection() { - // intersect 3x3 with 2 query boxes, closed boxes - init(); - std::vector result; - CGAL::box_intersection_d( boxes, boxes+9, query, query+2, - report( std::back_inserter( result))); - std::size_t check1[13] = {900,901,902,903,904,905,906,907,908, - 1004,1005,1007,1008}; - check_result( "Box inters. 3x3, 2, closed", result, check1, 13); +void test_box_intersection() +{ +#ifdef CGAL_LINKED_WITH_TBB + tbb::concurrent_vector result; +#else + std::vector result; +#endif - // intersect 3x3 with 2 query boxes, half-open boxes and changed cutoff - init(); - result.clear(); - CGAL::box_intersection_d( boxes, boxes+9, query, query+2, - report( std::back_inserter( result)), - std::ptrdiff_t(1), - CGAL::Box_intersection_d::HALF_OPEN); - std::size_t check2[2] = {904,1008}; - check_result( "Box inters. 3x3, 2, half-open", result, check2, 2); + // Some degenerate cases + init(); + CGAL::box_intersection_d(boxes, boxes, boxes, boxes, + report(result)); + assert(result.empty()); - // self intersect 3x2, closed boxes - init(); - result.clear(); - CGAL::box_self_intersection_d( boxes, boxes+6, - report( std::back_inserter( result))); - std::size_t check3[11] = {1,3,4,102,103,104,105,204,205,304,405}; - check_result( "Box self inters. 3x2, closed", result, check3, 11); + init(); + CGAL::box_intersection_d(boxes, boxes, query, query + 1, + report(result)); + assert(result.empty()); - // self intersect 3x2, half-open boxes - init(); - result.clear(); - CGAL::box_self_intersection_d( boxes, boxes+6, - report( std::back_inserter( result)), - std::ptrdiff_t(1), - CGAL::Box_intersection_d::HALF_OPEN); - std::size_t check4[1] = {9999}; - check_result( "Box self inters. 3x2, half-open", result, check4, 0); + init(); + CGAL::box_intersection_d(boxes, boxes + 3, query, query, + report(result)); + assert(result.empty()); - // self intersect 3x3+2 query boxes, half-open boxes - init(); - result.clear(); - CGAL::box_self_intersection_d( boxes, boxes+11, - report( std::back_inserter( result)), - std::ptrdiff_t(1), - CGAL::Box_intersection_d::HALF_OPEN); - std::size_t check5[2] = {409,810}; - check_result( "Box self inters. 3x3+2, half-open", result, check5, 2); + // With pointers + init(); + std::vector range_1 = {{ boxes, boxes+1, boxes+2, boxes+3, boxes+4, boxes+5, + boxes+6, boxes+7, boxes+8 }}; + std::vector range_2 = {{ query, query+1 }}; - // self intersect 3x3+2 query boxes, half-open boxes, full function interf. - // tests also mixed types for the two iterator ranges - init(); - result.clear(); - std::vector boxes2( boxes, boxes+11); - CGAL::box_intersection_d( boxes, boxes+11, boxes2.begin(), boxes2.end(), - report( std::back_inserter( result)), - std::ptrdiff_t(1), - CGAL::Box_intersection_d::HALF_OPEN, - CGAL::Box_intersection_d::COMPLETE); - check_result( "Box inters. 3x3+2, half-open", result, check5, 2); - - // compare this with the bipartite case - // self intersect 3x3+2 query boxes, half-open boxes - // tests also mixed types for the two iterator ranges - init(); - result.clear(); - boxes2 = std::vector( boxes, boxes+11); - CGAL::box_intersection_d( boxes, boxes+11, boxes2.begin(), boxes2.end(), - report( std::back_inserter( result)), - std::ptrdiff_t(20), - CGAL::Box_intersection_d::HALF_OPEN, - CGAL::Box_intersection_d::BIPARTITE); - std::size_t check6[4] = {409,810,904,1008}; - check_result( "Box inters. 3x3+2, half-open", result, check6, 4); + CGAL::box_intersection_d(range_1.begin(), range_1.begin(), + range_2.begin(), range_2.end(), + report(result)); + assert(result.empty()); + + CGAL::box_intersection_d(range_1.begin(), range_1.end(), + range_2.begin(), range_2.begin(), + report(result)); + assert(result.empty()); + + CGAL::box_intersection_d(range_1.begin(), range_1.end(), + range_2.begin(), range_2.end(), + report(result)); + std::size_t check0[13] = {900,901,902,903,904,905,906,907,908, + 1004,1005,1007,1008}; + check_result( "Box inters. 3x3 (ptr), 2, closed", result, check0, 13); + + // intersect 3x3 with 2 query boxes, closed boxes + init(); + result.clear(); + CGAL::box_intersection_d(boxes, boxes+9, query, query+1, report(result)); + std::size_t check1[13] = {900,901,902,903,904,905,906,907,908}; + check_result( "Box inters. 3x3, 2, closed", result, check1, 9); + + // intersect 3x3 with 2 query boxes, closed boxes + init(); + result.clear(); + CGAL::box_intersection_d(boxes, boxes+9, query, query+2, report(result)); + std::size_t check1bis[13] = {900,901,902,903,904,905,906,907,908, + 1004,1005,1007,1008}; + check_result( "Box inters. 3x3, 2, closed", result, check1bis, 13); + + // intersect 3x3 with 2 query boxes, half-open boxes and changed cutoff + init(); + result.clear(); + CGAL::box_intersection_d( boxes, boxes+9, query, query+2, + report(result), + std::ptrdiff_t(1), + CGAL::Box_intersection_d::HALF_OPEN); + std::size_t check2[2] = {904,1008}; + check_result( "Box inters. 3x3, 2, half-open", result, check2, 2); + + // intersect 3x3 with 2 query boxes, half-open boxes and changed cutoff (reversed) + init(); + result.clear(); + CGAL::box_intersection_d( query, query+2, boxes, boxes+9, + report(result), + std::ptrdiff_t(1), + CGAL::Box_intersection_d::HALF_OPEN); + std::size_t check2bis[2] = {409,810}; + check_result( "Box inters. 3x3 (reversed), 2, half-open", result, check2bis, 2); + + // self intersect 3x2, closed boxes + init(); + result.clear(); + CGAL::box_self_intersection_d( boxes, boxes+6, + report(result)); + std::size_t check3[11] = {1,3,4,102,103,104,105,204,205,304,405}; + check_result( "Box self inters. 3x2, closed", result, check3, 11); + + // self intersect 3x2, half-open boxes + init(); + result.clear(); + CGAL::box_self_intersection_d( boxes, boxes+6, + report(result), + std::ptrdiff_t(1), + CGAL::Box_intersection_d::HALF_OPEN); + std::size_t check4[1] = {9999}; + check_result( "Box self inters. 3x2, half-open", result, check4, 0); + + // self intersect 3x3+2 query boxes, half-open boxes + init(); + result.clear(); + CGAL::box_self_intersection_d( boxes, boxes+11, + report(result), + std::ptrdiff_t(1), + CGAL::Box_intersection_d::HALF_OPEN); + std::size_t check5[2] = {409,810}; + check_result( "Box self inters. 3x3+2, half-open", result, check5, 2); + + // self intersect 3x3+2 query boxes, half-open boxes, full function interf. + // tests also mixed types for the two iterator ranges + init(); + result.clear(); + std::vector boxes2( boxes, boxes+11); + CGAL::box_intersection_d( boxes, boxes+11, boxes2.begin(), boxes2.end(), + report(result), + std::ptrdiff_t(1), + CGAL::Box_intersection_d::HALF_OPEN, + CGAL::Box_intersection_d::COMPLETE); + check_result( "Box inters. 3x3+2, half-open", result, check5, 2); + + // compare this with the bipartite case + // self intersect 3x3+2 query boxes, half-open boxes + // tests also mixed types for the two iterator ranges + init(); + result.clear(); + boxes2 = std::vector( boxes, boxes+11); + CGAL::box_intersection_d( boxes, boxes+11, boxes2.begin(), boxes2.end(), + report(result), + std::ptrdiff_t(20), + CGAL::Box_intersection_d::HALF_OPEN, + CGAL::Box_intersection_d::BIPARTITE); + std::size_t check6[4] = {409,810,904,1008}; + check_result( "Box inters. 3x3+2, half-open", result, check6, 4); } // --------------------------------------------------------------------- // box_intersection_all_pairs_d // run the intersection algorithms and store results in a vector // --------------------------------------------------------------------- -void test_box_intersection_all_pairs() { - // intersect 3x3 with 2 query boxes, closed boxes - init(); - std::vector result; - CGAL::box_intersection_all_pairs_d( boxes, boxes+9, query, query+2, - report( std::back_inserter( result))); - std::size_t check1[13] = {900,901,902,903,904,905,906,907,908, - 1004,1005,1007,1008}; - check_result( "All-pairs inters. 3x3, 2, closed", result, check1, 13); +void test_box_intersection_all_pairs() +{ + // intersect 3x3 with 2 query boxes, closed boxes + init(); + std::vector result; + CGAL::box_intersection_all_pairs_d( boxes, boxes+9, query, query+2, + report(result)); + std::size_t check1[13] = {900,901,902,903,904,905,906,907,908, + 1004,1005,1007,1008}; + check_result( "All-pairs inters. 3x3, 2, closed", result, check1, 13); - // intersect 3x3 with 2 query boxes, half-open boxes - init(); - result.clear(); - CGAL::box_intersection_all_pairs_d( boxes, boxes+9, query, query+2, - report( std::back_inserter( result)), - CGAL::Box_intersection_d::HALF_OPEN); - std::size_t check2[2] = {904,1008}; - check_result( "All-pairs inters. 3x3, 2, half-open", result, check2, 2); + // intersect 3x3 with 2 query boxes, half-open boxes + init(); + result.clear(); + CGAL::box_intersection_all_pairs_d( boxes, boxes+9, query, query+2, + report(result), + CGAL::Box_intersection_d::HALF_OPEN); + std::size_t check2[2] = {904,1008}; + check_result( "All-pairs inters. 3x3, 2, half-open", result, check2, 2); - // self intersect 3x2, closed boxes - init(); - result.clear(); - CGAL::box_self_intersection_all_pairs_d( boxes, boxes+6, - report( std::back_inserter( result))); - std::size_t check3[11] = {100,201,300,301,400,401,402,403,501,502,504}; - check_result( "All-pairs self inters. 3x2, closed", result, check3, 11); + // self intersect 3x2, closed boxes + init(); + result.clear(); + CGAL::box_self_intersection_all_pairs_d( boxes, boxes+6, + report(result)); + std::size_t check3[11] = {100,201,300,301,400,401,402,403,501,502,504}; + check_result( "All-pairs self inters. 3x2, closed", result, check3, 11); - // self intersect 3x2, half-open boxes - init(); - result.clear(); - CGAL::box_self_intersection_all_pairs_d( boxes, boxes+6, - report( std::back_inserter( result)), - CGAL::Box_intersection_d::HALF_OPEN); - std::size_t check4[1] = {9999}; - check_result( "All-pairs self inters. 3x2, half-open", result, check4, 0); + // self intersect 3x2, half-open boxes + init(); + result.clear(); + CGAL::box_self_intersection_all_pairs_d( boxes, boxes+6, + report(result), + CGAL::Box_intersection_d::HALF_OPEN); + std::size_t check4[1] = {9999}; + check_result( "All-pairs self inters. 3x2, half-open", result, check4, 0); - // self intersect 3x3+2 query boxes, half-open boxes - init(); - result.clear(); - CGAL::box_self_intersection_all_pairs_d( boxes, boxes+11, - report( std::back_inserter( result)), - CGAL::Box_intersection_d::HALF_OPEN); - std::size_t check5[2] = {904,1008}; - check_result( "All-pairs self inters. 3x3+2, half-open", result, check5,2); + // self intersect 3x3+2 query boxes, half-open boxes + init(); + result.clear(); + CGAL::box_self_intersection_all_pairs_d( boxes, boxes+11, + report(result), + CGAL::Box_intersection_d::HALF_OPEN); + std::size_t check5[2] = {904,1008}; + check_result( "All-pairs self inters. 3x3+2, half-open", result, check5,2); - // self intersect 3x3+2 query boxes, half-open boxes, full function interf. - // tests also mixed types for the two iterator ranges - init(); - result.clear(); - std::vector boxes2( boxes, boxes+11); - CGAL::box_intersection_all_pairs_d( boxes, boxes+11, - boxes2.begin(), boxes2.end(), - report( std::back_inserter( result)), - CGAL::Box_intersection_d::HALF_OPEN, - CGAL::Box_intersection_d::COMPLETE); - check_result( "All-pairs self inters. 3x3+2, half-open", result, check5,2); - - // compare this with the bipartite case - // self intersect 3x3+2 query boxes, half-open boxes - // tests also mixed types for the two iterator ranges - init(); - result.clear(); - boxes2 = std::vector( boxes, boxes+11); - CGAL::box_intersection_all_pairs_d( boxes, boxes+11, - boxes2.begin(), boxes2.end(), - report( std::back_inserter( result)), - CGAL::Box_intersection_d::HALF_OPEN, - CGAL::Box_intersection_d::BIPARTITE); - std::size_t check6[4] = {409,810,904,1008}; - check_result( "All-pairs inters. 3x3+2, half-open", result, check6, 4); + // self intersect 3x3+2 query boxes, half-open boxes, full function interf. + // tests also mixed types for the two iterator ranges + init(); + result.clear(); + std::vector boxes2( boxes, boxes+11); + CGAL::box_intersection_all_pairs_d( boxes, boxes+11, + boxes2.begin(), boxes2.end(), + report(result), + CGAL::Box_intersection_d::HALF_OPEN, + CGAL::Box_intersection_d::COMPLETE); + check_result( "All-pairs self inters. 3x3+2, half-open", result, check5,2); + + // compare this with the bipartite case + // self intersect 3x3+2 query boxes, half-open boxes + // tests also mixed types for the two iterator ranges + init(); + result.clear(); + boxes2 = std::vector( boxes, boxes+11); + CGAL::box_intersection_all_pairs_d( boxes, boxes+11, + boxes2.begin(), boxes2.end(), + report(result), + CGAL::Box_intersection_d::HALF_OPEN, + CGAL::Box_intersection_d::BIPARTITE); + std::size_t check6[4] = {409,810,904,1008}; + check_result( "All-pairs inters. 3x3+2, half-open", result, check6, 4); } +int main() +{ + test_box_intersection(); + test_box_intersection_all_pairs(); -int main() { - test_box_intersection(); - test_box_intersection_all_pairs(); - return 0; + return EXIT_SUCCESS; } From 0191d868fa61eaae0e6c5461a34eff7b9825ce87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 2 Dec 2019 16:39:58 +0100 Subject: [PATCH 070/185] Simplify and clean parallel code for PMP::self_intersections --- .../self_intersections.h | 522 +++++++----------- 1 file changed, 210 insertions(+), 312 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index 526f143235e..7d9e84da942 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -21,76 +21,163 @@ #include -#include -#include -#include - -#ifdef CGAL_PMP_SI_DEBUG -#include -#endif - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - #include #include +#include +#include +#include +#include +#include +#include + +#include +#include + #ifdef CGAL_LINKED_WITH_TBB #include #include #include #endif +#include +#include +#include +#include + #ifdef DOXYGEN_RUNNING #define CGAL_PMP_NP_TEMPLATE_PARAMETERS NamedParameters #define CGAL_PMP_NP_CLASS NamedParameters #endif namespace CGAL { +namespace Polygon_mesh_processing { namespace internal { -template +// Checks for 'real' intersections, i.e. not simply a shared vertex or edge +template +bool do_faces_intersect(typename boost::graph_traits::halfedge_descriptor h, + typename boost::graph_traits::halfedge_descriptor g, + const TM& tmesh, + const VPM vpmap, + const typename GT::Construct_segment_3& construct_segment, + const typename GT::Construct_triangle_3& construct_triangle, + const typename GT::Do_intersect_3& do_intersect) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + + typedef typename GT::Segment_3 Segment; + typedef typename GT::Triangle_3 Triangle; + + vertex_descriptor hv[3], gv[3]; + hv[0] = target(h, tmesh); + hv[1] = target(next(h, tmesh), tmesh); + hv[2] = source(h, tmesh); + + gv[0] = target(g, tmesh); + gv[1] = target(next(g, tmesh), tmesh); + gv[2] = source(g, tmesh); + + halfedge_descriptor opp_h; + + // check for shared edge + for(unsigned int i=0; i<3; ++i) + { + opp_h = opposite(h, tmesh); + if(face(opp_h, tmesh) == face(g, tmesh)) + { + // there is an intersection if the four points are coplanar and the triangles overlap + if(CGAL::coplanar(get(vpmap, hv[i]), + get(vpmap, hv[(i+1)%3]), + get(vpmap, hv[(i+2)%3]), + get(vpmap, target(next(opp_h, tmesh), tmesh))) && + CGAL::coplanar_orientation(get(vpmap, hv[(i+2)%3]), + get(vpmap, hv[i]), + get(vpmap, hv[(i+1)%3]), + get(vpmap, target(next(opp_h, tmesh), tmesh))) + == CGAL::POSITIVE) + { + return true; + } + else + { + // there is a shared edge but no intersection + return false; + } + } + + h = next(h, tmesh); + } + + // check for shared vertex --> maybe intersection, maybe not + int i(0), j(0); + bool shared = false; + for(; i<3 && (! shared); ++i) + { + for(j=0; j<3 && (! shared); ++j) + { + if(hv[i] == gv[j]) + { + shared = true; + break; + } + } + + if(shared) + break; + } + + if(shared) + { + // found shared vertex: + CGAL_assertion(hv[i] == gv[j]); + + // geometric check if the opposite segments intersect the triangles + Triangle t1 = construct_triangle(get(vpmap, hv[0]), get(vpmap, hv[1]), get(vpmap, hv[2])); + Triangle t2 = construct_triangle(get(vpmap, gv[0]), get(vpmap, gv[1]), get(vpmap, gv[2])); + + Segment s1 = construct_segment(get(vpmap, hv[(i+1)%3]), get(vpmap, hv[(i+2)%3]) ); + Segment s2 = construct_segment(get(vpmap, gv[(j+1)%3]), get(vpmap, gv[(j+2)%3])); + + if(do_intersect(t1, s2)) + return true; + else if(do_intersect(t2, s1)) + return true; + + return false; + } + + // check for geometric intersection + Triangle t1 = construct_triangle(get(vpmap, hv[0]), get(vpmap, hv[1]), get(vpmap, hv[2])); + Triangle t2 = construct_triangle(get(vpmap, gv[0]), get(vpmap, gv[1]), get(vpmap, gv[2])); + if(do_intersect(t1, t2)) + return true; + + return false; +}; + +template struct Intersect_facets { -// typedefs - typedef typename Kernel::Segment_3 Segment; - typedef typename Kernel::Triangle_3 Triangle; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename boost::property_map::const_type Ppmap; -// members + mutable OutputIterator m_iterator; const TM& m_tmesh; - const VertexPointMap m_vpmap; - mutable OutputIterator m_iterator; + const VPM m_vpmap; + typename GT::Construct_segment_3 m_construct_segment; + typename GT::Construct_triangle_3 m_construct_triangle; + typename GT::Do_intersect_3 m_do_intersect; - typename Kernel::Construct_segment_3 segment_functor; - typename Kernel::Construct_triangle_3 triangle_functor; - typename Kernel::Do_intersect_3 do_intersect_3_functor; - - Intersect_facets(const TM& tmesh, OutputIterator it, VertexPointMap vpmap, const Kernel& kernel) + Intersect_facets(const TM& tmesh, VPM vpmap, const GT& gt, OutputIterator it) : - m_tmesh(tmesh), - m_vpmap(vpmap), - m_iterator(it), - segment_functor(kernel.construct_segment_3_object()), - triangle_functor(kernel.construct_triangle_3_object()), - do_intersect_3_functor(kernel.do_intersect_3_object()) + m_iterator(it), + m_tmesh(tmesh), + m_vpmap(vpmap), + m_construct_segment(gt.construct_segment_3_object()), + m_construct_triangle(gt.construct_triangle_3_object()), + m_do_intersect(gt.do_intersect_3_object()) {} void operator()(const Box* b, const Box* c) const @@ -98,272 +185,82 @@ struct Intersect_facets halfedge_descriptor h = halfedge(b->info(), m_tmesh); halfedge_descriptor g = halfedge(c->info(), m_tmesh); - vertex_descriptor hv[3], gv[3]; - hv[0] = target(h, m_tmesh); - hv[1] = target(next(h, m_tmesh), m_tmesh); - hv[2] = source(h, m_tmesh); - - gv[0] = target(g, m_tmesh); - gv[1] = target(next(g, m_tmesh), m_tmesh); - gv[2] = source(g, m_tmesh); - - halfedge_descriptor opp_h; - - // check for shared egde - for(unsigned int i=0; i<3; ++i){ - opp_h = opposite(h, m_tmesh); - if(face(opp_h, m_tmesh) == c->info()){ - // there is an intersection if the four points are coplanar and - // the triangles overlap - get(m_vpmap, hv[i]); - get(m_vpmap, hv[(i + 1) % 3]); - get(m_vpmap, hv[(i + 2) % 3]); - get(m_vpmap, target(next(opp_h, m_tmesh), m_tmesh)); - - if(CGAL::coplanar(get(m_vpmap, hv[i]), - get(m_vpmap, hv[(i+1)%3]), - get(m_vpmap, hv[(i+2)%3]), - get(m_vpmap, target(next(opp_h, m_tmesh), m_tmesh))) && - CGAL::coplanar_orientation(get(m_vpmap, hv[(i+2)%3]), - get(m_vpmap, hv[i]), - get(m_vpmap, hv[(i+1)%3]), - get(m_vpmap, target(next(opp_h, m_tmesh), m_tmesh))) - == CGAL::POSITIVE){ - *m_iterator++ = std::make_pair(b->info(), c->info()); - return; - } else { // there is a shared edge but no intersection - return; - } - } - h = next(h, m_tmesh); - } - - // check for shared vertex --> maybe intersection, maybe not - - halfedge_descriptor v; - - int i(0),j(0); - bool shared = false; - for(; i < 3 && (! shared); ++i){ - for(j = 0; j < 3 && (! shared); ++j){ - if(hv[i]==gv[j]){ - shared = true; - break; - } - } - if (shared) { - break; - } - } - if(shared){ - // found shared vertex: - CGAL_assertion(hv[i] == gv[j]); - - // geometric check if the opposite segments intersect the triangles - Triangle t1 = triangle_functor( get(m_vpmap, hv[0]), - get(m_vpmap, hv[1]), - get(m_vpmap, hv[2])); - Triangle t2 = triangle_functor( get(m_vpmap, gv[0]), - get(m_vpmap, gv[1]), - get(m_vpmap, gv[2])); - - Segment s1 = segment_functor( get(m_vpmap, hv[(i+1)%3]), - get(m_vpmap, hv[(i+2)%3]) ); - Segment s2 = segment_functor( get(m_vpmap, gv[(j+1)%3]), - get(m_vpmap, gv[(j+2)%3])); - - if(do_intersect_3_functor(t1,s2)){ - *m_iterator++ = std::make_pair(b->info(), c->info()); - } else if(do_intersect_3_functor(t2,s1)){ - *m_iterator++ = std::make_pair(b->info(), c->info()); - } - return; - } - - // check for geometric intersection - Triangle t1 = triangle_functor( get(m_vpmap, hv[0]), - get(m_vpmap, hv[1]), - get(m_vpmap, hv[2])); - Triangle t2 = triangle_functor( get(m_vpmap, gv[0]), - get(m_vpmap, gv[1]), - get(m_vpmap, gv[2])); - if(do_intersect_3_functor(t1, t2)){ + if(do_faces_intersect(h, g, m_tmesh, m_vpmap, m_construct_segment, m_construct_triangle, m_do_intersect)) *m_iterator++ = std::make_pair(b->info(), c->info()); - } - } // end operator () -}; // end struct Intersect_facets + } +}; - #ifdef CGAL_LINKED_WITH_TBB -//TODO: use the same code for the linear pass? -// The functor for doing all geometric tests in parallel -template -struct AllPairs +// The functor doing all geometric tests in parallel +template +struct Concurrent_face_intersection_tester { -// types - typedef typename Kernel::Segment_3 Segment; - typedef typename Kernel::Triangle_3 Triangle; - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; -// data members const TM& m_tmesh; - const VertexPointMap m_vpmap; - const FacePairs& face_pairs; - std::vector& dointersect; - typename Kernel::Construct_segment_3 segment_functor; - typename Kernel::Construct_triangle_3 triangle_functor; - typename Kernel::Do_intersect_3 do_intersect_3_functor; + const VPM m_vpmap; + const FacePairs& m_face_pairs; + DoIntersectVector& m_do_intersect_vector; + typename GT::Construct_segment_3 m_construct_segment; + typename GT::Construct_triangle_3 m_construct_triangle; + typename GT::Do_intersect_3 m_do_intersect; - - AllPairs(const FacePairs& face_pairs, - std::vector& dointersect, - const TM& tmesh, VertexPointMap vpmap, const Kernel& kernel) - : m_tmesh(tmesh), + Concurrent_face_intersection_tester(const FacePairs& face_pairs, + DoIntersectVector& do_intersect_vector, + const TM& tmesh, + VPM vpmap, + const GT& gt) + : + m_tmesh(tmesh), m_vpmap(vpmap), - face_pairs(face_pairs), - dointersect(dointersect), - triangle_functor(kernel.construct_triangle_3_object()), - do_intersect_3_functor(kernel.do_intersect_3_object()) + m_face_pairs(face_pairs), + m_do_intersect_vector(do_intersect_vector), + m_construct_segment(gt.construct_segment_3_object()), + m_construct_triangle(gt.construct_triangle_3_object()), + m_do_intersect(gt.do_intersect_3_object()) {} void operator()(const tbb::blocked_range &r) const { - for (std::size_t ri = r.begin(); ri != r.end(); ++ri) { + for(std::size_t ri = r.begin(); ri != r.end(); ++ri) this->operator()(ri); - } } void operator()(std::size_t ri) const { - const std::pair& ff = face_pairs[ri]; + const std::pair& ff = m_face_pairs[ri]; halfedge_descriptor h = halfedge(ff.first, m_tmesh), g = halfedge(ff.second, m_tmesh); - vertex_descriptor hv[3], gv[3]; - hv[0] = target(h, m_tmesh); - hv[1] = target(next(h, m_tmesh), m_tmesh); - hv[2] = source(h, m_tmesh); - - gv[0] = target(g, m_tmesh); - gv[1] = target(next(g, m_tmesh), m_tmesh); - gv[2] = source(g, m_tmesh); - - halfedge_descriptor opp_h; - - // check for shared egde - for(unsigned int i=0; i<3; ++i){ - opp_h = opposite(h, m_tmesh); - if(face(opp_h, m_tmesh) == ff.second){ - // there is an intersection if the four points are coplanar and - // the triangles overlap - get(m_vpmap, hv[i]); - get(m_vpmap, hv[(i + 1) % 3]); - get(m_vpmap, hv[(i + 2) % 3]); - get(m_vpmap, target(next(opp_h, m_tmesh), m_tmesh)); - - if(CGAL::coplanar(get(m_vpmap, hv[i]), - get(m_vpmap, hv[(i+1)%3]), - get(m_vpmap, hv[(i+2)%3]), - get(m_vpmap, target(next(opp_h, m_tmesh), m_tmesh))) && - CGAL::coplanar_orientation(get(m_vpmap, hv[(i+2)%3]), - get(m_vpmap, hv[i]), - get(m_vpmap, hv[(i+1)%3]), - get(m_vpmap, target(next(opp_h, m_tmesh), m_tmesh))) - == CGAL::POSITIVE){ - dointersect[ri]=true; - return; - } else { // there is a shared edge but no intersection - return; - } - } - h = next(h, m_tmesh); - } - - // check for shared vertex --> maybe intersection, maybe not - - halfedge_descriptor v; - - int i(0),j(0); - bool shared = false; - for(; i < 3 && (! shared); ++i){ - for(j = 0; j < 3 && (! shared); ++j){ - if(hv[i]==gv[j]){ - shared = true; - break; - } - } - if (shared) { - break; - } - } - if(shared){ - // found shared vertex: - CGAL_assertion(hv[i] == gv[j]); - - // geometric check if the opposite segments intersect the triangles - Triangle t1 = triangle_functor( get(m_vpmap, hv[0]), - get(m_vpmap, hv[1]), - get(m_vpmap, hv[2])); - Triangle t2 = triangle_functor( get(m_vpmap, gv[0]), - get(m_vpmap, gv[1]), - get(m_vpmap, gv[2])); - - Segment s1 = segment_functor( get(m_vpmap, hv[(i+1)%3]), - get(m_vpmap, hv[(i+2)%3]) ); - Segment s2 = segment_functor( get(m_vpmap, gv[(j+1)%3]), - get(m_vpmap, gv[(j+2)%3])); - - dointersect[ri] = (do_intersect_3_functor(t1, s2)) || do_intersect_3_functor(t2, s1); - return; - } - - // check for geometric intersection - Triangle t1 = triangle_functor( get(m_vpmap, hv[0]), - get(m_vpmap, hv[1]), - get(m_vpmap, hv[2])); - Triangle t2 = triangle_functor( get(m_vpmap, gv[0]), - get(m_vpmap, gv[1]), - get(m_vpmap, gv[2])); - dointersect[ri] = do_intersect_3_functor(t1, t2); + if(do_faces_intersect(h, g, m_tmesh, m_vpmap, m_construct_segment, m_construct_triangle, m_do_intersect)) + m_do_intersect_vector[ri] = true; } }; - -// The functor that filters nothing +// This filter does not filter anything, but simply forwards intersecting pair information so that +// filtering can be done outside of the call to 'box_intersection_d' template struct All_faces_filter { - mutable OutputIterator m_iterator; - - All_faces_filter(OutputIterator it) : m_iterator(it) {} + All_faces_filter(OutputIterator it) : m_iterator(it) { } template - void operator()(const Box* b, const Box* c) const - { - *m_iterator ++ = std::make_pair(b->info(), c->info()); - } + void operator()(const Box* b, const Box* c) const { *m_iterator++ = std::make_pair(b->info(), c->info()); } + + mutable OutputIterator m_iterator; }; - - #endif -struct Throw_at_output { - class Throw_at_output_exception: public std::exception - { }; +struct Throw_at_output +{ + class Throw_at_output_exception: public std::exception { }; template - void operator()(const T& /* t */) const { - throw Throw_at_output_exception(); - } + void operator()(const T& /* t */) const { throw Throw_at_output_exception(); } }; -}// namespace internal - -namespace Polygon_mesh_processing { +} // namespace internal /*! * \ingroup PMP_intersection_grp @@ -403,7 +300,7 @@ template < class ConcurrencyTag = Sequential_tag, class OutputIterator, class NamedParameters> OutputIterator -self_intersections( const FaceRange& face_range, +self_intersections(const FaceRange& face_range, const TriangleMesh& tmesh, OutputIterator out, const NamedParameters& np) @@ -416,25 +313,25 @@ self_intersections( const FaceRange& face_range, typedef CGAL::Box_intersection_d::ID_FROM_BOX_ADDRESS Box_policy; typedef CGAL::Box_intersection_d::Box_with_info_d Box; - typedef typename GetGeomTraits::type GeomTraits; - GeomTraits gt = parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits), GeomTraits()); + typedef typename GetGeomTraits::type GT; + GT gt = parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits), GT()); - typedef typename GetVertexPointMap::const_type VertexPointMap; - VertexPointMap vpmap = parameters::choose_parameter(parameters::get_parameter(np, internal_np::vertex_point), - get_const_property_map(boost::vertex_point, tmesh)); + typedef typename GetVertexPointMap::const_type VPM; + VPM vpmap = parameters::choose_parameter(parameters::get_parameter(np, internal_np::vertex_point), + get_const_property_map(boost::vertex_point, tmesh)); // make one box per face std::vector boxes; - boxes.reserve(std::distance(boost::begin(face_range), boost::end(face_range))); + boxes.reserve(std::distance(std::begin(face_range), std::end(face_range))); for(face_descriptor f : face_range) { - typename boost::property_traits::reference + typename boost::property_traits::reference p = get(vpmap, target(halfedge(f,tmesh),tmesh)), q = get(vpmap, target(next(halfedge(f, tmesh), tmesh), tmesh)), r = get(vpmap, target(next(next(halfedge(f, tmesh), tmesh), tmesh), tmesh)); - if ( collinear(p, q, r) ) + if(collinear(p, q, r) ) *out++= std::make_pair(f,f); else boxes.push_back(Box(p.bbox() + q.bbox() + r.bbox(), f)); @@ -448,40 +345,43 @@ self_intersections( const FaceRange& face_range, box_ptr.push_back(&b); #if !defined(CGAL_LINKED_WITH_TBB) - CGAL_static_assertion_msg (!(boost::is_convertible::value), + CGAL_static_assertion_msg (!(std::is_convertible::value), "Parallel_tag is enabled but TBB is unavailable."); #else - if (boost::is_convertible::value) + if(std::is_convertible::value) { - // (Parallel version of the code) - // (A) Sequentially write all pairs of faces with intersecting bbox into a std::vector + // (A) Parallel: Write all pairs of faces with intersecting bbox std::ptrdiff_t cutoff = 2000; - typedef tbb::concurrent_vector >FacePairs; + typedef tbb::concurrent_vector > Face_pairs; + typedef std::back_insert_iterator Face_pairs_back_inserter; - typedef std::back_insert_iterator FacePairsI; - FacePairs face_pairs; - CGAL::internal::All_faces_filter all_faces_filter(std::back_inserter(face_pairs)); + Face_pairs face_pairs; + internal::All_faces_filter all_faces_filter(std::back_inserter(face_pairs)); CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(), all_faces_filter, cutoff); - // (B) Parallel: perform the geometric tests - std::vector dointersect(face_pairs.size(), 0); - CGAL::internal::AllPairs all_pairs(face_pairs, dointersect, tmesh, vpmap, gt); + // (B) Parallel: Perform the geometric tests + typedef std::vector Do_intersect_vector; + typedef internal::Concurrent_face_intersection_tester Tester; - tbb::parallel_for(tbb::blocked_range(0, face_pairs.size()), all_pairs); + Do_intersect_vector do_intersect(face_pairs.size(), 0); + Tester tester(face_pairs, do_intersect, tmesh, vpmap, gt); + tbb::parallel_for(tbb::blocked_range(0, face_pairs.size()), tester); // (C) Sequentially: Copy from the concurent container to the output iterator - for(std::size_t i=0; i < dointersect.size(); ++i){ - if(dointersect[i]) + for(std::size_t i=0; i - intersect_facets(tmesh, out, vpmap, gt); + // Sequential version of the code + // Compute self-intersections filtered out by boxes + typedef internal::Intersect_facets Intersecting_facet_filter; + Intersecting_facet_filter intersect_facets(tmesh, vpmap, gt, out); std::ptrdiff_t cutoff = 2000; CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(),intersect_facets, cutoff); @@ -502,7 +402,6 @@ self_intersections(const FaceRange& face_range, } /// \endcond - /** * \ingroup PMP_intersection_grp * collects intersections between all the faces of a triangulated surface mesh. @@ -590,10 +489,10 @@ bool does_self_intersect(const TriangleMesh& tmesh, try { - typedef boost::function_output_iterator OutputIterator; + typedef boost::function_output_iterator OutputIterator; self_intersections(tmesh, OutputIterator(), np); } - catch( CGAL::internal::Throw_at_output::Throw_at_output_exception& ) + catch(internal::Throw_at_output::Throw_at_output_exception& ) { return true; } return false; @@ -636,10 +535,10 @@ bool does_self_intersect(const FaceRange& face_range, try { - typedef boost::function_output_iterator OutputIterator; + typedef boost::function_output_iterator OutputIterator; self_intersections(face_range, tmesh, OutputIterator(), np); } - catch( CGAL::internal::Throw_at_output::Throw_at_output_exception& ) + catch(internal::Throw_at_output::Throw_at_output_exception& ) { return true; } return false; @@ -660,8 +559,7 @@ bool does_self_intersect(const FaceRange& face_range, } /// \endcond -}// end namespace Polygon_mesh_processing - +}// namespace Polygon_mesh_processing }// namespace CGAL #include From a1adb5fc947f6a4bbb5b26799b6e9af02a8883e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 3 Dec 2019 10:10:34 +0100 Subject: [PATCH 071/185] Use correct parallel tags in the example --- .../self_intersections_example.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp index a36a5003ae7..a44efca2da7 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp @@ -1,10 +1,11 @@ #include #include -#include #include +#include #include +#include #include typedef CGAL::Exact_predicates_inexact_constructions_kernel K; @@ -25,22 +26,22 @@ int main(int argc, char* argv[]) return EXIT_FAILURE; } + std::cout << "Using parallel mode? " << std::is_same::value << std::endl; + CGAL::Real_timer timer; timer.start(); - std::cout << "Using parallel mode? " << std::is_same::value << std::endl; - - bool intersecting = PMP::does_self_intersect( - mesh, CGAL::parameters::vertex_point_map(get(CGAL::vertex_point, mesh))); + bool intersecting = PMP::does_self_intersect(mesh, CGAL::parameters::vertex_point_map(get(CGAL::vertex_point, mesh))); std::cout << (intersecting ? "There are self-intersections." : "There is no self-intersection.") << std::endl; + std::cout << "Elapsed time (does self intersect): " << timer.time() << std::endl; + + timer.reset(); std::vector > intersected_tris; - PMP::self_intersections(faces(mesh), mesh, std::back_inserter(intersected_tris)); + PMP::self_intersections(faces(mesh), mesh, std::back_inserter(intersected_tris)); std::cout << intersected_tris.size() << " pairs of triangles intersect." << std::endl; - timer.stop(); - double t = timer.time(); - std::cout << "Time: " << t << std::endl; + std::cout << "Elapsed time (self intersections): " << timer.time() << std::endl; return EXIT_SUCCESS; } From c0921a5e530e92baaebd75ac63506d114f937fac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 3 Dec 2019 12:00:31 +0100 Subject: [PATCH 072/185] Fix collecting all intersecting pairs before throwing + fix NP improper forward --- .../self_intersections.h | 291 ++++++++++-------- 1 file changed, 158 insertions(+), 133 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index 7d9e84da942..935e0314b7b 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -31,9 +31,6 @@ #include #include -#include -#include - #ifdef CGAL_LINKED_WITH_TBB #include #include @@ -252,61 +249,27 @@ struct All_faces_filter }; #endif -struct Throw_at_output -{ - class Throw_at_output_exception: public std::exception { }; +class Throw_at_output_exception + : public std::exception +{ }; - template - void operator()(const T& /* t */) const { throw Throw_at_output_exception(); } -}; - -} // namespace internal - -/*! - * \ingroup PMP_intersection_grp - * collects intersections between a subset of faces of a triangulated surface mesh. - * Two faces are said to intersect if the corresponding triangles intersect - * and the intersection is not an edge nor a vertex incident to both faces. - * - * This function depends on the package \ref PkgBoxIntersectionD - * - * @pre `CGAL::is_triangle_mesh(tmesh)` - * - * @tparam ConcurrencyTag enables sequential versus parallel algorithm. - * Possible values are `Sequential_tag`, `Parallel_tag`, and `Parallel_if_available_tag`. - * @tparam FaceRange range of `boost::graph_traits::%face_descriptor`, - * model of `Range`. - * Its iterator type is `RandomAccessIterator`. - * @tparam TriangleMesh a model of `FaceListGraph` - * @tparam OutputIterator a model of `OutputIterator` holding objects of type - * `std::pair::%face_descriptor, boost::graph_traits::%face_descriptor>` - * @tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" - * - * @param face_range the range of faces to check for self-intersection. - * @param tmesh the triangulated surface mesh to be checked - * @param out output iterator to be filled with all pairs of non-adjacent faces that intersect - * @param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below - * - * \cgalNamedParamsBegin - * \cgalParamBegin{vertex_point_map} the property map with the points associated to the vertices of `pmesh`. - * If this parameter is omitted, an internal property map for - * `CGAL::vertex_point_t` must be available in `TriangleMesh`\cgalParamEnd - * \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `PMPSelfIntersectionTraits` \cgalParamEnd - * \cgalNamedParamsEnd - */ -template < class ConcurrencyTag = Sequential_tag, - class TriangleMesh, - class FaceRange, - class OutputIterator, - class NamedParameters> -OutputIterator -self_intersections(const FaceRange& face_range, - const TriangleMesh& tmesh, - OutputIterator out, - const NamedParameters& np) +template +FacePairOutputIterator +self_intersections_impl(const FaceRange& face_range, + const TriangleMesh& tmesh, + FacePairOutputIterator out, + const bool throw_on_SI, + const NamedParameters& np) { CGAL_precondition(CGAL::is_triangle_mesh(tmesh)); + using CGAL::parameters::choose_parameter; + using CGAL::parameters::get_parameter; + typedef TriangleMesh TM; typedef typename boost::graph_traits::face_descriptor face_descriptor; @@ -314,11 +277,13 @@ self_intersections(const FaceRange& face_range, typedef CGAL::Box_intersection_d::Box_with_info_d Box; typedef typename GetGeomTraits::type GT; - GT gt = parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits), GT()); + GT gt = choose_parameter(get_parameter(np, internal_np::geom_traits), GT()); typedef typename GetVertexPointMap::const_type VPM; - VPM vpmap = parameters::choose_parameter(parameters::get_parameter(np, internal_np::vertex_point), - get_const_property_map(boost::vertex_point, tmesh)); + VPM vpmap = choose_parameter(get_parameter(np, internal_np::vertex_point), + get_const_property_map(boost::vertex_point, tmesh)); + + const std::ptrdiff_t cutoff = 2000; // make one box per face std::vector boxes; @@ -331,10 +296,19 @@ self_intersections(const FaceRange& face_range, q = get(vpmap, target(next(halfedge(f, tmesh), tmesh), tmesh)), r = get(vpmap, target(next(next(halfedge(f, tmesh), tmesh), tmesh), tmesh)); - if(collinear(p, q, r) ) - *out++= std::make_pair(f,f); + // tiny fixme: if f is degenerate, we might still have a real intersection between f + // and another face f', but right now we are not creating a box for f and thus not returning those + if(collinear(p, q, r)) + { + if(throw_on_SI) + throw internal::Throw_at_output_exception(); + else + *out++= std::make_pair(f, f); + } else + { boxes.push_back(Box(p.bbox() + q.bbox() + r.bbox(), f)); + } } // generate box pointers @@ -344,6 +318,9 @@ self_intersections(const FaceRange& face_range, for(Box& b : boxes) box_ptr.push_back(&b); + // In case we are throwing, like in `does_self_intersect()` + auto throwing_callback = [] (const Box*, const Box*) { throw internal::Throw_at_output_exception(); }; + #if !defined(CGAL_LINKED_WITH_TBB) CGAL_static_assertion_msg (!(std::is_convertible::value), "Parallel_tag is enabled but TBB is unavailable."); @@ -351,14 +328,16 @@ self_intersections(const FaceRange& face_range, if(std::is_convertible::value) { // (A) Parallel: Write all pairs of faces with intersecting bbox - std::ptrdiff_t cutoff = 2000; - typedef tbb::concurrent_vector > Face_pairs; typedef std::back_insert_iterator Face_pairs_back_inserter; Face_pairs face_pairs; internal::All_faces_filter all_faces_filter(std::back_inserter(face_pairs)); - CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(), all_faces_filter, cutoff); + + if(throw_on_SI) + CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(), throwing_callback, cutoff); + else + CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(), all_faces_filter, cutoff); // (B) Parallel: Perform the geometric tests typedef std::vector Do_intersect_vector; @@ -380,23 +359,72 @@ self_intersections(const FaceRange& face_range, #endif // Sequential version of the code // Compute self-intersections filtered out by boxes - typedef internal::Intersect_facets Intersecting_facet_filter; + typedef internal::Intersect_facets Intersecting_facet_filter; Intersecting_facet_filter intersect_facets(tmesh, vpmap, gt, out); - std::ptrdiff_t cutoff = 2000; - CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(),intersect_facets, cutoff); + if(throw_on_SI) + CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(), throwing_callback, cutoff); + else + CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(), intersect_facets, cutoff); + return intersect_facets.m_iterator; } +} // namespace internal + +/*! + * \ingroup PMP_intersection_grp + * collects intersections between a subset of faces of a triangulated surface mesh. + * Two faces are said to intersect if the corresponding triangles intersect + * and the intersection is not an edge nor a vertex incident to both faces. + * + * This function depends on the package \ref PkgBoxIntersectionD + * + * @pre `CGAL::is_triangle_mesh(tmesh)` + * + * @tparam ConcurrencyTag enables sequential versus parallel algorithm. + * Possible values are `Sequential_tag`, `Parallel_tag`, and `Parallel_if_available_tag`. + * @tparam FaceRange a model of `ConstRange` with value type `boost::graph_traits::%face_descriptor`. + * @tparam TriangleMesh a model of `FaceListGraph` + * @tparam OutputIterator a model of `OutputIterator` holding objects of type + * `std::pair::%face_descriptor, boost::graph_traits::%face_descriptor>` + * @tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" + * + * @param face_range the range of faces to check for self-intersection. + * @param tmesh the triangulated surface mesh to be checked + * @param out output iterator to be filled with all pairs of non-adjacent faces that intersect + * @param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below + * + * \cgalNamedParamsBegin + * \cgalParamBegin{vertex_point_map} the property map with the points associated to the vertices of `pmesh`. + * If this parameter is omitted, an internal property map for + * `CGAL::vertex_point_t` must be available in `TriangleMesh`\cgalParamEnd + * \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `PMPSelfIntersectionTraits` \cgalParamEnd + * \cgalNamedParamsEnd + */ +template < class ConcurrencyTag = Sequential_tag, + class TriangleMesh, + class FaceRange, + class FacePairOutputIterator, + class NamedParameters> +FacePairOutputIterator +self_intersections(const FaceRange& face_range, + const TriangleMesh& tmesh, + FacePairOutputIterator out, + const NamedParameters& np) +{ + return internal::self_intersections_impl(face_range, tmesh, out, false /*don't throw*/, np); +} + /// \cond SKIP_IN_MANUAL template -OutputIterator + class FacePairOutputIterator> +FacePairOutputIterator self_intersections(const FaceRange& face_range, const TriangleMesh& tmesh, - OutputIterator out) + FacePairOutputIterator out) { return self_intersections(face_range, tmesh, out, CGAL::parameters::all_default()); } @@ -415,7 +443,7 @@ self_intersections(const FaceRange& face_range, * @tparam ConcurrencyTag enables sequential versus parallel algorithm. * Possible values are `Sequential_tag`, `Parallel_tag`, and `Parallel_if_available_tag`. * @tparam TriangleMesh a model of `FaceListGraph` - * @tparam OutputIterator a model of `OutputIterator` holding objects of type + * @tparam FacePairOutputIterator a model of `FacePairOutputIterator` holding objects of type * `std::pair::%face_descriptor, boost::graph_traits::%face_descriptor>` * @tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" * @@ -437,25 +465,78 @@ self_intersections(const FaceRange& face_range, */ template -OutputIterator +FacePairOutputIterator self_intersections(const TriangleMesh& tmesh, - OutputIterator out, + FacePairOutputIterator out, const CGAL_PMP_NP_CLASS& np) { return self_intersections(faces(tmesh), tmesh, out, np); } /// \cond SKIP_IN_MANUAL -template -OutputIterator -self_intersections(const TriangleMesh& tmesh, OutputIterator out) +template +FacePairOutputIterator +self_intersections(const TriangleMesh& tmesh, FacePairOutputIterator out) { return self_intersections(faces(tmesh), tmesh, out, parameters::all_default()); } /// \endcond +/** + * \ingroup PMP_intersection_grp + * tests if a set of faces of a triangulated surface mesh self-intersects. + * This function depends on the package \ref PkgBoxIntersectionD + * @pre `CGAL::is_triangle_mesh(tmesh)` + * + * @tparam ConcurrencyTag enables sequential versus parallel algorithm. + * Possible values are `Sequential_tag`, `Parallel_tag`, and `Parallel_if_available_tag`. + * @tparam FaceRange a range of `face_descriptor` + * @tparam TriangleMesh a model of `FaceListGraph` + * @tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" + * + * @param face_range the set of faces to test for self-intersection + * @param tmesh the triangulated surface mesh to be tested + * @param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below + * + * \cgalNamedParamsBegin + * \cgalParamBegin{vertex_point_map} the property map with the points associated to the vertices of `tmesh`. + * If this parameter is omitted, an internal property map for + * `CGAL::vertex_point_t` must be available in `TriangleMesh`\cgalParamEnd + * \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `SelfIntersectionTraits` \cgalParamEnd + * \cgalNamedParamsEnd + * + * @warning The parallel version of the algorithm has a small overhead as the range of faces + * is duplicated to allow concurrent work. Consequently, if the mesh has a large number + * of self-intersections, the sequential version of the algorithm might be faster. + * + * + * @return `true` if the faces in `face_range` self-intersect + */ +template +bool does_self_intersect(const FaceRange& face_range, + const TriangleMesh& tmesh, + const NamedParameters& np) +{ + CGAL_precondition(CGAL::is_triangle_mesh(tmesh)); + + try + { + CGAL::Emptyset_iterator unused_out; + internal::self_intersections_impl(face_range, tmesh, unused_out, true /*throw*/, np); + } + catch(internal::Throw_at_output_exception&) + { + return true; + } + + return false; +} + /** * \ingroup PMP_intersection_grp * tests if a triangulated surface mesh self-intersects. @@ -485,70 +566,14 @@ template OutputIterator; - self_intersections(tmesh, OutputIterator(), np); - } - catch(internal::Throw_at_output::Throw_at_output_exception& ) - { return true; } - - return false; -} - -/** - * \ingroup PMP_intersection_grp - * tests if a set of faces of a triangulated surface mesh self-intersects. - * This function depends on the package \ref PkgBoxIntersectionD - * @pre `CGAL::is_triangle_mesh(tmesh)` - * - * @tparam ConcurrencyTag enables sequential versus parallel algorithm. - * Possible values are `Sequential_tag`, `Parallel_tag`, and `Parallel_if_available_tag`. - * @tparam FaceRange a range of `face_descriptor` - * @tparam TriangleMesh a model of `FaceListGraph` - * @tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" - * - * @param face_range the set of faces to test for self-intersection - * @param tmesh the triangulated surface mesh to be tested - * @param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below - * - * \cgalNamedParamsBegin - * \cgalParamBegin{vertex_point_map} the property map with the points associated to the vertices of `tmesh`. - * If this parameter is omitted, an internal property map for - * `CGAL::vertex_point_t` must be available in `TriangleMesh`\cgalParamEnd - * \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `SelfIntersectionTraits` \cgalParamEnd - * \cgalNamedParamsEnd - * - * @return `true` if the faces in `face_range` self-intersect - */ -template -bool does_self_intersect(const FaceRange& face_range, - const TriangleMesh& tmesh, - const NamedParameters& np) -{ - CGAL_precondition(CGAL::is_triangle_mesh(tmesh)); - - try - { - typedef boost::function_output_iterator OutputIterator; - self_intersections(face_range, tmesh, OutputIterator(), np); - } - catch(internal::Throw_at_output::Throw_at_output_exception& ) - { return true; } - - return false; + return does_self_intersect(faces(tmesh), tmesh, np); } /// \cond SKIP_IN_MANUAL template bool does_self_intersect(const TriangleMesh& tmesh) { - return does_self_intersect(tmesh, CGAL::parameters::all_default()); + return does_self_intersect(faces(tmesh), tmesh, CGAL::parameters::all_default()); } template From cbf78b3de16206d2a77754db333c691de7206777 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 3 Dec 2019 12:11:19 +0100 Subject: [PATCH 073/185] Minor doc / comment changes --- .../CGAL/Polygon_mesh_processing/self_intersections.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index 935e0314b7b..c0abe0e8d84 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -289,6 +289,7 @@ self_intersections_impl(const FaceRange& face_range, std::vector boxes; boxes.reserve(std::distance(std::begin(face_range), std::end(face_range))); + // This loop is very cheap, so there is hardly anything to gain from parallelizing it for(face_descriptor f : face_range) { typename boost::property_traits::reference @@ -347,7 +348,7 @@ self_intersections_impl(const FaceRange& face_range, Tester tester(face_pairs, do_intersect, tmesh, vpmap, gt); tbb::parallel_for(tbb::blocked_range(0, face_pairs.size()), tester); - // (C) Sequentially: Copy from the concurent container to the output iterator + // (C) Sequential: Copy from the concurent container to the output iterator for(std::size_t i=0; i Date: Wed, 20 Nov 2019 11:42:47 +0100 Subject: [PATCH 074/185] Document the new type --- STL_Extension/doc/STL_Extension/CGAL/tags.h | 11 +++++++++-- .../doc/STL_Extension/PackageDescription.txt | 3 +++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/STL_Extension/doc/STL_Extension/CGAL/tags.h b/STL_Extension/doc/STL_Extension/CGAL/tags.h index 5e102c1d8ca..9a54c36a4fe 100644 --- a/STL_Extension/doc/STL_Extension/CGAL/tags.h +++ b/STL_Extension/doc/STL_Extension/CGAL/tags.h @@ -69,18 +69,25 @@ struct Null_functor { /*! \ingroup PkgSTLExtensionUtilities -Tag used to enable/disable concurrency. +Tag used to disable concurrency. For example, it may be used by a user to request the sequential version of an algorithm. */ struct Sequential_tag {}; /*! \ingroup PkgSTLExtensionUtilities -Tag used to enable/disable concurrency. +Tag used to enable concurrency. For example, it may be used by a user to request the parallel version of an algorithm. */ struct Parallel_tag {}; +/*! +\ingroup PkgSTLExtensionUtilities +This tag is a convenience typedef to `Parallel_tag` if the third party library \ref thirdpartyTBB +has been found and linked, and to `Sequential_tag` otherwise. +*/ +struct Parallel_if_available_tag {}; + /*! \ingroup PkgSTLExtensionUtilities diff --git a/STL_Extension/doc/STL_Extension/PackageDescription.txt b/STL_Extension/doc/STL_Extension/PackageDescription.txt index df921c5c6e0..4372a8f37d3 100644 --- a/STL_Extension/doc/STL_Extension/PackageDescription.txt +++ b/STL_Extension/doc/STL_Extension/PackageDescription.txt @@ -109,6 +109,9 @@ - `CGAL::Tag_false` - `CGAL::Null_tag` - `CGAL::Null_functor` +- `CGAL::Sequential_tag` +- `CGAL::Parallel_tag` +- `CGAL::Parallel_if_available_tag` - `CGAL::Uncertain` - `CGAL::Default` - `CGAL::Fast` From b93e556ff31afdc7a9ed59a8879e05f26be73934 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 3 Dec 2019 14:20:24 +0100 Subject: [PATCH 075/185] Document the parallel version of the box_intersection_d --- .../CGAL/box_intersection_d.h | 40 ++++++++++++++++--- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/Box_intersection_d/doc/Box_intersection_d/CGAL/box_intersection_d.h b/Box_intersection_d/doc/Box_intersection_d/CGAL/box_intersection_d.h index 89b6facc3cc..4a7840e47a2 100644 --- a/Box_intersection_d/doc/Box_intersection_d/CGAL/box_intersection_d.h +++ b/Box_intersection_d/doc/Box_intersection_d/CGAL/box_intersection_d.h @@ -242,6 +242,27 @@ void box_intersection_all_pairs_d( cutoff parameters are recommended. See also Section \ref secboxintersperformance . +\cgalHeading{Concurrency} + + The first template parameter of the function enables to choose whether + the algorithm is to be run in parallel, if `CGAL::Parallel_tag` is specified + and %CGAL has been linked with the Intel TBB library, or sequentially, + if `CGAL::Sequential_tag` - the default value - is specified. + The parallelization of the algorithm is based on a divide-and-conquer + approach: the two ranges are split in a number of smaller ranges, and + all combinations of subranges are treated in parallel. + + \warning The parallel mode comes with a small overhead due to the + duplication and splitting of the input ranges. It is an improvement + for almost all inputs, but not all. A configuration where the two ranges + are small and entirely disjoint might result in a slightly worse + runtime when using the parallel version. Users should benchmark both + versions to verify that their data does not fall in this (small) + set of inputs. + + \warning When using the parallel mode, the callback function must + be threadsafe. + \cgalHeading{Example} The box implementation provided with @@ -274,7 +295,8 @@ void box_intersection_all_pairs_d( */ -template< class RandomAccessIterator1, +template< class ConcurrencyTag = CGAL::Sequential_tag, + class RandomAccessIterator1, class RandomAccessIterator2, class Callback > void box_intersection_d( @@ -291,7 +313,8 @@ void box_intersection_d( Invocation with custom box traits. */ -template< class RandomAccessIterator1, +template< class ConcurrencyTag = CGAL::Sequential_tag, + class RandomAccessIterator1, class RandomAccessIterator2, class Callback, class BoxTraits > void box_intersection_d( @@ -489,8 +512,11 @@ namespace CGAL { \cgalHeading{Implementation} - See the implementation section of the `box_intersection_d()` - function. + See the implementation section of the `box_intersection_d()` function. + +\cgalHeading{Concurrency} + + See the concurrency section of the `box_intersection_d()` function. \cgalHeading{Example} @@ -520,7 +546,8 @@ namespace CGAL { `RandomAccessIterator`. */ -template< class RandomAccessIterator, class Callback > +template< class ConcurrencyTag = CGAL::Sequential_tag, + class RandomAccessIterator, class Callback > void box_self_intersection_d( RandomAccessIterator begin, RandomAccessIterator end, Callback callback, @@ -532,7 +559,8 @@ void box_self_intersection_d( Invocation with custom box traits. */ -template< class RandomAccessIterator, +template< class ConcurrencyTag = CGAL::Sequential_tag + class RandomAccessIterator, class Callback, class BoxTraits > void box_self_intersection_d( RandomAccessIterator begin, RandomAccessIterator end, From 6bd31f593e3b8ac89677b854a5d681167e083420 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 3 Dec 2019 14:30:11 +0100 Subject: [PATCH 076/185] Minor doc fix --- .../include/CGAL/Polygon_mesh_processing/self_intersections.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index c0abe0e8d84..2a69d29b960 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -387,7 +387,7 @@ self_intersections_impl(const FaceRange& face_range, * Possible values are `Sequential_tag`, `Parallel_tag`, and `Parallel_if_available_tag`. * @tparam FaceRange a model of `ConstRange` with value type `boost::graph_traits::%face_descriptor`. * @tparam TriangleMesh a model of `FaceListGraph` - * @tparam OutputIterator a model of `OutputIterator` holding objects of type + * @tparam FacePairOutputIterator a model of `OutputIterator` holding objects of type * `std::pair::%face_descriptor, boost::graph_traits::%face_descriptor>` * @tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" * @@ -444,7 +444,7 @@ self_intersections(const FaceRange& face_range, * @tparam ConcurrencyTag enables sequential versus parallel algorithm. * Possible values are `Sequential_tag`, `Parallel_tag`, and `Parallel_if_available_tag`. * @tparam TriangleMesh a model of `FaceListGraph` - * @tparam FacePairOutputIterator a model of `FacePairOutputIterator` holding objects of type + * @tparam FacePairOutputIterator a model of `OutputIterator` holding objects of type * `std::pair::%face_descriptor, boost::graph_traits::%face_descriptor>` * @tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" * From 47585d85b5bd5b20b80a827ec6678953e89b136a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 3 Dec 2019 16:12:49 +0100 Subject: [PATCH 077/185] Add an additional comment in the doc about parallel box_intersection_d --- .../doc/Box_intersection_d/CGAL/box_intersection_d.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Box_intersection_d/doc/Box_intersection_d/CGAL/box_intersection_d.h b/Box_intersection_d/doc/Box_intersection_d/CGAL/box_intersection_d.h index 4a7840e47a2..b8eb1310a32 100644 --- a/Box_intersection_d/doc/Box_intersection_d/CGAL/box_intersection_d.h +++ b/Box_intersection_d/doc/Box_intersection_d/CGAL/box_intersection_d.h @@ -250,7 +250,9 @@ void box_intersection_all_pairs_d( if `CGAL::Sequential_tag` - the default value - is specified. The parallelization of the algorithm is based on a divide-and-conquer approach: the two ranges are split in a number of smaller ranges, and - all combinations of subranges are treated in parallel. + all combinations of subranges are treated in parallel. It is thus + recommended to use ranges of pointers to bounding boxes, to keep + these copies light. \warning The parallel mode comes with a small overhead due to the duplication and splitting of the input ranges. It is an improvement From c526d40b4438b6c959e84b439bc011cf1df90e5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 3 Dec 2019 16:17:53 +0100 Subject: [PATCH 078/185] Fix throwing as soon as boxes intersect and not checking for actual intersection --- .../self_intersections.h | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index 2a69d29b960..f6ca79f207d 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -37,6 +37,8 @@ #include #endif +#include + #include #include #include @@ -156,7 +158,7 @@ bool do_faces_intersect(typename boost::graph_traits::halfedge_descriptor h, template -struct Intersect_facets +struct Intersect_faces { typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; @@ -167,7 +169,7 @@ struct Intersect_facets typename GT::Construct_triangle_3 m_construct_triangle; typename GT::Do_intersect_3 m_do_intersect; - Intersect_facets(const TM& tmesh, VPM vpmap, const GT& gt, OutputIterator it) + Intersect_faces(const TM& tmesh, VPM vpmap, const GT& gt, OutputIterator it) : m_iterator(it), m_tmesh(tmesh), @@ -253,6 +255,12 @@ class Throw_at_output_exception : public std::exception { }; +struct Throw_at_output +{ + template + void operator()(const T&) const { throw Throw_at_output_exception(); } +}; + template Throwing_output_iterator; + typedef internal::Intersect_faces Throwing_filter; + Throwing_filter throwing_filter(tmesh, vpmap, gt, Throwing_output_iterator()); #if !defined(CGAL_LINKED_WITH_TBB) CGAL_static_assertion_msg (!(std::is_convertible::value), @@ -336,7 +349,7 @@ self_intersections_impl(const FaceRange& face_range, internal::All_faces_filter all_faces_filter(std::back_inserter(face_pairs)); if(throw_on_SI) - CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(), throwing_callback, cutoff); + CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(), throwing_filter, cutoff); else CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(), all_faces_filter, cutoff); @@ -360,15 +373,15 @@ self_intersections_impl(const FaceRange& face_range, #endif // Sequential version of the code // Compute self-intersections filtered out by boxes - typedef internal::Intersect_facets Intersecting_facet_filter; - Intersecting_facet_filter intersect_facets(tmesh, vpmap, gt, out); + typedef internal::Intersect_faces Intersecting_faces_filter; + Intersecting_faces_filter intersect_faces(tmesh, vpmap, gt, out); if(throw_on_SI) - CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(), throwing_callback, cutoff); + CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(), throwing_filter, cutoff); else - CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(), intersect_facets, cutoff); + CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(), intersect_faces, cutoff); - return intersect_facets.m_iterator; + return intersect_faces.m_iterator; } } // namespace internal From e9e3d9b5b0242e82cf59911681c3c68df3bfcf92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 3 Dec 2019 16:23:35 +0100 Subject: [PATCH 079/185] Add missing includes --- .../include/CGAL/Polygon_mesh_processing/intersection.h | 6 ++++++ .../CGAL/Polygon_mesh_processing/self_intersections.h | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/intersection.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/intersection.h index 13f60f31f03..f46e8ccd821 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/intersection.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/intersection.h @@ -28,10 +28,16 @@ #include #include +#include #include #include #include +#include +#include +#include +#include + namespace CGAL { namespace Polygon_mesh_processing{ namespace internal { diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index f6ca79f207d..a18fde6c068 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -28,8 +28,9 @@ #include #include #include -#include #include +#include +#include #ifdef CGAL_LINKED_WITH_TBB #include From b210bf3f08dcccbd2d1b29ff075fde95a27705a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 3 Dec 2019 19:56:00 +0100 Subject: [PATCH 080/185] Fix conflict in struct names --- .../CGAL/Polygon_mesh_processing/self_intersections.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index a18fde6c068..8e239bc077f 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -159,7 +159,7 @@ bool do_faces_intersect(typename boost::graph_traits::halfedge_descriptor h, template -struct Intersect_faces +struct Strict_intersect_faces // meaning, not just a shared subface { typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; @@ -170,7 +170,7 @@ struct Intersect_faces typename GT::Construct_triangle_3 m_construct_triangle; typename GT::Do_intersect_3 m_do_intersect; - Intersect_faces(const TM& tmesh, VPM vpmap, const GT& gt, OutputIterator it) + Strict_intersect_faces(const TM& tmesh, VPM vpmap, const GT& gt, OutputIterator it) : m_iterator(it), m_tmesh(tmesh), @@ -333,7 +333,7 @@ self_intersections_impl(const FaceRange& face_range, // to do the same as for `self_intersections()`. However, doing like `self_intersections()` would // be a major slow-down over sequential code if there are a lot of self-intersections... typedef boost::function_output_iterator Throwing_output_iterator; - typedef internal::Intersect_faces Throwing_filter; + typedef internal::Strict_intersect_faces Throwing_filter; Throwing_filter throwing_filter(tmesh, vpmap, gt, Throwing_output_iterator()); #if !defined(CGAL_LINKED_WITH_TBB) @@ -374,7 +374,7 @@ self_intersections_impl(const FaceRange& face_range, #endif // Sequential version of the code // Compute self-intersections filtered out by boxes - typedef internal::Intersect_faces Intersecting_faces_filter; + typedef internal::Strict_intersect_faces Intersecting_faces_filter; Intersecting_faces_filter intersect_faces(tmesh, vpmap, gt, out); if(throw_on_SI) From 57fed1416a2fae663da3cab1a30fc49ef73d53d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 4 Dec 2019 09:10:49 +0100 Subject: [PATCH 081/185] Factorize code creating throwing output iterators --- .../self_intersections.h | 17 ++++------------- .../Polyhedron/Plugins/IO/OFF_io_plugin.cpp | 7 +++++-- .../demo/Polyhedron/Scene_surface_mesh_item.cpp | 3 ++- STL_Extension/include/CGAL/exceptions.h | 12 ++++++++++++ 4 files changed, 23 insertions(+), 16 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index 8e239bc077f..c160ccf99e5 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -31,6 +31,7 @@ #include #include #include +#include #ifdef CGAL_LINKED_WITH_TBB #include @@ -252,16 +253,6 @@ struct All_faces_filter }; #endif -class Throw_at_output_exception - : public std::exception -{ }; - -struct Throw_at_output -{ - template - void operator()(const T&) const { throw Throw_at_output_exception(); } -}; - template Throwing_output_iterator; + typedef boost::function_output_iterator Throwing_output_iterator; typedef internal::Strict_intersect_faces Throwing_filter; Throwing_filter throwing_filter(tmesh, vpmap, gt, Throwing_output_iterator()); @@ -539,7 +530,7 @@ bool does_self_intersect(const FaceRange& face_range, CGAL::Emptyset_iterator unused_out; internal::self_intersections_impl(face_range, tmesh, unused_out, true /*throw*/, np); } - catch(internal::Throw_at_output_exception&) + catch(CGAL::internal::Throw_at_output_exception&) { return true; } diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_io_plugin.cpp index 580023022f7..e62593c9b89 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/OFF_io_plugin.cpp @@ -9,13 +9,16 @@ #include #include -#include +#include #include #include #include #include +#include +#include + using namespace CGAL::Three; class Polyhedron_demo_off_plugin : public QObject, @@ -186,7 +189,7 @@ Polyhedron_demo_off_plugin::load_off(QFileInfo fileinfo) { try{ CGAL::Polygon_mesh_processing::non_manifold_vertices(*surface_mesh, OutputIterator()); } - catch( CGAL::internal::Throw_at_output::Throw_at_output_exception& ) + catch( CGAL::internal::Throw_at_output_exception& ) { QApplication::restoreOverrideCursor(); diff --git a/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp b/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp index 88365d2667d..021bbf46a7f 100644 --- a/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp @@ -33,6 +33,7 @@ #include #include "triangulate_primitive.h" +#include #include #include #include @@ -1578,7 +1579,7 @@ QString Scene_surface_mesh_item::computeStats(int type) try{ CGAL::Polygon_mesh_processing::non_manifold_vertices(*d->smesh_, OutputIterator()); } - catch( CGAL::internal::Throw_at_output::Throw_at_output_exception& ) + catch( CGAL::internal::Throw_at_output_exception& ) { d->has_nm_vertices = true; } diff --git a/STL_Extension/include/CGAL/exceptions.h b/STL_Extension/include/CGAL/exceptions.h index 21305a47851..ddd047d395a 100644 --- a/STL_Extension/include/CGAL/exceptions.h +++ b/STL_Extension/include/CGAL/exceptions.h @@ -185,7 +185,19 @@ public: "warning condition failed") {} }; +namespace internal { +// The following classes are useful to create output iterators (with the help +// of boost::function_output_iterator) that will throw as soon as something is being written. +class Throw_at_output_exception : public std::exception { }; + +struct Throw_at_output +{ + template + void operator()(const T& /* t */) const { throw Throw_at_output_exception(); } +}; + +} // namespace internal } //namespace CGAL #endif // CGAL_EXCEPTIONS_H From 5fdeb063261f825b86334fce38ecee335e49306a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 11 Dec 2019 09:36:27 +0100 Subject: [PATCH 082/185] Generalize box_d 'divide and conquer' approach to any given integer --- .../include/CGAL/box_intersection_d.h | 172 ++++++++++++------ 1 file changed, 117 insertions(+), 55 deletions(-) diff --git a/Box_intersection_d/include/CGAL/box_intersection_d.h b/Box_intersection_d/include/CGAL/box_intersection_d.h index ca0683a0a67..fb70c7ad6c2 100644 --- a/Box_intersection_d/include/CGAL/box_intersection_d.h +++ b/Box_intersection_d/include/CGAL/box_intersection_d.h @@ -29,7 +29,7 @@ #include #ifdef CGAL_LINKED_WITH_TBB -#include +#include #endif #include @@ -68,71 +68,133 @@ void box_intersection_segment_tree_d( #else // CGAL_LINKED_WITH_TBB if(boost::is_convertible::value) { - // Below takes both box ranges and split each range in 3, and then does cross products - // to get all combinations (9 pairs). + // Here is an illustration for n=2. // - // 3 is chosen such that we get 9 tasks in parallel, which is close to the usual number - // of threads (8-12) on a (current) "normal" machine. This could potentially be generalized - // by grabbing the number of available threads (n = std::thread::hardware_concurrency()) and - // splitting in 'i' and 'j' such that i*j=n. + // Doing a R1-R2 intersection with a 2-split is doing 4 subpairs in parallel + // a-c and b-d + // r1[0][0] --a-- r1[0][1] --b-- r1[0][2] + // r2[0][0] --c-- r2[0][1] --d-- r2[0][2] // - // The memory footprint due to having to duplicate box ranges is empirically observed - // to be negligible (as long as a range of pointers is passed) + // a-d and b-c + // r1[1][0] --a-- r1[1][1] --b-- r1[1][2] + // r2[1][0] --c-- r2[1][1] --d-- r2[1][2] // - typedef typename std::iterator_traits::value_type val_t; - typedef typename std::vector< val_t>::iterator It; + // Ranges must be duplicates since sorting is performed - typename std::iterator_traits::difference_type r1_third = std::distance(begin1, end1) / 3; - typename std::iterator_traits::difference_type r1_two_third = 2 * r1_third; - typename std::iterator_traits::difference_type r2_third = std::distance(begin2, end2) / 3; - typename std::iterator_traits::difference_type r2_two_third = 2 * r2_third; + typedef typename std::iterator_traits::value_type val_t; + typedef typename std::iterator_traits::difference_type diff_size; - CGAL_assertion(0 <= r1_third && r1_third <= r1_two_third && - (r1_two_third < std::distance(begin1, end1) || std::distance(begin1, end1) == 0)); - CGAL_assertion(0 <= r2_third && r2_third <= r2_two_third && - (r2_two_third < std::distance(begin2, end2) || std::distance(begin2, end2) == 0)); + typedef std::vector val_container; + typedef typename val_container::iterator It; - std::vector< val_t> r3( begin1, end1); - std::vector< val_t> r4( begin2, end2); - std::vector< val_t> r5( begin1, end1); - std::vector< val_t> r6( begin2, end2); + static constexpr int n = 4; - RandomAccessIter1 r1_left = begin1; std::advance(r1_left, r1_third); - RandomAccessIter2 r2_left = begin2; std::advance(r2_left, r2_third); - It r3_left = r3.begin(); std::advance(r3_left, r1_third); - It r4_left = r4.begin(); std::advance(r4_left, r2_third); - It r5_left = r5.begin(); std::advance(r5_left, r1_third); - It r6_left = r6.begin(); std::advance(r6_left, r2_third); + const diff_size r1s = std::distance(begin1, end1); + const diff_size r2s = std::distance(begin2, end2); - RandomAccessIter1 r1_right = begin1; std::advance(r1_right, r1_two_third); - RandomAccessIter2 r2_right = begin2; std::advance(r2_right, r2_two_third); - It r3_right = r3.begin(); std::advance(r3_right, r1_two_third); - It r4_right = r4.begin(); std::advance(r4_right, r2_two_third); - It r5_right = r5.begin(); std::advance(r5_right, r1_two_third); - It r6_right = r6.begin(); std::advance(r6_right, r2_two_third); + val_container range_1_copies, range_2_copies; + range_1_copies.reserve(r1s * n); + range_2_copies.reserve(r2s * n); - tbb::parallel_invoke([&]{ Box_intersection_d::segment_tree( begin1, r1_left, begin2, r2_left, inf, sup, - callback, traits, cutoff, dim, in_order); }, - [&]{ Box_intersection_d::segment_tree( r1_left, r1_right, r2_left, r2_right, inf, sup, - callback, traits, cutoff, dim, in_order); }, - [&]{ Box_intersection_d::segment_tree( r1_right, end1, r2_right, end2, inf, sup, - callback, traits, cutoff, dim, in_order); }, + const diff_size r1_step = r1s / n; + const diff_size r2_step = r2s / n; - // shifted 1 - [&]{ Box_intersection_d::segment_tree( r3.begin(), r3_left, r4_left, r4_right, inf, sup, - callback, traits, cutoff, dim, in_order); }, - [&]{ Box_intersection_d::segment_tree( r3_left, r3_right, r4_right, r4.end(), inf, sup, - callback, traits, cutoff, dim, in_order); }, - [&]{ Box_intersection_d::segment_tree( r3_right, r3.end(), r4.begin(), r4_left, inf, sup, - callback, traits, cutoff, dim, in_order); }, + for(int i=0; i, n> range_1_iterators; + std::array, n> range_2_iterators; + + for(int i=0; i Date: Wed, 11 Dec 2019 09:52:52 +0100 Subject: [PATCH 083/185] Reintegrate the callback within the call to box_intersection_d() This is motivated by the fact that if you have a configuration where there is a large number of boxes intersection (such as k*n^2, with n being the number of faces), then the size of the concurrent container can be very large and thus the memory footprint would be huge. Instead, since the box_intersection_d call is now parallel, we can just do callbacks in the tree directly. The only thing is, we want to have these (heavy) callback calls to be roughly balanced. For this, we random shuffle the range of faces. Same runtime as before, no more huge memory footprint! --- .../self_intersections.h | 103 ++++-------------- 1 file changed, 20 insertions(+), 83 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index c160ccf99e5..5a00000fbc1 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -24,14 +24,16 @@ #include #include +#include #include #include #include #include -#include +#include #include #include -#include +#include +#include #ifdef CGAL_LINKED_WITH_TBB #include @@ -191,68 +193,6 @@ struct Strict_intersect_faces // meaning, not just a shared subface } }; -#ifdef CGAL_LINKED_WITH_TBB -// The functor doing all geometric tests in parallel -template -struct Concurrent_face_intersection_tester -{ - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename boost::graph_traits::face_descriptor face_descriptor; - - const TM& m_tmesh; - const VPM m_vpmap; - const FacePairs& m_face_pairs; - DoIntersectVector& m_do_intersect_vector; - typename GT::Construct_segment_3 m_construct_segment; - typename GT::Construct_triangle_3 m_construct_triangle; - typename GT::Do_intersect_3 m_do_intersect; - - Concurrent_face_intersection_tester(const FacePairs& face_pairs, - DoIntersectVector& do_intersect_vector, - const TM& tmesh, - VPM vpmap, - const GT& gt) - : - m_tmesh(tmesh), - m_vpmap(vpmap), - m_face_pairs(face_pairs), - m_do_intersect_vector(do_intersect_vector), - m_construct_segment(gt.construct_segment_3_object()), - m_construct_triangle(gt.construct_triangle_3_object()), - m_do_intersect(gt.do_intersect_3_object()) - {} - - void operator()(const tbb::blocked_range &r) const - { - for(std::size_t ri = r.begin(); ri != r.end(); ++ri) - this->operator()(ri); - } - - void operator()(std::size_t ri) const - { - const std::pair& ff = m_face_pairs[ri]; - halfedge_descriptor h = halfedge(ff.first, m_tmesh), g = halfedge(ff.second, m_tmesh); - - if(do_faces_intersect(h, g, m_tmesh, m_vpmap, m_construct_segment, m_construct_triangle, m_do_intersect)) - m_do_intersect_vector[ri] = true; - } -}; - -// This filter does not filter anything, but simply forwards intersecting pair information so that -// filtering can be done outside of the call to 'box_intersection_d' -template -struct All_faces_filter -{ - All_faces_filter(OutputIterator it) : m_iterator(it) { } - - template - void operator()(const Box* b, const Box* c) const { *m_iterator++ = std::make_pair(b->info(), c->info()); } - - mutable OutputIterator m_iterator; -}; -#endif - template ::value) { - // (A) Parallel: Write all pairs of faces with intersecting bbox - typedef tbb::concurrent_vector > Face_pairs; - typedef std::back_insert_iterator Face_pairs_back_inserter; + // We are going to split the range into a number of smaller ranges. To handle + // smaller trees of roughly the same size, we first apply a random shuffle to the range + CGAL::Random rng(seed); + CGAL::cpp98::random_shuffle(box_ptr.begin(), box_ptr.end(), rng); + + // Write in a concurrent vector all pairs that intersect + typedef tbb::concurrent_vector > Face_pairs; + typedef std::back_insert_iterator Face_pairs_back_inserter; + typedef internal::Strict_intersect_faces Intersecting_faces_filter; Face_pairs face_pairs; - internal::All_faces_filter all_faces_filter(std::back_inserter(face_pairs)); + Intersecting_faces_filter callback(tmesh, vpmap, gt, std::back_inserter(face_pairs)); if(throw_on_SI) CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(), throwing_filter, cutoff); else - CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(), all_faces_filter, cutoff); + CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(), callback, cutoff); - // (B) Parallel: Perform the geometric tests - typedef std::vector Do_intersect_vector; - typedef internal::Concurrent_face_intersection_tester Tester; - - Do_intersect_vector do_intersect(face_pairs.size(), 0); - Tester tester(face_pairs, do_intersect, tmesh, vpmap, gt); - tbb::parallel_for(tbb::blocked_range(0, face_pairs.size()), tester); - - // (C) Sequential: Copy from the concurent container to the output iterator - for(std::size_t i=0; i Date: Thu, 12 Dec 2019 14:21:12 -0800 Subject: [PATCH 084/185] Set the precision when saving a mesh --- Surface_mesh/test/Surface_mesh/sm_ply_io.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Surface_mesh/test/Surface_mesh/sm_ply_io.cpp b/Surface_mesh/test/Surface_mesh/sm_ply_io.cpp index c18b6523b74..b42b87410d7 100644 --- a/Surface_mesh/test/Surface_mesh/sm_ply_io.cpp +++ b/Surface_mesh/test/Surface_mesh/sm_ply_io.cpp @@ -39,6 +39,7 @@ int main() CGAL::read_ply (in2, mesh); std::ofstream out ("out.ply"); + out.precision(17); // CGAL::set_binary_mode(out); CGAL::write_ply (out, mesh); From d46eb996447032c22b26515e1ee12691524a3374 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 13 Dec 2019 08:32:48 +0100 Subject: [PATCH 085/185] add clipping overload to a iso-cuboid --- .../CGAL/Polygon_mesh_processing/clip.h | 75 ++++++++++++++++++- .../Polygon_mesh_processing/test_pmp_clip.cpp | 11 +++ 2 files changed, 85 insertions(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h index 0b2e28fd8fa..069e0cdecb6 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h @@ -360,7 +360,8 @@ bool dispatch_clip_call(TriangleMesh& tm, TriangleMesh& clipper, * If `tm` is closed, the clipped part can be closed too if the named parameter `clip_volume` is set to `true`. * See subsection \ref coref_clip for more details. * - * \note In the current implementation it is not possible to set the vertex point map and the default will be used. + * \note In the current implementation it is not possible to set the vertex point map and the default will be used. `Plane_3` must be + * from the same Kernel as the point of the vertex point map. * \pre \link CGAL::Polygon_mesh_processing::does_self_intersect() `!CGAL::Polygon_mesh_processing::does_self_intersect(tm)` \endlink * * @tparam TriangleMesh a model of `MutableFaceGraph`, `HalfedgeListGraph` and `FaceListGraph`. @@ -432,6 +433,70 @@ bool clip( TriangleMesh& tm, np, CGAL::graph_has_property()); } +/** + * \ingroup PMP_corefinement_grp + * clips `tm` by keeping the part that is inside `iso_cuboid`. + * If `tm` is closed, the clipped part can be closed too if the named parameter `clip_volume` is set to `true`. + * See subsection \ref coref_clip for more details. + * + * \note In the current implementation it is not possible to set the vertex point map and the default will be used. `Iso_cuboid_3` must be + * from the same Kernel as the point of the vertex point map. + * \pre \link CGAL::Polygon_mesh_processing::does_self_intersect() `!CGAL::Polygon_mesh_processing::does_self_intersect(tm)` \endlink + * + * @tparam TriangleMesh a model of `MutableFaceGraph`, `HalfedgeListGraph` and `FaceListGraph`. + * If `TriangleMesh` has an internal property map for `CGAL::face_index_t`, + * as a named parameter, then it must be initialized. + * An internal property map for `CGAL::vertex_point_t` must be available. + * + * @tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" + * + * @param tm input triangulated surface mesh + * @param iso_cuboid iso-cuboid used to clip `tm`. + * @param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below + * + * \cgalNamedParamsBegin + * \cgalParamBegin{visitor} a class model of `PMPCorefinementVisitor` + * that is used to track the creation of new faces. + * \cgalParamEnd + * \cgalParamBegin{throw_on_self_intersection} if `true`, + * the set of triangles closed to the intersection of `tm` and `plane` will be + * checked for self-intersections and `CGAL::Polygon_mesh_processing::Corefinement::Self_intersection_exception` + * will be thrown if at least one is found. + * \cgalParamEnd + * \cgalParamBegin{clip_volume} if `true` and `tm` is closed, the clipping will be done on + * the volume \link coref_def_subsec bounded \endlink by `tm` rather than on its surface + * (i.e. `tm` will be kept closed). + * \cgalParamEnd + * \cgalParamBegin{use_compact_clipper} if `false` and `clip_volume` is `false` and `tm` is open, the parts of `tm` coplanar with `plane` + * will not be part of the output. + * \cgalNamedParamsEnd + * + * @return `true` if the output surface mesh is manifold. + * If `false` is returned `tm` is only refined by the intersection with `plane`. + */ +template +bool clip( TriangleMesh& tm, + #ifdef DOXYGEN_RUNNING + const Iso_cuboid_3& iso_cuboid, + #else + const typename GetGeomTraits::type::Iso_cuboid_3& iso_cuboid, + #endif + const NamedParameters& np) +{ + if( boost::begin(faces(tm))==boost::end(faces(tm)) ) return true; + TriangleMesh clipper; + + make_hexahedron(iso_cuboid[0], iso_cuboid[1], iso_cuboid[2], iso_cuboid[3], + iso_cuboid[4], iso_cuboid[5], iso_cuboid[6], iso_cuboid[7], + clipper); + triangulate_faces(clipper); + + // dispatch is needed because face index map for tm and clipper have to be of the same time + return internal::dispatch_clip_call(tm, clipper, + np, CGAL::graph_has_property()); +} + /// \cond SKIP_IN_MANUAL // convenience overloads @@ -442,6 +507,14 @@ bool clip( TriangleMesh& tm, return clip(tm, plane, parameters::all_default()); } +// convenience overloads +template +bool clip( TriangleMesh& tm, + const typename GetGeomTraits::type::Iso_cuboid_3& iso_cuboid) +{ + return clip(tm, iso_cuboid, parameters::all_default()); +} + // convenience overload template diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_clip.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_clip.cpp index f330133421e..23efd0a3788 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_clip.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_clip.cpp @@ -51,6 +51,17 @@ void test() CGAL::clear(tm1); CGAL::clear(tm2); + + // test with a iso-cuboid + input.open("data-coref/elephant.off"); + input >> tm1; + input.close(); + K::Iso_cuboid_3 iso_cuboid(K::Point_3(0,0,0), K::Point_3(0.4, 0.6, 0.4)); + + PMP::clip(tm1, iso_cuboid, params::clip_volume(true)); + assert(CGAL::is_closed(tm1)); + CGAL::clear(tm1); + // test with a plane input.open("data-coref/cube.off"); input >> tm1; From 01893797672b053591f7d66959782021d2802149 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 13 Dec 2019 10:47:17 +0100 Subject: [PATCH 086/185] update doc after review --- .../include/CGAL/Polygon_mesh_processing/clip.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h index 069e0cdecb6..4f516b8b18e 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h @@ -266,7 +266,7 @@ clip_to_bbox(const Plane_3& plane, * clips `tm` by keeping the part that is inside the volume \link coref_def_subsec bounded \endlink * by `clipper`. * If `tm` is closed, the clipped part can be closed too if the named parameter `clip_volume` is set to `true`. - * See subsection \ref coref_clip for more details. + * See Subsection \ref coref_clip for more details. * \attention With the current implementation, `clipper` will be modified (refined with the intersection with `tm`). * * \pre \link CGAL::Polygon_mesh_processing::does_self_intersect() `!CGAL::Polygon_mesh_processing::does_self_intersect(tm1)` \endlink @@ -305,7 +305,7 @@ clip_to_bbox(const Plane_3& plane, * \cgalParamEnd * \cgalParamBegin{clip_volume} if `true` and `tm` is closed, the clipping will be done on * the volume \link coref_def_subsec bounded \endlink by `tm` rather than on its surface - * (i.e. `tm` will be kept closed). + * (i.e., `tm` will be kept closed). * \cgalParamEnd * \cgalParamBegin{use_compact_clipper} if `false` and `clip_volume` is `false` and `tm` is open, the parts of `tm` coplanar with `clipper` * will not be part of the output. @@ -358,10 +358,10 @@ bool dispatch_clip_call(TriangleMesh& tm, TriangleMesh& clipper, * \ingroup PMP_corefinement_grp * clips `tm` by keeping the part that is on the negative side of `plane` (side opposite to its normal vector). * If `tm` is closed, the clipped part can be closed too if the named parameter `clip_volume` is set to `true`. - * See subsection \ref coref_clip for more details. + * See Subsection \ref coref_clip for more details. * * \note In the current implementation it is not possible to set the vertex point map and the default will be used. `Plane_3` must be - * from the same Kernel as the point of the vertex point map. + * from the same %Kernel as the point of the vertex point map. * \pre \link CGAL::Polygon_mesh_processing::does_self_intersect() `!CGAL::Polygon_mesh_processing::does_self_intersect(tm)` \endlink * * @tparam TriangleMesh a model of `MutableFaceGraph`, `HalfedgeListGraph` and `FaceListGraph`. @@ -387,7 +387,7 @@ bool dispatch_clip_call(TriangleMesh& tm, TriangleMesh& clipper, * \cgalParamEnd * \cgalParamBegin{clip_volume} if `true` and `tm` is closed, the clipping will be done on * the volume \link coref_def_subsec bounded \endlink by `tm` rather than on its surface - * (i.e. `tm` will be kept closed). + * (i.e., `tm` will be kept closed). * \cgalParamEnd * \cgalParamBegin{use_compact_clipper} if `false` and `clip_volume` is `false` and `tm` is open, the parts of `tm` coplanar with `plane` * will not be part of the output. @@ -437,10 +437,10 @@ bool clip( TriangleMesh& tm, * \ingroup PMP_corefinement_grp * clips `tm` by keeping the part that is inside `iso_cuboid`. * If `tm` is closed, the clipped part can be closed too if the named parameter `clip_volume` is set to `true`. - * See subsection \ref coref_clip for more details. + * See Subsection \ref coref_clip for more details. * * \note In the current implementation it is not possible to set the vertex point map and the default will be used. `Iso_cuboid_3` must be - * from the same Kernel as the point of the vertex point map. + * from the same %Kernel as the point of the vertex point map. * \pre \link CGAL::Polygon_mesh_processing::does_self_intersect() `!CGAL::Polygon_mesh_processing::does_self_intersect(tm)` \endlink * * @tparam TriangleMesh a model of `MutableFaceGraph`, `HalfedgeListGraph` and `FaceListGraph`. @@ -465,7 +465,7 @@ bool clip( TriangleMesh& tm, * \cgalParamEnd * \cgalParamBegin{clip_volume} if `true` and `tm` is closed, the clipping will be done on * the volume \link coref_def_subsec bounded \endlink by `tm` rather than on its surface - * (i.e. `tm` will be kept closed). + * (i.e., `tm` will be kept closed). * \cgalParamEnd * \cgalParamBegin{use_compact_clipper} if `false` and `clip_volume` is `false` and `tm` is open, the parts of `tm` coplanar with `plane` * will not be part of the output. From 49d36567311968015862660f715ba5a4b23175db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 13 Dec 2019 10:57:57 +0100 Subject: [PATCH 087/185] use generic type --- .../include/CGAL/Polygon_mesh_processing/connected_components.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/connected_components.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/connected_components.h index 850c855a8e0..90122fdde19 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/connected_components.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/connected_components.h @@ -245,7 +245,7 @@ connected_components(const PolygonMesh& pmesh, if ( handled[fq_id]) continue; handled[fq_id]=true; put(fcm, fq, i); - for (typename PolygonMesh::Halfedge_index h : halfedges_around_face(halfedge(fq, pmesh), pmesh)) + for (halfedge_descriptor h : halfedges_around_face(halfedge(fq, pmesh), pmesh)) { if ( get(ecmap, edge(h, pmesh)) ) continue; halfedge_descriptor opp = opposite(h, pmesh); From 64bce3fd90109326cd7095e4b99ef71dd0812d68 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 13 Dec 2019 16:27:52 +0100 Subject: [PATCH 088/185] Remove tehe option WITH_GMPXX completely --- Installation/CMakeLists.txt | 8 +------- Installation/cmake/modules/CGAL_SetupGMP.cmake | 2 -- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/Installation/CMakeLists.txt b/Installation/CMakeLists.txt index 8fee098dc9a..54f0bee3d41 100644 --- a/Installation/CMakeLists.txt +++ b/Installation/CMakeLists.txt @@ -621,9 +621,6 @@ if(CGAL_DISABLE_GMP) "#error GMP is disabled by the CMake option CGAL_DISABLE_GMP") else() list(APPEND CGAL_ESSENTIAL_3RD_PARTY_LIBRARIES GMP MPFR) - if(WITH_GMPXX) - list(APPEND CGAL_ESSENTIAL_3RD_PARTY_LIBRARIES GMPXX) - endif() # When CMake is run several times, to avoid duplicates list (REMOVE_DUPLICATES CGAL_ESSENTIAL_3RD_PARTY_LIBRARIES) @@ -643,11 +640,8 @@ foreach (lib ${CGAL_SUPPORTING_3RD_PARTY_LIBRARIES}) # add option list( FIND CGAL_ESSENTIAL_3RD_PARTY_LIBRARIES "${lib}" POSITION ) if ( "${POSITION}" STRGREATER "-1" ) # if lib is essential - option(WITH_${lib} "Select external library ${lib}" ON) + else() #GMPXX set in CGAL_SetupGMP.cmake - if(NOT "${lib}" STREQUAL "GMPXX") - option(WITH_${lib} "Select external library ${lib}" OFF) - endif() endif() endforeach() diff --git a/Installation/cmake/modules/CGAL_SetupGMP.cmake b/Installation/cmake/modules/CGAL_SetupGMP.cmake index 26fc412e135..6627df01796 100644 --- a/Installation/cmake/modules/CGAL_SetupGMP.cmake +++ b/Installation/cmake/modules/CGAL_SetupGMP.cmake @@ -27,10 +27,8 @@ find_package(GMPXX QUIET) if(NOT GMPXX_FOUND) option(CGAL_WITH_GMPXX "Use CGAL with GMPXX: use C++ classes of GNU MP instead of CGAL wrappers" OFF) - option(WITH_GMPXX "Select external library GMPXX" OFF) else() option(CGAL_WITH_GMPXX "Use CGAL with GMPXX: use C++ classes of GNU MP instead of CGAL wrappers" ON) - option(WITH_GMPXX "Select external library GMPXX" ON) endif() #.rst: From 0a150dd3d28b2252d5f0d20057013cf6377a069e Mon Sep 17 00:00:00 2001 From: Oleg Alexandrov Date: Sat, 14 Dec 2019 09:43:19 -0800 Subject: [PATCH 089/185] Improve the instructions The compilation instructions have been very confusing. Its first section suggests that no libraries are needed and no CMakeLists is needed. Also the same block of code is repeated three times. I removed the redundant and incorrect first section, made it clear early on how to create a CMakeLists.txt, and that linking to external libraries is necessary. I did not remove any information. --- INSTALL.md | 42 +++++++----------------------------------- 1 file changed, 7 insertions(+), 35 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 8913be934e0..ad26ab28e34 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,41 +1,7 @@ -NOTICE -====== - -Since Version 5.0, CGAL is a header-only library it is not needed -to build and install it. Usage of CGAL should thus simply amount to: - -``` {.bash} -git clone https://github.com/CGAL/cgal.git /path/to/cgal.git -cd /path/to/cgal.git/Triangulation_2/examples/Triangulation_2 -mkdir -p build/debug -cd build/debug -cmake -DCMAKE_BUILD_TYPE=Debug -DCGAL_DIR=/path/to/cgal.git -make -``` - -in the case of the building of an example in debug mode. - -For more information head over to the [CGAL manual](https://doc.cgal.org/latest/Manual/general_intro.html). -Note that this page describes the setting of CGAL as a sources release and, as such, -files are organized in a slightly different way, see the [Layout of the CGAL Git Repository](README.md). - - Building a Program Using CGAL ============================= -To compile a program using CGAL, simply set `CGAL_DIR` to the location -of the directory containing `CGALConfig.cmake` (for example the root -of the extracted source archive or the root of a git checkout). - -Here is an example of how to build in debug the examples from the 3D Triangulations package: - -``` {.bash} - cd /path/to/cgal.git/Triangulation_3/examples/Triangulation_3 - mkdir -p build/debug - cd build/debug - cmake -DCGAL_DIR:PATH=/path/to/cgal.git ../.. - make -``` +Since Version 5.0, CGAL is header-only, hence it does not create a library. It needs however to link to the external libraries GMP and MPRF. If you are trying to build examples or tests that do not already have a `CMakeLists.txt`, you can trigger its creation by calling the script [`cgal_create_cmake_script`](Scripts/scripts/cgal_create_cmake_script) @@ -52,4 +18,10 @@ Here is an example for the examples of the 2D Triangulation package: make ``` +Note that this page describes the setting of CGAL as a sources release and, as such, +files are organized in a slightly different way, see the [Layout of the CGAL Git Repository](README.md). + For more information head over to the [CGAL manual](https://doc.cgal.org/latest/Manual/general_intro.html). + + + From 38be1385b219952ad626f66ab7f3cb57b5369438 Mon Sep 17 00:00:00 2001 From: Oleg Alexandrov Date: Sat, 14 Dec 2019 10:00:58 -0800 Subject: [PATCH 090/185] Improve the commit per suggestions Clarify the dependencies And minor wording fix Avoid duplicating words --- INSTALL.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index ad26ab28e34..91a981a2f70 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,12 +1,12 @@ Building a Program Using CGAL ============================= -Since Version 5.0, CGAL is header-only, hence it does not create a library. It needs however to link to the external libraries GMP and MPRF. +Since Version 5.0, CGAL is header-only, hence it does not create a library. Some parts of it, however, link to several external libraries, such as GMP, MPFR, etc. If you are trying to build examples or tests that do not already have a `CMakeLists.txt`, you can trigger its creation by calling the script [`cgal_create_cmake_script`](Scripts/scripts/cgal_create_cmake_script) found in `/path/to/cgal.git/Scripts/scripts/` at the root of the example/test directory. -Here is an example for the examples of the 2D Triangulation package: +Here is a recipe for the examples of the 2D Triangulation package: ``` {.bash} cd /path/to/cgal.git/Triangulation_2/examples/Triangulation_2 @@ -22,6 +22,3 @@ Note that this page describes the setting of CGAL as a sources release and, as s files are organized in a slightly different way, see the [Layout of the CGAL Git Repository](README.md). For more information head over to the [CGAL manual](https://doc.cgal.org/latest/Manual/general_intro.html). - - - From 0783723f477983513ce640237f83c4490e4a4aac Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 16 Dec 2019 09:30:54 +0100 Subject: [PATCH 091/185] restore wrongly deleted lines --- Installation/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Installation/CMakeLists.txt b/Installation/CMakeLists.txt index 54f0bee3d41..8a9ee567b62 100644 --- a/Installation/CMakeLists.txt +++ b/Installation/CMakeLists.txt @@ -640,7 +640,9 @@ foreach (lib ${CGAL_SUPPORTING_3RD_PARTY_LIBRARIES}) # add option list( FIND CGAL_ESSENTIAL_3RD_PARTY_LIBRARIES "${lib}" POSITION ) if ( "${POSITION}" STRGREATER "-1" ) # if lib is essential - + option(WITH_${lib} "Select external library ${lib}" ON) + else() + option(WITH_${lib} "Select external library ${lib}" OFF) else() #GMPXX set in CGAL_SetupGMP.cmake endif() From c7c35c24f721b66a7687c5f76961727bfb551354 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 16 Dec 2019 09:37:52 +0100 Subject: [PATCH 092/185] Remove remaining WITH_GMPXX in list --- Installation/CMakeLists.txt | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Installation/CMakeLists.txt b/Installation/CMakeLists.txt index 8a9ee567b62..735b4a8e649 100644 --- a/Installation/CMakeLists.txt +++ b/Installation/CMakeLists.txt @@ -568,10 +568,6 @@ message("== Detect external libraries ==") # Coin is used in KDS, but no FindCoin or FindCOIN exists # There exists FindIPE, FindMKL, but they are only used to support supporting libs list (INSERT CGAL_SUPPORTING_3RD_PARTY_LIBRARIES 0 GMP MPFR ZLIB OpenGL LEDA MPFI RS RS3 OpenNL Eigen3 ESBTL Coin3D NTL IPE) -if (NOT WIN32) - # GMPXX is not supported on WIN32 machines - list (INSERT CGAL_SUPPORTING_3RD_PARTY_LIBRARIES 1 GMPXX) -endif() # Where CMake is run several times, to avoid duplicates list(REMOVE_DUPLICATES CGAL_SUPPORTING_3RD_PARTY_LIBRARIES) @@ -611,8 +607,6 @@ if(CGAL_DISABLE_GMP) unset(WITH_GMP CACHE) unset(CGAL_USE_GMP) unset(CGAL_USE_GMP CACHE) - unset(WITH_GMPXX) - unset(WITH_GMPXX CACHE) unset(WITH_MPFR) unset(WITH_MPFR CACHE) @@ -643,7 +637,6 @@ foreach (lib ${CGAL_SUPPORTING_3RD_PARTY_LIBRARIES}) option(WITH_${lib} "Select external library ${lib}" ON) else() option(WITH_${lib} "Select external library ${lib}" OFF) - else() #GMPXX set in CGAL_SetupGMP.cmake endif() endforeach() From a777e02da314ee5887b793d924bd31472967887d Mon Sep 17 00:00:00 2001 From: Sebastien Loriot Date: Mon, 16 Dec 2019 10:13:56 +0100 Subject: [PATCH 093/185] copy-paste error --- .../include/CGAL/Polygon_mesh_processing/clip.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h index 4f516b8b18e..4ba19542fb7 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h @@ -467,7 +467,7 @@ bool clip( TriangleMesh& tm, * the volume \link coref_def_subsec bounded \endlink by `tm` rather than on its surface * (i.e., `tm` will be kept closed). * \cgalParamEnd - * \cgalParamBegin{use_compact_clipper} if `false` and `clip_volume` is `false` and `tm` is open, the parts of `tm` coplanar with `plane` + * \cgalParamBegin{use_compact_clipper} if `false` and `clip_volume` is `false` and `tm` is open, the parts of `tm` coplanar with `is_cuboid` * will not be part of the output. * \cgalNamedParamsEnd * From 1ff278eb35d03f465c32f2bf0cfdaa5c39e4a105 Mon Sep 17 00:00:00 2001 From: Sebastien Loriot Date: Mon, 16 Dec 2019 10:14:33 +0100 Subject: [PATCH 094/185] copy-paste error --- .../include/CGAL/Polygon_mesh_processing/clip.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h index 4ba19542fb7..90df3c31648 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h @@ -472,7 +472,7 @@ bool clip( TriangleMesh& tm, * \cgalNamedParamsEnd * * @return `true` if the output surface mesh is manifold. - * If `false` is returned `tm` is only refined by the intersection with `plane`. + * If `false` is returned `tm` is only refined by the intersection with `iso_cuboid`. */ template From 65072b4a33badb2c19b37a5bbf7b5036663d9e9f Mon Sep 17 00:00:00 2001 From: Sebastien Loriot Date: Mon, 16 Dec 2019 10:15:07 +0100 Subject: [PATCH 095/185] copy-paste error --- .../include/CGAL/Polygon_mesh_processing/clip.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h index 90df3c31648..ca4256c3977 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h @@ -459,7 +459,7 @@ bool clip( TriangleMesh& tm, * that is used to track the creation of new faces. * \cgalParamEnd * \cgalParamBegin{throw_on_self_intersection} if `true`, - * the set of triangles closed to the intersection of `tm` and `plane` will be + * the set of triangles closed to the intersection of `tm` and `iso_cuboid` will be * checked for self-intersections and `CGAL::Polygon_mesh_processing::Corefinement::Self_intersection_exception` * will be thrown if at least one is found. * \cgalParamEnd From 8cdcd006f0e3d28fd2679ff96f5ad94a423bc3fa Mon Sep 17 00:00:00 2001 From: Mael Date: Tue, 17 Dec 2019 17:57:54 +0100 Subject: [PATCH 096/185] Use 'seed' even when TBB is not linked --- .../include/CGAL/Polygon_mesh_processing/self_intersections.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index 5a00000fbc1..55563d8b1da 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -34,6 +34,7 @@ #include #include #include +#include #ifdef CGAL_LINKED_WITH_TBB #include @@ -224,6 +225,7 @@ self_intersections_impl(const FaceRange& face_range, get_const_property_map(boost::vertex_point, tmesh)); const unsigned int seed = choose_parameter(get_parameter(np, internal_np::random_seed), 0); + CGAL_USE(seed); // used in the random shuffle of the range, which is only done to balance tasks in parallel const std::ptrdiff_t cutoff = 2000; From 0d7ce069aee919a90db2db13779b768cc8818350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 30 Dec 2019 18:20:26 +0100 Subject: [PATCH 097/185] Add a note explaining rebind mechanisms in the doc of vertex/face typedefs --- TDS_2/doc/TDS_2/CGAL/Triangulation_data_structure_2.h | 8 ++++++-- TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h | 1 + TDS_2/doc/TDS_2/Concepts/TriangulationDSVertexBase_2.h | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/TDS_2/doc/TDS_2/CGAL/Triangulation_data_structure_2.h b/TDS_2/doc/TDS_2/CGAL/Triangulation_data_structure_2.h index 1022d56b585..c547a798b4d 100644 --- a/TDS_2/doc/TDS_2/CGAL/Triangulation_data_structure_2.h +++ b/TDS_2/doc/TDS_2/CGAL/Triangulation_data_structure_2.h @@ -48,10 +48,14 @@ public: typedef Triangulation_data_structure_2 Tds; -/// The vertex type. + /// The vertex type. + /// + /// \sa Section \ref TDS_2TheRebindMechanism typedef typename VertexBase::template Rebind_TDS::Other Vertex; -/// The face type. + /// The face type. + /// + /// \sa Section \ref TDS_2TheRebindMechanism typedef typename FaceBase::template Rebind_TDS::Other Face; /// @} diff --git a/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h b/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h index 4d17e03cf52..085e91d2b79 100644 --- a/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h +++ b/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h @@ -76,6 +76,7 @@ This template class has to define a type `Rebind_TDS::%Other` which is th This type `Other` will be the actual base of the class `CGAL::Triangulation_data_structure_2::Face`. \note It can be implemented using a nested template class. +\sa Section \ref TDS_2TheRebindMechanism */ template using Rebind_TDS = unspecified_type; diff --git a/TDS_2/doc/TDS_2/Concepts/TriangulationDSVertexBase_2.h b/TDS_2/doc/TDS_2/Concepts/TriangulationDSVertexBase_2.h index 35245d1a609..c616d582f7f 100644 --- a/TDS_2/doc/TDS_2/Concepts/TriangulationDSVertexBase_2.h +++ b/TDS_2/doc/TDS_2/Concepts/TriangulationDSVertexBase_2.h @@ -72,6 +72,7 @@ This template class has to define a type `Rebind_TDS::%Other` which is the This type `Other` will be the actual base of the class `CGAL::Triangulation_data_structure_2::Vertex`. \note It can be implemented using a nested template class. +\sa Section \ref TDS_2TheRebindMechanism */ template using Rebind_TDS = unspecified_type; From db357a9ecb340c588ab4e65fb5d0b44cb32c1a17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 30 Dec 2019 18:22:10 +0100 Subject: [PATCH 098/185] TriangulationDSFaceBase_2 should refine TDS2::Face --- .../TDS_2/Concepts/TriangulationDSFaceBase_2.h | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h b/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h index 085e91d2b79..5391b2b51da 100644 --- a/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h +++ b/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h @@ -3,6 +3,8 @@ \ingroup PkgTDS2Concepts \cgalConcept +\cgalRefines `TriangulationDataStructure_2::Face` + The concept `TriangulationDSFaceBase_2` describes the requirements for the face base class of a `CGAL::Triangulation_data_structure_2`. @@ -46,22 +48,16 @@ that the `CGAL::Triangulation_data_structure_2` actually uses as a base class for the class `CGAL::Triangulation_data_structure_2::Face`. -\cgalRefines `TriangulationDataStructure_2::Face` - -\cgalHasModel `CGAL::Triangulation_ds_face_base_2` -\cgalHasModel `CGAL::Triangulation_face_base_2` -\cgalHasModel `CGAL::Regular_triangulation_face_base_2` -\cgalHasModel `CGAL::Constrained_triangulation_face_base_2` -\cgalHasModel `CGAL::Triangulation_face_base_with_info_2` +\cgalHasModel `CGAL::Triangulation_ds_face_base_2` \sa `TriangulationDSVertexBase_2` -\sa `TriangulationDataStructure_2::Face` -\sa `TriangulationFaceBase_2` \sa `CGAL::Triangulation_data_structure_2` */ -class TriangulationDSFaceBase_2 { +class TriangulationDSFaceBase_2 + : public TriangulationDataStructure_2::Face +{ public: /// \name Types From fb539f605c7b268f383c4b165bedc5b0ed5f07dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 30 Dec 2019 18:22:42 +0100 Subject: [PATCH 099/185] TriangulationDSVertexBase_2 should refine TDS2::Vertex --- .../TDS_2/Concepts/TriangulationDSVertexBase_2.h | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/TDS_2/doc/TDS_2/Concepts/TriangulationDSVertexBase_2.h b/TDS_2/doc/TDS_2/Concepts/TriangulationDSVertexBase_2.h index c616d582f7f..534accb027c 100644 --- a/TDS_2/doc/TDS_2/Concepts/TriangulationDSVertexBase_2.h +++ b/TDS_2/doc/TDS_2/Concepts/TriangulationDSVertexBase_2.h @@ -3,6 +3,8 @@ \ingroup PkgTDS2Concepts \cgalConcept +\cgalRefines `TriangulationDataStructure_2::Vertex` + The concept `TriangulationDSVertexBase_2` describes the requirements for the vertex base class of a `CGAL::Triangulation_data_structure_2`. @@ -42,23 +44,16 @@ that the `CGAL::Triangulation_data_structure_2` actually uses as a base class for the class of `CGAL::Triangulation_data_structure_2::Vertex`. -\cgalRefines `TriangulationDataStructure_2::Vertex` - \cgalHasModel `CGAL::Triangulation_ds_vertex_base_2` -\cgalHasModel `CGAL::Triangulation_vertex_base_2` -\cgalHasModel `CGAL::Regular_triangulation_vertex_base_2` -\cgalHasModel `CGAL::Triangulation_hierarchy_vertex_base_2` -\cgalHasModel `CGAL::Triangulation_vertex_base_with_info_2` -\sa `TriangulationVertexBase_2` \sa `TriangulationDSFaceBase_2` -\sa `TriangulationFaceBase_2` -\sa `TriangulationDataStructure_2::Vertex` \sa `CGAL::Triangulation_data_structure_2` */ -class TriangulationDSVertexBase_2 { +class TriangulationDSVertexBase_2 + : public TriangulationDataStructure_2::Vertex +{ public: /// \name Types From 4b693695cd284fb9ac6478e8c934ce424a205d43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 30 Dec 2019 18:23:37 +0100 Subject: [PATCH 100/185] Don't duplicate requirements between TriangulationDSFace and TDS2::Face --- .../Concepts/TriangulationDSFaceBase_2.h | 103 ++---------------- 1 file changed, 10 insertions(+), 93 deletions(-) diff --git a/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h b/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h index 5391b2b51da..2a99e243ab9 100644 --- a/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h +++ b/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h @@ -100,26 +100,26 @@ typedef TriangulationDataStructure_2::Face_handle Face_handle; /*! default constructor. */ -TriangulationDSFaceBase_2(); +TriangulationDSFaceBase_2(); /*! Initializes the vertices with `v0, v1, v2` and the neighbors with `Face_handle()`. */ -TriangulationDSFaceBase_2(Vertex_handle v0, -Vertex_handle v1, -Vertex_handle v2); +TriangulationDSFaceBase_2(Vertex_handle v0, + Vertex_handle v1, + Vertex_handle v2); /*! initializes the vertices with `v0,v1, v2` and the neighbors with `n0, n1, n2`. */ -TriangulationDSFaceBase_2(Vertex_handle v0, -Vertex_handle v1, -Vertex_handle v2, -Face_handle n0, -Face_handle n1, -Face_handle n2); +TriangulationDSFaceBase_2(Vertex_handle v0, + Vertex_handle v1, + Vertex_handle v2, + Face_handle n0, + Face_handle n1, + Face_handle n2); /// @} @@ -131,89 +131,6 @@ returns the dimension. */ int dimension(); -/*! -returns the vertex `i` of the face. -\pre \f$ 0\leq i \leq2\f$. -*/ -Vertex_handle vertex(int i) const; - -/*! -returns `true` if `v` is a vertex of the face. -*/ -bool has_vertex(Vertex_handle v); - -/*! -as above, and sets `i` to the index of `v` in the face. -*/ -bool has_vertex(Vertex_handle v, int& i) const; - -/*! -returns the index of `v` in the face. -*/ -int index(Vertex_handle v) const; - -/*! -returns the neighbor `i` of the face. -\pre \f$ 0\leq i \leq2\f$. -*/ -Face_handle neighbor(int i) const; - -/*! -returns `true` if `n` is a neighbor of the face. -*/ -bool has_neighbor(Face_handle n); - -/*! -as above, and sets i to the index of `n` in the face. -*/ -bool has_neigbor(Face_handle n, int& i) const; - -/*! -returns the index of neighbor `n` in the face. -*/ -int index(const Face_handle n) const; - -/// @} - -/// \name Setting -/// @{ - -/*! -sets vertex `i` to `v`. -\pre \f$ 0\leq i \leq2\f$. -*/ -void set_vertex(int i, Vertex_handle v); - -/*! -sets the vertices to `Vertex_handle()`. -*/ -void set_vertices(); - -/*! -sets the vertices. -*/ -void set_vertices(Vertex_handle v0, -Vertex_handle v1, -Vertex_handle v2); - -/*! -sets neighbor `i` to `n`. -\pre \f$ 0\leq i \leq2\f$. -*/ -void set_neighbor(int i, Face_handle n); - -/*! -sets the neighbors to `Face_handle()`. -*/ -void set_neighbors(); - -/*! -sets the neighbors. -*/ -void set_neighbors(Face_handle n0, -Face_handle n1, -Face_handle n2); - /// @} /// \name Orientation From ba7c36850a2f7b400c0ef4c7eb4780fd87dec8ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 30 Dec 2019 18:24:11 +0100 Subject: [PATCH 101/185] Remove Rebind_vertex/Face from TDS2 concept The rebind mechanism is for the model CGAL::TDS_2, not the concept TDS2 where this doesn't make sense. --- .../Concepts/TriangulationDataStructure_2.h | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/TDS_2/doc/TDS_2/Concepts/TriangulationDataStructure_2.h b/TDS_2/doc/TDS_2/Concepts/TriangulationDataStructure_2.h index 4b025c1b7e4..ec5640d7d2a 100644 --- a/TDS_2/doc/TDS_2/Concepts/TriangulationDataStructure_2.h +++ b/TDS_2/doc/TDS_2/Concepts/TriangulationDataStructure_2.h @@ -110,26 +110,6 @@ Handle to a face. */ typedef unspecified_type Face_handle; -/*! -This template class allows to get the type of a triangulation -data structure that only changes the vertex type. It has to define a type -`Rebind_vertex::%Other` which is a rebound triangulation data structure, that is, the -one whose `TriangulationDSVertexBase_2` will be `Vb2`. -\note It can be implemented using a nested template class. -*/ -template -using Rebind_vertex = unspecified_type; - -/*! -This template class allows to get the type of a triangulation -data structure that only changes the face type. It has to define a type -`Rebind_face::%Other` which is a rebound triangulation data structure, that is, the -one whose `TriangulationDSFaceBase_2` will be `Fb2`. -\note It can be implemented using a nested template class. -*/ -template -using Rebind_face = unspecified_type; - /*! The edge type. The `Edge(f,i)` is edge common to faces `f` and From 0b0e7a7890505a459ebb745df353ee1fb38908da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 30 Dec 2019 18:25:33 +0100 Subject: [PATCH 102/185] Document the Vertex/Cell types in the doc of CGAL::TDS_3 (the model) --- .../CGAL/Triangulation_data_structure_3.h | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/TDS_3/doc/TDS_3/CGAL/Triangulation_data_structure_3.h b/TDS_3/doc/TDS_3/CGAL/Triangulation_data_structure_3.h index 49bcbed73b4..68b5d9f74a0 100644 --- a/TDS_3/doc/TDS_3/CGAL/Triangulation_data_structure_3.h +++ b/TDS_3/doc/TDS_3/CGAL/Triangulation_data_structure_3.h @@ -33,23 +33,32 @@ container to store vertices and cells. It can be `Sequential_tag` (use of a The base class `Triangulation_utils_3` defines basic computations on indices of vertices and neighbors of cells. -\attention All members listed here are additional to the interface -specified by the concept. - \sa `CGAL::Triangulation_ds_vertex_base_3` \sa `CGAL::Triangulation_ds_cell_base_3` -\sa `CGAL::Triangulation_vertex_base_with_info_3` -\sa `CGAL::Triangulation_cell_base_with_info_3` */ template< typename VertexBase, typename CellBase, typename ConcurrencyTag > -class Triangulation_data_structure_3 : public CGAL::Triangulation_utils_3 { +class Triangulation_data_structure_3 + : public CGAL::Triangulation_utils_3 +{ public: /// \name Types /// @{ +typedef Triangulation_data_structure_2 Tds; + +/// The vertex type. +/// +/// \sa Section \ref tds3cyclic +typedef typename VertexBase::template Rebind_TDS::Other Vertex; + +/// The face type. +/// +/// \sa Section \ref tds3cyclic +typedef typename CellBase::template Rebind_TDS::Other Cell; + /*! Vertex container type. If `ConcurrencyTag` is `Parallel_tag`, a `Concurrent_compact_container` is used instead of a `Compact_container`. @@ -64,6 +73,10 @@ typedef Compact_container Cell_range; /// @} /// \name Operations +/// +/// In addition to the interface documented in the concept, +/// the class offers the following functions. +/// /// @{ /*! From cb7c2897668fa364f5c6dce8f28655fd8427ddae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 30 Dec 2019 18:26:35 +0100 Subject: [PATCH 103/185] TriangulationDSCellBase_3 should refine TDS3::Cell --- .../Concepts/TriangulationDSCellBase_3.h | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h b/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h index 01c6ac9cc95..6b5248f43de 100644 --- a/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h +++ b/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h @@ -3,6 +3,16 @@ \ingroup PkgTDS3Concepts \cgalConcept +\cgalRefines TriangulationDataStructure_3::Cell + +The concept `TriangulationDSCellBase_3` describes the requirements for +the cell base class of a `CGAL::Triangulation_data_structure_3`. + +Note that if the `CGAL::Triangulation_data_structure_3` +is plugged into a triangulation class, +the face base class may have additional geometric +requirements depending on the triangulation class. + At the base level (see the Software Design sections of the Chapters \ref Triangulation3secdesign "Triangulation" and \ref TDS3secdesign "Triangulation Datastructure"), @@ -23,18 +33,16 @@ cell classes. The rebound base classes so obtained are the classes which are used as base classes for the final vertex and cell classes. More information can be found in Section \ref TDS3secdesign. -\cgalHasModel CGAL::Triangulation_ds_cell_base_3 -\cgalHasModel CGAL::Triangulation_cell_base_3 -\cgalHasModel CGAL::Triangulation_cell_base_with_info_3 +\cgalHasModel `CGAL::Triangulation_ds_cell_base_3` \sa `TriangulationDSVertexBase_3` -\sa `TriangulationVertexBase_3` -\sa `TriangulationHierarchyVertexBase_3` -\sa `TriangulationCellBase_3` +\sa `CGAL::Triangulation_data_structure_3` */ -class TriangulationDSCellBase_3 { +class TriangulationDSCellBase_3 + : public TriangulationDataStructure_3::Cell +{ public: /// \name Types From 6232c04f71562648e973bc1b76691c5f95c01282 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 30 Dec 2019 18:27:22 +0100 Subject: [PATCH 104/185] TriangulationDSVertexBase_3 should refine TDS3::Vertex --- .../Concepts/TriangulationDSVertexBase_3.h | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h b/TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h index 47d209d9c9f..c591fcd0bec 100644 --- a/TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h +++ b/TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h @@ -3,14 +3,18 @@ \ingroup PkgTDS3Concepts \cgalConcept +\cgalRefines TriangulationDataStructure_3::Vertex + +The concept TriangulationDSVertexBase_3 describes the requirements for the vertex base class +of a CGAL::Triangulation_data_structure_3. + +Note that if the `CGAL::Triangulation_data_structure_3` is plugged into a triangulation class, +the vertex base class may have additional geometric requirements depending on the triangulation class. + At the bottom level of 3D-triangulations (see Sections \ref Triangulation3secdesign and \ref TDS3secdesign), a vertex provides access to one of its incident cells through a handle. -Note that when you use the triangulation data structure as parameter of a -geometric triangulation, the vertex base class has additional geometric -requirements : it has to match the `TriangulationVertexBase_3` concept. - Since the Triangulation data structure is the class which defines the handle types, the vertex base class has to be somehow parameterized by the Triangulation data structure. But since it is itself parameterized by the cell @@ -24,18 +28,16 @@ cell classes. The rebound base classes so obtained are the classes which are used as base classes for the final vertex and cell classes. More information can be found in Section \ref TDS3secdesign. -\cgalHasModel CGAL::Triangulation_ds_vertex_base_3 -\cgalHasModel CGAL::Triangulation_vertex_base_3 -\cgalHasModel CGAL::Triangulation_vertex_base_with_info_3 +\cgalHasModel `CGAL::Triangulation_ds_vertex_base_3` -\sa `TriangulationVertexBase_3` -\sa `TriangulationHierarchyVertexBase_3` -\sa `TriangulationDSCellBase_3` -\sa `TriangulationCellBase_3` +\sa `TriangulationDSCellBase_3` +\sa `CGAL::Triangulation_data_structure_3` */ -class TriangulationDSVertexBase_3 { +class TriangulationDSVertexBase_3 + : public TriangulationDataStructure_3::Vertex +{ public: /// \name Types From 185e50c250691a7dbc413fb0ba01e457dce4d588 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 30 Dec 2019 18:27:55 +0100 Subject: [PATCH 105/185] Fix typo ('TDS2' in the documentation of TDS3) --- TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h | 9 +++++---- TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h | 7 ++++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h b/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h index 6b5248f43de..bee4962703f 100644 --- a/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h +++ b/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h @@ -50,13 +50,14 @@ public: /// @{ /*! -This template class has to define a type `Rebind_TDS::%Other` which is the +This template class has to define a type `Rebind_TDS::%Other` which is the rebound cell, that is, the one whose `Triangulation_data_structure` -will be the actually used one. `Rebind_TDS::%Other` will be the real base +will be the actually used one. `Rebind_TDS::%Other` will be the real base class of `Triangulation_data_structure_3::Cell`. \note It can be implemented using a nested template class. -*/ -template +\sa Section \ref tds3cyclic +*/ +template using Rebind_TDS = unspecified_type; /*! diff --git a/TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h b/TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h index c591fcd0bec..01579d27f50 100644 --- a/TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h +++ b/TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h @@ -44,13 +44,14 @@ public: /// @{ /*! -This template class has to define a type `Rebind_TDS::%Other` which is the +This template class has to define a type `Rebind_TDS::%Other` which is the rebound vertex, that is, the one whose `Triangulation_data_structure` -will be the actually used one. `Rebind_TDS::%Other` will be the real base +will be the actually used one. `Rebind_TDS::%Other` will be the real base class of `Triangulation_data_structure_3::Vertex`. \note It can be implemented using a nested template class. +\sa Section \ref tds3cyclic */ -template +template using Rebind_TDS = unspecified_type; /*! From efcb6c53784be4edbea59ff6522c8d41ebdd70a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 30 Dec 2019 18:29:03 +0100 Subject: [PATCH 106/185] Fix documentation of tds_data tds_data is required from TDS3::Cell, not by a model of the cell base of CGAL::T_D_S_3 (the model of TDS3). It also must properly document its API. --- .../Concepts/TriangulationDSCellBase_3.h | 25 ----- .../Concepts/TriangulationDataStructure_3.h | 95 +++++++++++++++++++ TDS_3/doc/TDS_3/PackageDescription.txt | 1 + 3 files changed, 96 insertions(+), 25 deletions(-) diff --git a/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h b/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h index bee4962703f..3e0a7f86102 100644 --- a/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h +++ b/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h @@ -75,11 +75,6 @@ typedef TriangulationDataStructure_3::Vertex_handle Vertex_handle; */ typedef TriangulationDataStructure_3::Cell_handle Cell_handle; -/*! - -*/ -typedef TriangulationDataStructure_3::Cell_data TDS_data; - /// @} /// \name Creation @@ -236,26 +231,6 @@ void * & for_compact_container(); /// @} -/// \name Internal -/// \cgalAdvancedBegin -/// These functions are used internally by the triangulation data -/// structure. The user is not encouraged to use them directly as they -/// may change in the future. -/// \cgalAdvancedEnd -/// @{ - -/*! - -*/ -TDS_data& tds_data(); - -/*! - -*/ -const TDS_data& tds_data() const; - -/// @} - /// \name I/O /// @{ diff --git a/TDS_3/doc/TDS_3/Concepts/TriangulationDataStructure_3.h b/TDS_3/doc/TDS_3/Concepts/TriangulationDataStructure_3.h index 175a64c4e20..76f560dad46 100644 --- a/TDS_3/doc/TDS_3/Concepts/TriangulationDataStructure_3.h +++ b/TDS_3/doc/TDS_3/Concepts/TriangulationDataStructure_3.h @@ -90,6 +90,11 @@ typedef unspecified_type Vertex; */ typedef unspecified_type Cell; +/*! + %Cell data type, requirements are described in `TriangulationDataStructure_3::Cell_data`. +*/ +typedef unspecified_type Cell_data; + /*! Size type (unsigned integral type) */ @@ -1161,6 +1166,7 @@ In order to obtain new cells or destruct unused cells, the user must call the structure. \sa `TriangulationDataStructure_3::Vertex` +\sa `TriangulationDataStructure_3::Cell_data` */ @@ -1185,6 +1191,11 @@ typedef TriangulationDataStructure_3::Vertex_handle Vertex_handle; */ typedef TriangulationDataStructure_3::Cell_handle Cell_handle; +/*! + +*/ +typedef TriangulationDataStructure_3::Cell_data TDS_data; + /// @} /// \name Access Functions @@ -1272,6 +1283,26 @@ Cell_handle n3); /// @} +/// \name Internal +/// \cgalAdvancedBegin +/// These functions are used internally by the triangulation data +/// structure. The user is not encouraged to use them directly as they +/// may change in the future. +/// \cgalAdvancedEnd +/// @{ + +/*! + +*/ +TDS_data& tds_data(); + +/*! + +*/ +const TDS_data& tds_data() const; + +/// @} + /// \name Checking /// @{ @@ -1286,3 +1317,67 @@ bool is_valid(bool verbose = false, int level = 0) const; /// @} }; /* end Cell */ + + +/*! +\ingroup PkgTDS3Concepts +\cgalConcept + +Various algorithms using a triangulation data structure, such as Delaunay triangulations +or Alpha Shapes, must be able to associate a state to a cell elemental. +For efficiency, this information must be stored directly within the cell. + +This class is only meant to store a state (Boolean). Consequently, the state must be the default +value (i.e. `false`) unless a setting function (`mark_in_conflict()`, etc.) has been called. + +The three states are "in conflict", "on boundary", and "processed". +By default, a cell is not in conflict, not on boundary, and not processed. + +\sa `TriangulationDataStructure_3::Cell` + +*/ + +class TriangulationDataStructure_3::Cell_data +{ +public: + /// \name Setting + /// @{ + + /// Clears all flags: the cell is neither in conflict, nor on the boundary, nor processed. + void clear(); + + /// Sets the "in conflict" state to `true`. + /// + /// \post `is_in_conflict()` returns `true` + void mark_in_conflict(); + + /// Sets the "on boundary" state to `true`. + /// + /// \post `is_on_boundary()` returns `true` + void mark_on_boundary(); + + /// Sets the "processed" state to `true`. + /// + /// \post `processed()` returns `true` + void mark_processed(); + + /// @} + + /// \name Access Functions + /// @{ + + /// Checks whether the cell has default state (not in conflict, not on boundary, not processed). + bool is_clear(); + + /// Returns whether the cell has been marked as "in conflict". + bool is_in_conflict(); + + /// Returns whether the cell has been marked as "on boundary". + bool is_on_boundary(); + + /// Returns whether the cell has been marked as "processed". + bool processed(); + + /// @} + +}; /* end Cell_data */ diff --git a/TDS_3/doc/TDS_3/PackageDescription.txt b/TDS_3/doc/TDS_3/PackageDescription.txt index 9bde710fa0d..ec963cff969 100644 --- a/TDS_3/doc/TDS_3/PackageDescription.txt +++ b/TDS_3/doc/TDS_3/PackageDescription.txt @@ -50,6 +50,7 @@ Section \ref TDS3secintro.) - `TriangulationDataStructure_3` - `TriangulationDataStructure_3::Cell` +- `TriangulationDataStructure_3::Cell_data` - `TriangulationDataStructure_3::Vertex` - `TriangulationDSCellBase_3` - `TriangulationDSVertexBase_3` From 801187c642891f5400dfaa72c7fcf00bc070e7e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 30 Dec 2019 18:30:28 +0100 Subject: [PATCH 107/185] Clean some tests --- .../include/CGAL/_test_cls_periodic_3_tds_cell.h | 10 ---------- TDS_3/test/TDS_3/include/CGAL/_test_cls_tds_cell.h | 10 ---------- 2 files changed, 20 deletions(-) diff --git a/Periodic_3_triangulation_3/test/Periodic_3_triangulation_3/include/CGAL/_test_cls_periodic_3_tds_cell.h b/Periodic_3_triangulation_3/test/Periodic_3_triangulation_3/include/CGAL/_test_cls_periodic_3_tds_cell.h index f6bd867855d..fb949a078fc 100644 --- a/Periodic_3_triangulation_3/test/Periodic_3_triangulation_3/include/CGAL/_test_cls_periodic_3_tds_cell.h +++ b/Periodic_3_triangulation_3/test/Periodic_3_triangulation_3/include/CGAL/_test_cls_periodic_3_tds_cell.h @@ -88,11 +88,6 @@ _test_cell_tds_3(const Tds &) assert(c2->index(v1)==0); assert(c2->index(v2)==1); assert(c2->index(v3)==2); - // c2->set_vertices(); - // assert(c2->vertex(0)==NULL); - // assert(c2->vertex(1)==NULL); - // assert(c2->vertex(2)==NULL); - // assert(c2->vertex(3)==NULL); c2->set_vertices(v0, v1, v2, v3); assert(c2->index(v0)==0); assert(c2->index(v1)==1); @@ -107,11 +102,6 @@ _test_cell_tds_3(const Tds &) assert(c2->index(n1)==0); assert(c2->index(n2)==1); assert(c2->index(n3)==2); - // c2->set_neighbors(); - // assert(c2->neighbor(0)==NULL); - // assert(c2->neighbor(1)==NULL); - // assert(c2->neighbor(2)==NULL); - // assert(c2->neighbor(3)==NULL); c2->set_neighbors(n0, n1, n2, n3); assert(c2->index(n0)==0); assert(c2->index(n1)==1); diff --git a/TDS_3/test/TDS_3/include/CGAL/_test_cls_tds_cell.h b/TDS_3/test/TDS_3/include/CGAL/_test_cls_tds_cell.h index f6bd867855d..fb949a078fc 100644 --- a/TDS_3/test/TDS_3/include/CGAL/_test_cls_tds_cell.h +++ b/TDS_3/test/TDS_3/include/CGAL/_test_cls_tds_cell.h @@ -88,11 +88,6 @@ _test_cell_tds_3(const Tds &) assert(c2->index(v1)==0); assert(c2->index(v2)==1); assert(c2->index(v3)==2); - // c2->set_vertices(); - // assert(c2->vertex(0)==NULL); - // assert(c2->vertex(1)==NULL); - // assert(c2->vertex(2)==NULL); - // assert(c2->vertex(3)==NULL); c2->set_vertices(v0, v1, v2, v3); assert(c2->index(v0)==0); assert(c2->index(v1)==1); @@ -107,11 +102,6 @@ _test_cell_tds_3(const Tds &) assert(c2->index(n1)==0); assert(c2->index(n2)==1); assert(c2->index(n3)==2); - // c2->set_neighbors(); - // assert(c2->neighbor(0)==NULL); - // assert(c2->neighbor(1)==NULL); - // assert(c2->neighbor(2)==NULL); - // assert(c2->neighbor(3)==NULL); c2->set_neighbors(n0, n1, n2, n3); assert(c2->index(n0)==0); assert(c2->index(n1)==1); From 6e69d886e3b4865963beb90904030b0a4a9028b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 30 Dec 2019 18:31:02 +0100 Subject: [PATCH 108/185] Don't duplicate code between TDSVertex/Cell and TDS3::Vertex/Cell --- .../Concepts/TriangulationDSCellBase_3.h | 104 ++---------------- .../Concepts/TriangulationDSVertexBase_3.h | 24 +--- 2 files changed, 9 insertions(+), 119 deletions(-) diff --git a/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h b/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h index 3e0a7f86102..8f32290698d 100644 --- a/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h +++ b/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h @@ -83,113 +83,23 @@ typedef TriangulationDataStructure_3::Cell_handle Cell_handle; /*! Default constructor */ -Cell_base(); +TriangulationDSCellBase_3(); /*! Initializes the vertices with `v0, v1, v2, v3`. Neighbors are initialized to the default constructed handle. */ -Cell_base( Vertex_handle v0, Vertex_handle v1, -Vertex_handle v2, Vertex_handle v3); +TriangulationDSCellBase_3( Vertex_handle v0, Vertex_handle v1, + Vertex_handle v2, Vertex_handle v3); /*! Initializes the vertices with `v0, v1, v2, v3` and the neighbors with `n0, n1, n2, n3`. */ -Cell_base( Vertex_handle v0, Vertex_handle v1, -Vertex_handle v2, Vertex_handle v3, -Cell_handle n0, Cell_handle n1, -Cell_handle n2, Cell_handle n3); - -/// @} - -/// \name Access Functions -/// @{ - -/*! -Returns the vertex `i` of `c`. -\pre \f$ i \in\{0, 1, 2, 3\}\f$. -*/ -Vertex_handle vertex(int i) const; - -/*! -Returns the index of `v`. -\pre `v` is a vertex of `c` -*/ -int index(Vertex_handle v) const; - -/*! -True iff `v` is a vertex of `c`. -*/ -bool has_vertex(Vertex_handle v); - -/*! -Returns `true` if `v` is a vertex of `c`, and -computes its index `i` in `c`. -*/ -bool has_vertex(Vertex_handle v, int & i) const; - -/*! -Returns the neighbor `i` of `c`. -\pre \f$ i \in\{0, 1, 2, 3\}\f$. -*/ -Cell_handle neighbor(int i) const; - -/*! -Returns the index of cell `n` in `c`. -\pre `n` is a neighbor of `c`. -*/ -int index(Cell_handle n) const; - -/*! -Returns `true` if `n` is a neighbor of `c`. -*/ -bool has_neighbor(Cell_handle n); - -/*! -Returns `true` if `n` is a neighbor of `c`, and -computes its index `i` in `c`. -*/ -bool has_neighbor(Cell_handle n, int & i) const; - -/// @} - -/// \name Setting -/// @{ - -/*! -Sets vertex `i` to `v`. -\pre \f$ i \in\{0, 1, 2, 3\}\f$. -*/ -void set_vertex(int i, Vertex_handle v); - -/*! -Sets the vertices to the default constructed handle. -*/ -void set_vertices(); - -/*! -Sets the vertices. -*/ -void set_vertices( Vertex_handle v0, Vertex_handle v1, -Vertex_handle v2, Vertex_handle v3); - -/*! -Sets neighbor `i` to `n`. -\pre \f$ i \in\{0, 1, 2, 3\}\f$. -*/ -void set_neighbor(int i, Cell_handle n); - -/*! -Sets the neighbors to the default constructed handle. -*/ -void set_neighbors(); - -/*! -Sets the neighbors. -*/ -void set_neighbors(Cell_handle n0, Cell_handle n1, -Cell_handle n2, Cell_handle n3); +TriangulationDSCellBase_3( Vertex_handle v0, Vertex_handle v1, + Vertex_handle v2, Vertex_handle v3, + Cell_handle n0, Cell_handle n1, + Cell_handle n2, Cell_handle n3); /// @} diff --git a/TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h b/TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h index 01579d27f50..73566772f4c 100644 --- a/TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h +++ b/TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h @@ -77,32 +77,12 @@ typedef TriangulationDataStructure_3::Cell_handle Cell_handle; /*! Default constructor. */ -TriangulationVertexBase_3(); +TriangulationDSVertexBase_3(); /*! Constructs a vertex pointing to cell `c`. */ -TriangulationVertexBase_3(Cell_handle c); - -/// @} - -/// \name Access Functions -/// @{ - -/*! -Returns the pointer to an incident cell -*/ -Cell_handle cell() const; - -/// @} - -/// \name Setting -/// @{ - -/*! -Sets the incident cell. -*/ -void set_cell(Cell_handle c); +TriangulationDSVertexBase_3(Cell_handle c); /// @} From 19ceed98b8bf05e142b881c956ff8cfb5a601054 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 30 Dec 2019 18:32:04 +0100 Subject: [PATCH 109/185] Misc minor fixes --- TDS_2/doc/TDS_2/CGAL/Triangulation_ds_face_base_2.h | 2 +- TDS_2/doc/TDS_2/CGAL/Triangulation_ds_vertex_base_2.h | 6 ++++-- TDS_2/doc/TDS_2/Concepts/TriangulationDataStructure_2.h | 5 +++-- TDS_2/doc/TDS_2/PackageDescription.txt | 2 +- TDS_2/include/CGAL/Triangulation_ds_face_base_2.h | 6 +++--- TDS_3/doc/TDS_3/CGAL/Triangulation_data_structure_3.h | 1 - TDS_3/doc/TDS_3/CGAL/Triangulation_ds_cell_base_3.h | 3 +-- TDS_3/doc/TDS_3/CGAL/Triangulation_ds_vertex_base_3.h | 1 - TDS_3/doc/TDS_3/Concepts/TriangulationDataStructure_3.h | 6 ++---- TDS_3/doc/TDS_3/PackageDescription.txt | 2 +- 10 files changed, 16 insertions(+), 18 deletions(-) diff --git a/TDS_2/doc/TDS_2/CGAL/Triangulation_ds_face_base_2.h b/TDS_2/doc/TDS_2/CGAL/Triangulation_ds_face_base_2.h index e4154ace5f7..f60d429e163 100644 --- a/TDS_2/doc/TDS_2/CGAL/Triangulation_ds_face_base_2.h +++ b/TDS_2/doc/TDS_2/CGAL/Triangulation_ds_face_base_2.h @@ -14,7 +14,7 @@ The class `Triangulation_ds_face_base_2` is a model for the concept \sa `CGAL::Triangulation_ds_vertex_base_2` */ -template< typename Tds > +template< typename TDS > class Triangulation_ds_face_base_2 { public: diff --git a/TDS_2/doc/TDS_2/CGAL/Triangulation_ds_vertex_base_2.h b/TDS_2/doc/TDS_2/CGAL/Triangulation_ds_vertex_base_2.h index f93dd03270a..22c77de5ad2 100644 --- a/TDS_2/doc/TDS_2/CGAL/Triangulation_ds_vertex_base_2.h +++ b/TDS_2/doc/TDS_2/CGAL/Triangulation_ds_vertex_base_2.h @@ -18,13 +18,15 @@ geometric triangulation, there are additional geometric requirements to be fulfilled by the vertex base class, and `Triangulation_ds_vertex_base_2` cannot be plugged in. +\tparam TDS A + \cgalModels `TriangulationDSVertexBase_2` \sa `CGAL::Triangulation_vertex_base_2` -\sa `CGAL::Triangulation_ds_face_base_2` +\sa `CGAL::Triangulation_ds_face_base_2` */ -template< typename Tds > +template< typename TDS > class Triangulation_ds_vertex_base_2 { public: diff --git a/TDS_2/doc/TDS_2/Concepts/TriangulationDataStructure_2.h b/TDS_2/doc/TDS_2/Concepts/TriangulationDataStructure_2.h index ec5640d7d2a..bcd40c0b975 100644 --- a/TDS_2/doc/TDS_2/Concepts/TriangulationDataStructure_2.h +++ b/TDS_2/doc/TDS_2/Concepts/TriangulationDataStructure_2.h @@ -723,8 +723,9 @@ triangulation data structure. \cgalHasModel `CGAL::Triangulation_ds_vertex_base_2` -\sa `TriangulationDataStructure_2` +\sa `TriangulationDSVertexBase_2` \sa `TriangulationDataStructure_2::Face` +\sa `TriangulationDataStructure_2` */ class TriangulationDataStructure_2::Vertex { @@ -843,9 +844,9 @@ define new faces and to delete no longer used faces. \cgalHasModel `CGAL::Triangulation_ds_face_base_2` +\sa `TriangulationDSFaceBase_2` \sa `TriangulationDataStructure_2` \sa `TriangulationDataStructure_2::Vertex` -\sa `TriangulationFaceBase_2` */ class TriangulationDataStructure_2::Face { diff --git a/TDS_2/doc/TDS_2/PackageDescription.txt b/TDS_2/doc/TDS_2/PackageDescription.txt index 54faad3f455..95e6f385c9f 100644 --- a/TDS_2/doc/TDS_2/PackageDescription.txt +++ b/TDS_2/doc/TDS_2/PackageDescription.txt @@ -58,7 +58,7 @@ These refining concepts and their models are described in Chapter - `TriangulationDSVertexBase_2` \cgalCRPSection{Classes} -- `CGAL::Triangulation_data_structure_2` +- `CGAL::Triangulation_data_structure_2` - `CGAL::Triangulation_ds_face_base_2` - `CGAL::Triangulation_ds_vertex_base_2` diff --git a/TDS_2/include/CGAL/Triangulation_ds_face_base_2.h b/TDS_2/include/CGAL/Triangulation_ds_face_base_2.h index 971f2b2d807..8de378eec8f 100644 --- a/TDS_2/include/CGAL/Triangulation_ds_face_base_2.h +++ b/TDS_2/include/CGAL/Triangulation_ds_face_base_2.h @@ -239,14 +239,14 @@ set_neighbor(int i, Face_handle n) N[i] = n; } -template +template inline void -Triangulation_ds_face_base_2 :: +Triangulation_ds_face_base_2 :: set_vertices() { V[0] = V[1] = V[2] = Vertex_handle(); } - + template inline void Triangulation_ds_face_base_2 :: diff --git a/TDS_3/doc/TDS_3/CGAL/Triangulation_data_structure_3.h b/TDS_3/doc/TDS_3/CGAL/Triangulation_data_structure_3.h index 68b5d9f74a0..87629817773 100644 --- a/TDS_3/doc/TDS_3/CGAL/Triangulation_data_structure_3.h +++ b/TDS_3/doc/TDS_3/CGAL/Triangulation_data_structure_3.h @@ -19,7 +19,6 @@ additional template parameters. \tparam CellBase must be a model of `TriangulationDSCellBase_3`. The default is `Triangulation_ds_cell_base_3`. - \tparam ConcurrencyTag enables the use of a concurrent container to store vertices and cells. It can be `Sequential_tag` (use of a `Compact_container` to store vertices and cells) or `Parallel_tag` diff --git a/TDS_3/doc/TDS_3/CGAL/Triangulation_ds_cell_base_3.h b/TDS_3/doc/TDS_3/CGAL/Triangulation_ds_cell_base_3.h index 51c3048d577..858b5a2121b 100644 --- a/TDS_3/doc/TDS_3/CGAL/Triangulation_ds_cell_base_3.h +++ b/TDS_3/doc/TDS_3/CGAL/Triangulation_ds_cell_base_3.h @@ -12,10 +12,9 @@ The class `Triangulation_ds_cell_base_3<>` is a model for the concept \sa `CGAL::Triangulation_cell_base_3` \sa `CGAL::Triangulation_ds_vertex_base_3` -\sa `CGAL::Triangulation_cell_base_with_info_3` */ -template< typename TDS = void > +template< typename TDS > class Triangulation_ds_cell_base_3 { public: diff --git a/TDS_3/doc/TDS_3/CGAL/Triangulation_ds_vertex_base_3.h b/TDS_3/doc/TDS_3/CGAL/Triangulation_ds_vertex_base_3.h index 10a7a078f09..76c61a46284 100644 --- a/TDS_3/doc/TDS_3/CGAL/Triangulation_ds_vertex_base_3.h +++ b/TDS_3/doc/TDS_3/CGAL/Triangulation_ds_vertex_base_3.h @@ -22,7 +22,6 @@ example) tuned for a specific application. \sa `CGAL::Triangulation_vertex_base_3` \sa `CGAL::Triangulation_ds_cell_base_3` -\sa `CGAL::Triangulation_vertex_base_with_info_3` */ template< typename TDS = void > diff --git a/TDS_3/doc/TDS_3/Concepts/TriangulationDataStructure_3.h b/TDS_3/doc/TDS_3/Concepts/TriangulationDataStructure_3.h index 76f560dad46..2df0ae7574a 100644 --- a/TDS_3/doc/TDS_3/Concepts/TriangulationDataStructure_3.h +++ b/TDS_3/doc/TDS_3/Concepts/TriangulationDataStructure_3.h @@ -38,9 +38,7 @@ the dimension of the triangulation is lower than 3 (see Section \ref TDS3secintro). Thus, a 3D-triangulation data structure can store a triangulation of a -topological sphere \f$ S^d\f$ of \f$ \mathbb{R}^{d+1}\f$, for any \f$ d \in \{-1,0,1,2,3\}\f$.
    - - +topological sphere \f$ S^d\f$ of \f$ \mathbb{R}^{d+1}\f$, for any \f$ d \in \{-1,0,1,2,3\}\f$.
    The second template parameter of the basic triangulation class (see Chapter \ref chapterTriangulation3 "3D Triangulations") @@ -67,7 +65,7 @@ neighbors of each cell, where the index corresponds to the preceding list of cells. When dimension < 3, the same information is stored for faces of maximal dimension instead of cells. -\cgalHasModel `CGAL::Triangulation_data_structure_3` +\cgalHasModel `CGAL::Triangulation_data_structure_3` \sa `TriangulationDataStructure_3::Vertex` \sa `TriangulationDataStructure_3::Cell` diff --git a/TDS_3/doc/TDS_3/PackageDescription.txt b/TDS_3/doc/TDS_3/PackageDescription.txt index ec963cff969..233f7bd329a 100644 --- a/TDS_3/doc/TDS_3/PackageDescription.txt +++ b/TDS_3/doc/TDS_3/PackageDescription.txt @@ -57,7 +57,7 @@ Section \ref TDS3secintro.) \cgalCRPSection{Classes} -- `CGAL::Triangulation_data_structure_3` is a model for the concept of the 3D-triangulation data structure `TriangulationDataStructure_3`. It is templated by base classes for vertices and cells. +- `CGAL::Triangulation_data_structure_3` is a model for the concept of the 3D-triangulation data structure `TriangulationDataStructure_3`. It is templated by base classes for vertices and cells. \cgal provides base vertex classes and base cell classes: From 9d58d7ff670765c10b076dcba7f33ef5d43f2fc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 30 Dec 2019 18:57:16 +0100 Subject: [PATCH 110/185] Document the parameter template of CGAL::T_DS_vertex/face/cell_23 --- TDS_2/doc/TDS_2/CGAL/Triangulation_ds_face_base_2.h | 4 +++- TDS_2/doc/TDS_2/CGAL/Triangulation_ds_vertex_base_2.h | 4 ++-- TDS_3/doc/TDS_3/CGAL/Triangulation_ds_cell_base_3.h | 4 +++- TDS_3/doc/TDS_3/CGAL/Triangulation_ds_vertex_base_3.h | 2 ++ 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/TDS_2/doc/TDS_2/CGAL/Triangulation_ds_face_base_2.h b/TDS_2/doc/TDS_2/CGAL/Triangulation_ds_face_base_2.h index f60d429e163..a506fae08b6 100644 --- a/TDS_2/doc/TDS_2/CGAL/Triangulation_ds_face_base_2.h +++ b/TDS_2/doc/TDS_2/CGAL/Triangulation_ds_face_base_2.h @@ -10,11 +10,13 @@ The class `Triangulation_ds_face_base_2` is a model for the concept \cgalModels `TriangulationDSFaceBase_2` +\tparam TDS should not be specified (see Section \ref TDS_2TheRebindMechanism and examples) + \sa `CGAL::Triangulation_face_base_2` \sa `CGAL::Triangulation_ds_vertex_base_2` */ -template< typename TDS > +template< typename TDS = void> class Triangulation_ds_face_base_2 { public: diff --git a/TDS_2/doc/TDS_2/CGAL/Triangulation_ds_vertex_base_2.h b/TDS_2/doc/TDS_2/CGAL/Triangulation_ds_vertex_base_2.h index 22c77de5ad2..f2d8600e82f 100644 --- a/TDS_2/doc/TDS_2/CGAL/Triangulation_ds_vertex_base_2.h +++ b/TDS_2/doc/TDS_2/CGAL/Triangulation_ds_vertex_base_2.h @@ -18,7 +18,7 @@ geometric triangulation, there are additional geometric requirements to be fulfilled by the vertex base class, and `Triangulation_ds_vertex_base_2` cannot be plugged in. -\tparam TDS A +\tparam TDS should not be specified (see Section \ref TDS_2TheRebindMechanism and examples) \cgalModels `TriangulationDSVertexBase_2` @@ -26,7 +26,7 @@ and `Triangulation_ds_vertex_base_2` cannot be plugged in. \sa `CGAL::Triangulation_ds_face_base_2` */ -template< typename TDS > +template< typename TDS = void > class Triangulation_ds_vertex_base_2 { public: diff --git a/TDS_3/doc/TDS_3/CGAL/Triangulation_ds_cell_base_3.h b/TDS_3/doc/TDS_3/CGAL/Triangulation_ds_cell_base_3.h index 858b5a2121b..90f86670ea8 100644 --- a/TDS_3/doc/TDS_3/CGAL/Triangulation_ds_cell_base_3.h +++ b/TDS_3/doc/TDS_3/CGAL/Triangulation_ds_cell_base_3.h @@ -10,11 +10,13 @@ The class `Triangulation_ds_cell_base_3<>` is a model for the concept \cgalModels `TriangulationDSCellBase_3` +\tparam TDS should not be specified (see Section \ref tds3cyclic and examples) + \sa `CGAL::Triangulation_cell_base_3` \sa `CGAL::Triangulation_ds_vertex_base_3` */ -template< typename TDS > +template< typename TDS = void > class Triangulation_ds_cell_base_3 { public: diff --git a/TDS_3/doc/TDS_3/CGAL/Triangulation_ds_vertex_base_3.h b/TDS_3/doc/TDS_3/CGAL/Triangulation_ds_vertex_base_3.h index 76c61a46284..c54caf3952a 100644 --- a/TDS_3/doc/TDS_3/CGAL/Triangulation_ds_vertex_base_3.h +++ b/TDS_3/doc/TDS_3/CGAL/Triangulation_ds_vertex_base_3.h @@ -20,6 +20,8 @@ example) tuned for a specific application. \cgalModels `TriangulationDSVertexBase_3` +\tparam TDS should not be specified (see Section \ref tds3cyclic and examples) + \sa `CGAL::Triangulation_vertex_base_3` \sa `CGAL::Triangulation_ds_cell_base_3` From dfec9598dac97fc00cd170b33a78999a389f2fd1 Mon Sep 17 00:00:00 2001 From: Oleg Alexandrov Date: Tue, 31 Dec 2019 18:38:35 -0800 Subject: [PATCH 111/185] Add to the user manual example a parameter that is discussed in that section --- .../reconstruction_fct.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Advancing_front_surface_reconstruction/examples/Advancing_front_surface_reconstruction/reconstruction_fct.cpp b/Advancing_front_surface_reconstruction/examples/Advancing_front_surface_reconstruction/reconstruction_fct.cpp index f3b259d80e4..9b3d83f3eef 100644 --- a/Advancing_front_surface_reconstruction/examples/Advancing_front_surface_reconstruction/reconstruction_fct.cpp +++ b/Advancing_front_surface_reconstruction/examples/Advancing_front_surface_reconstruction/reconstruction_fct.cpp @@ -60,6 +60,8 @@ int main(int argc, char* argv[]) { std::ifstream in((argc>1)?argv[1]:"data/half.xyz"); double per = (argc>2)?boost::lexical_cast(argv[2]):0; + double radius_ratio_bound = (argc>3)?boost::lexical_cast(argv[3]):5.0; + std::vector points; std::vector facets; @@ -71,7 +73,8 @@ int main(int argc, char* argv[]) CGAL::advancing_front_surface_reconstruction(points.begin(), points.end(), std::back_inserter(facets), - perimeter); + perimeter, + radius_ratio_bound); std::cout << "OFF\n" << points.size() << " " << facets.size() << " 0\n"; std::copy(points.begin(), From 5c41b10d2b69e28a528a6b0360049e5658e97fa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 2 Jan 2020 10:26:44 +0100 Subject: [PATCH 112/185] Clean whitespace / tabs in Spatial_sorting/include (cosmetic only) --- .../doc/Spatial_sorting/CGAL/spatial_sort.h | 2 +- Spatial_sorting/include/CGAL/Hilbert_sort_2.h | 24 +- Spatial_sorting/include/CGAL/Hilbert_sort_3.h | 28 +- .../include/CGAL/Hilbert_sort_base.h | 36 +-- Spatial_sorting/include/CGAL/Hilbert_sort_d.h | 26 +- .../include/CGAL/Hilbert_sort_median_2.h | 185 ++++++------- .../include/CGAL/Hilbert_sort_median_3.h | 245 +++++++++--------- .../include/CGAL/Hilbert_sort_median_d.h | 229 ++++++++-------- .../include/CGAL/Hilbert_sort_middle_2.h | 212 +++++++-------- .../include/CGAL/Hilbert_sort_middle_base.h | 18 +- .../include/CGAL/Multiscale_sort.h | 36 +-- .../CGAL/Spatial_sort_traits_adapter_2.h | 45 ++-- .../CGAL/Spatial_sort_traits_adapter_3.h | 56 ++-- .../CGAL/Spatial_sort_traits_adapter_d.h | 62 ++--- Spatial_sorting/include/CGAL/hilbert_sort.h | 159 ++++++------ .../include/CGAL/hilbert_sort_on_sphere.h | 85 +++--- .../internal/Transform_coordinates_traits_3.h | 149 ++++++----- Spatial_sorting/include/CGAL/spatial_sort.h | 225 ++++++++-------- .../include/CGAL/spatial_sort_on_sphere.h | 149 ++++++----- 19 files changed, 989 insertions(+), 982 deletions(-) diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h index 4beac521426..a2d7aabe8bf 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h @@ -45,7 +45,7 @@ times the original size of the set, Hilbert sort is applied on the second subset. */ - template +template void spatial_sort( RandomAccessIterator begin, RandomAccessIterator end, diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_2.h b/Spatial_sorting/include/CGAL/Hilbert_sort_2.h index b784365a176..1a4b7b249cd 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_2.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_2.h @@ -19,26 +19,26 @@ namespace CGAL { template - class Hilbert_sort_2; +class Hilbert_sort_2; -template - class Hilbert_sort_2 +template +class Hilbert_sort_2 : public Hilbert_sort_median_2 { - public: - Hilbert_sort_2 (const K &k=K() , std::ptrdiff_t limit=1 ) - : Hilbert_sort_median_2 (k,limit) - {} +public: + Hilbert_sort_2 (const K &k=K(), std::ptrdiff_t limit=1 ) + : Hilbert_sort_median_2 (k,limit) + {} }; template - class Hilbert_sort_2 +class Hilbert_sort_2 : public Hilbert_sort_middle_2 { - public: - Hilbert_sort_2 (const K &k=K() , std::ptrdiff_t limit=1 ) - : Hilbert_sort_middle_2 (k,limit) - {} +public: + Hilbert_sort_2 (const K &k=K(), std::ptrdiff_t limit=1 ) + : Hilbert_sort_middle_2 (k,limit) + {} }; } // namespace CGAL diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_3.h b/Spatial_sorting/include/CGAL/Hilbert_sort_3.h index 486eec6c401..df51c0c973c 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_3.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_3.h @@ -18,27 +18,27 @@ namespace CGAL { - template - class Hilbert_sort_3; +template +class Hilbert_sort_3; - template +template class Hilbert_sort_3 - : public Hilbert_sort_median_3 + : public Hilbert_sort_median_3 { - public: - Hilbert_sort_3 (const K &k=K() , std::ptrdiff_t limit=1 ) - : Hilbert_sort_median_3 (k,limit) - {} +public: + Hilbert_sort_3 (const K &k=K(), std::ptrdiff_t limit=1 ) + : Hilbert_sort_median_3 (k,limit) + {} }; - template - class Hilbert_sort_3 +template +class Hilbert_sort_3 : public Hilbert_sort_middle_3 { - public: - Hilbert_sort_3 (const K &k=K() , std::ptrdiff_t limit=1 ) - : Hilbert_sort_middle_3 (k,limit) - {} +public: + Hilbert_sort_3 (const K &k=K(), std::ptrdiff_t limit=1 ) + : Hilbert_sort_middle_3 (k,limit) + {} }; } // namespace CGAL diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_base.h b/Spatial_sorting/include/CGAL/Hilbert_sort_base.h index f5a0b3a9efe..d4d62d0b49a 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_base.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_base.h @@ -21,25 +21,27 @@ namespace CGAL { namespace internal { - template - RandomAccessIterator - hilbert_split (RandomAccessIterator begin, RandomAccessIterator end, - Cmp cmp = Cmp ()) - { - if (begin >= end) return begin; - #if defined(CGAL_HILBERT_SORT_WITH_MEDIAN_POLICY_CROSS_PLATFORM_BEHAVIOR) - RandomAccessIterator middle = begin + (end - begin) / 2; - CGAL::nth_element (begin, middle, end, cmp); - return middle; - #else - RandomAccessIterator middle = begin + (end - begin) / 2; - std::nth_element (begin, middle, end, cmp); - return middle; - #endif - - } +template +RandomAccessIterator +hilbert_split (RandomAccessIterator begin, RandomAccessIterator end, + Cmp cmp = Cmp ()) +{ + if (begin >= end) + return begin; + +#if defined(CGAL_HILBERT_SORT_WITH_MEDIAN_POLICY_CROSS_PLATFORM_BEHAVIOR) + RandomAccessIterator middle = begin + (end - begin) / 2; + CGAL::nth_element (begin, middle, end, cmp); + return middle; +#else + RandomAccessIterator middle = begin + (end - begin) / 2; + std::nth_element (begin, middle, end, cmp); + return middle; +#endif } +} // namespace internal + } // namespace CGAL #endif//CGAL_HILBERT_SORT_BASE_H diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_d.h b/Spatial_sorting/include/CGAL/Hilbert_sort_d.h index 0574b330262..b213c26f73d 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_d.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_d.h @@ -19,26 +19,26 @@ namespace CGAL { template - class Hilbert_sort_d; +class Hilbert_sort_d; template - class Hilbert_sort_d - : public Hilbert_sort_median_d +class Hilbert_sort_d + : public Hilbert_sort_median_d { - public: - Hilbert_sort_d (const K &k=K() , std::ptrdiff_t limit=1 ) - : Hilbert_sort_median_d (k,limit) - {} +public: + Hilbert_sort_d (const K &k=K() , std::ptrdiff_t limit=1 ) + : Hilbert_sort_median_d (k,limit) + {} }; template - class Hilbert_sort_d - : public Hilbert_sort_middle_d +class Hilbert_sort_d + : public Hilbert_sort_middle_d { - public: - Hilbert_sort_d (const K &k=K() , std::ptrdiff_t limit=1 ) - : Hilbert_sort_middle_d (k,limit) - {} +public: + Hilbert_sort_d (const K &k=K() , std::ptrdiff_t limit=1 ) + : Hilbert_sort_middle_d (k,limit) + {} }; } // namespace CGAL diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h b/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h index d66144c8158..330bea5e374 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h @@ -14,8 +14,6 @@ #include #include -#include -#include #include #include @@ -24,124 +22,132 @@ #include #endif +#include +#include + namespace CGAL { namespace internal { - template struct Hilbert_cmp_2; - template - struct Hilbert_cmp_2 - : public CGAL::cpp98::binary_function - { - typedef typename K::Point_2 Point; - K k; - Hilbert_cmp_2 (const K &_k = K()) : k(_k) {} - bool operator() (const Point &p, const Point &q) const - { - return Hilbert_cmp_2 (k) (q, p); - } - }; - - template - struct Hilbert_cmp_2 - : public CGAL::cpp98::binary_function - { - typedef typename K::Point_2 Point; - K k; - Hilbert_cmp_2 (const K &_k = K()) : k(_k) {} - bool operator() (const Point &p, const Point &q) const - { - return k.less_x_2_object() (p, q); - } - }; - - template - struct Hilbert_cmp_2 - : public CGAL::cpp98::binary_function - { - typedef typename K::Point_2 Point; - K k; - Hilbert_cmp_2 (const K &_k = K()) : k(_k) {} - bool operator() (const Point &p, const Point &q) const - { - return k.less_y_2_object() (p, q); - } - }; -} +template struct Hilbert_cmp_2; + +template +struct Hilbert_cmp_2 + : public CGAL::cpp98::binary_function +{ + typedef typename K::Point_2 Point; + K k; + Hilbert_cmp_2 (const K &_k = K()) : k(_k) {} + bool operator() (const Point &p, const Point &q) const + { + return Hilbert_cmp_2 (k) (q, p); + } +}; + +template +struct Hilbert_cmp_2 + : public CGAL::cpp98::binary_function +{ + typedef typename K::Point_2 Point; + K k; + Hilbert_cmp_2 (const K &_k = K()) : k(_k) {} + bool operator() (const Point &p, const Point &q) const + { + return k.less_x_2_object() (p, q); + } +}; + +template +struct Hilbert_cmp_2 + : public CGAL::cpp98::binary_function +{ + typedef typename K::Point_2 Point; + K k; + Hilbert_cmp_2 (const K &_k = K()) : k(_k) {} + bool operator() (const Point &p, const Point &q) const + { + return k.less_y_2_object() (p, q); + } +}; + +} // namespace internal template class Hilbert_sort_median_2 { public: typedef Hilbert_sort_median_2 Self; - typedef K Kernel; - typedef typename Kernel::Point_2 Point; - -private: - Kernel _k; - std::ptrdiff_t _limit; + typedef K Kernel; + typedef typename Kernel::Point_2 Point; - template struct Cmp : public internal::Hilbert_cmp_2 - { Cmp (const Kernel &k) : internal::Hilbert_cmp_2 (k) {} }; +private: + Kernel _k; + std::ptrdiff_t _limit; + + template + struct Cmp + : public internal::Hilbert_cmp_2 + { + Cmp (const Kernel &k) : internal::Hilbert_cmp_2 (k) {} + }; public: - Hilbert_sort_median_2 (const Kernel &k = Kernel(), std::ptrdiff_t limit = 1) - : _k(k), _limit (limit) - {} - - template - void recursive_sort (RandomAccessIterator begin, RandomAccessIterator end) const - { - const int y = (x + 1) % 2; - if (end - begin <= _limit) return; - - RandomAccessIterator m0 = begin, m4 = end; - - RandomAccessIterator m2 = internal::hilbert_split (m0, m4, Cmp< x, upx> (_k)); - RandomAccessIterator m1 = internal::hilbert_split (m0, m2, Cmp< y, upy> (_k)); - RandomAccessIterator m3 = internal::hilbert_split (m2, m4, Cmp< y, !upy> (_k)); - - recursive_sort (m0, m1); - recursive_sort (m1, m2); - recursive_sort (m2, m3); - recursive_sort (m3, m4); - } + Hilbert_sort_median_2 (const Kernel &k = Kernel(), std::ptrdiff_t limit = 1) + : _k(k), _limit (limit) + {} template - struct Recursive_sort { + void recursive_sort (RandomAccessIterator begin, RandomAccessIterator end) const + { + const int y = (x + 1) % 2; + if (end - begin <= _limit) + return; + + RandomAccessIterator m0 = begin, m4 = end; + + RandomAccessIterator m2 = internal::hilbert_split (m0, m4, Cmp< x, upx> (_k)); + RandomAccessIterator m1 = internal::hilbert_split (m0, m2, Cmp< y, upy> (_k)); + RandomAccessIterator m3 = internal::hilbert_split (m2, m4, Cmp< y, !upy> (_k)); + + recursive_sort (m0, m1); + recursive_sort (m1, m2); + recursive_sort (m2, m3); + recursive_sort (m3, m4); + } + + template + struct Recursive_sort + { const Self& hs; RandomAccessIterator begin,end; - + Recursive_sort(const Self& hs, RandomAccessIterator begin, RandomAccessIterator end) : hs(hs), begin(begin), end(end) {} - + void operator()() const { hs.recursive_sort(begin,end); } }; - + template struct Hilbert_split { RandomAccessIterator& res; RandomAccessIterator begin, end; const Comp& comp; - + Hilbert_split(RandomAccessIterator& res, RandomAccessIterator begin, RandomAccessIterator end, const Comp comp) : res(res), begin(begin), end(end), comp(comp) {} - + void operator()() const { res = internal::hilbert_split(begin, end, comp); } }; - + template void sort (RandomAccessIterator begin, RandomAccessIterator end, Parallel_tag) const { @@ -150,19 +156,20 @@ public: CGAL_USE(end); CGAL_static_assertion_msg (!(boost::is_convertible::value), "Parallel_tag is enabled but TBB is unavailable."); -#else +#else const int y = (x + 1) % 2; - if (end - begin <= _limit) return; - + if (end - begin <= _limit) + return; + RandomAccessIterator m0 = begin, m4 = end; - + if((end - begin) > 1024){ RandomAccessIterator m1, m2, m3; m2 = internal::hilbert_split (m0, m4, Cmp< x, upx> (_k)); - + tbb::parallel_invoke(Hilbert_split > (m1, m0, m2, Cmp< y, upy> (_k)), Hilbert_split > (m3, m2, m4, Cmp< y, !upy> (_k))); - + tbb::parallel_invoke(Recursive_sort (*this, m0, m1), Recursive_sort (*this, m1, m2), Recursive_sort (*this, m2, m3), @@ -175,10 +182,10 @@ public: template void sort (RandomAccessIterator begin, RandomAccessIterator end, Sequential_tag) const - { + { recursive_sort<0, false, false>(begin, end); } - + template void operator() (RandomAccessIterator begin, RandomAccessIterator end) const { diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h b/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h index 38d03ff6299..5e8525bb7c1 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h @@ -27,156 +27,154 @@ namespace CGAL { namespace internal { - template struct Hilbert_cmp_3; +template struct Hilbert_cmp_3; - template - struct Hilbert_cmp_3 - : public CGAL::cpp98::binary_function - { - typedef typename K::Point_3 Point; - K k; - Hilbert_cmp_3 (const K &_k = K()) : k(_k) {} - bool operator() (const Point &p, const Point &q) const - { - return Hilbert_cmp_3 (k) (q, p); - } - }; +template +struct Hilbert_cmp_3 + : public CGAL::cpp98::binary_function +{ + typedef typename K::Point_3 Point; + K k; + Hilbert_cmp_3 (const K &_k = K()) : k(_k) {} + bool operator() (const Point &p, const Point &q) const + { + return Hilbert_cmp_3 (k) (q, p); + } +}; - template - struct Hilbert_cmp_3 - : public CGAL::cpp98::binary_function - { - typedef typename K::Point_3 Point; - K k; - Hilbert_cmp_3 (const K &_k = K()) : k(_k) {} - bool operator() (const Point &p, const Point &q) const - { - return k.less_x_3_object() (p, q); - } - }; +template +struct Hilbert_cmp_3 + : public CGAL::cpp98::binary_function +{ + typedef typename K::Point_3 Point; + K k; + Hilbert_cmp_3 (const K &_k = K()) : k(_k) {} + bool operator() (const Point &p, const Point &q) const + { + return k.less_x_3_object() (p, q); + } +}; - template - struct Hilbert_cmp_3 - : public CGAL::cpp98::binary_function - { - typedef typename K::Point_3 Point; - K k; - Hilbert_cmp_3 (const K &_k = K()) : k(_k) {} - bool operator() (const Point &p, const Point &q) const - { - return k.less_y_3_object() (p, q); - } - }; +template +struct Hilbert_cmp_3 + : public CGAL::cpp98::binary_function +{ + typedef typename K::Point_3 Point; + K k; + Hilbert_cmp_3 (const K &_k = K()) : k(_k) {} + bool operator() (const Point &p, const Point &q) const + { + return k.less_y_3_object() (p, q); + } +}; - template - struct Hilbert_cmp_3 - : public CGAL::cpp98::binary_function - { - typedef typename K::Point_3 Point; - K k; - Hilbert_cmp_3 (const K &_k = K()) : k(_k) {} - bool operator() (const Point &p, const Point &q) const - { - return k.less_z_3_object() (p, q); - } - }; -} +template +struct Hilbert_cmp_3 + : public CGAL::cpp98::binary_function +{ + typedef typename K::Point_3 Point; + K k; + Hilbert_cmp_3 (const K &_k = K()) : k(_k) {} + bool operator() (const Point &p, const Point &q) const + { + return k.less_z_3_object() (p, q); + } +}; + +} // namespace internal template class Hilbert_sort_median_3 { public: - typedef Hilbert_sort_median_3 Self; - typedef K Kernel; - typedef typename Kernel::Point_3 Point; + typedef K Kernel; + typedef typename Kernel::Point_3 Point; private: - Kernel _k; - std::ptrdiff_t _limit; + Kernel _k; + std::ptrdiff_t _limit; - template struct Cmp : public internal::Hilbert_cmp_3 - { Cmp (const Kernel &k) : internal::Hilbert_cmp_3 (k) {} }; + template + struct Cmp + : public internal::Hilbert_cmp_3 + { + Cmp (const Kernel &k) : internal::Hilbert_cmp_3 (k) {} + }; public: - Hilbert_sort_median_3 (const Kernel &k = Kernel(), std::ptrdiff_t limit = 1) - : _k(k), _limit (limit) - {} - - - template - void recursive_sort (RandomAccessIterator begin, RandomAccessIterator end) const - { - const int y = (x + 1) % 3, z = (x + 2) % 3; - if (end - begin <= _limit) return; - - RandomAccessIterator m0 = begin, m8 = end; - - RandomAccessIterator m4 = internal::hilbert_split (m0, m8, Cmp< x, upx> (_k)); - RandomAccessIterator m2 = internal::hilbert_split (m0, m4, Cmp< y, upy> (_k)); - RandomAccessIterator m1 = internal::hilbert_split (m0, m2, Cmp< z, upz> (_k)); - RandomAccessIterator m3 = internal::hilbert_split (m2, m4, Cmp< z, !upz> (_k)); - RandomAccessIterator m6 = internal::hilbert_split (m4, m8, Cmp< y, !upy> (_k)); - RandomAccessIterator m5 = internal::hilbert_split (m4, m6, Cmp< z, upz> (_k)); - RandomAccessIterator m7 = internal::hilbert_split (m6, m8, Cmp< z, !upz> (_k)); - - recursive_sort (m0, m1); - recursive_sort (m1, m2); - recursive_sort (m2, m3); - recursive_sort (m3, m4); - recursive_sort (m4, m5); - recursive_sort (m5, m6); - recursive_sort (m6, m7); - recursive_sort (m7, m8); - } + Hilbert_sort_median_3 (const Kernel &k = Kernel(), std::ptrdiff_t limit = 1) + : _k(k), _limit (limit) + {} template - struct Recursive_sort { + void recursive_sort (RandomAccessIterator begin, RandomAccessIterator end) const + { + const int y = (x + 1) % 3, z = (x + 2) % 3; + if (end - begin <= _limit) return; + + RandomAccessIterator m0 = begin, m8 = end; + + RandomAccessIterator m4 = internal::hilbert_split (m0, m8, Cmp< x, upx> (_k)); + RandomAccessIterator m2 = internal::hilbert_split (m0, m4, Cmp< y, upy> (_k)); + RandomAccessIterator m1 = internal::hilbert_split (m0, m2, Cmp< z, upz> (_k)); + RandomAccessIterator m3 = internal::hilbert_split (m2, m4, Cmp< z, !upz> (_k)); + RandomAccessIterator m6 = internal::hilbert_split (m4, m8, Cmp< y, !upy> (_k)); + RandomAccessIterator m5 = internal::hilbert_split (m4, m6, Cmp< z, upz> (_k)); + RandomAccessIterator m7 = internal::hilbert_split (m6, m8, Cmp< z, !upz> (_k)); + + recursive_sort (m0, m1); + recursive_sort (m1, m2); + recursive_sort (m2, m3); + recursive_sort (m3, m4); + recursive_sort (m4, m5); + recursive_sort (m5, m6); + recursive_sort (m6, m7); + recursive_sort (m7, m8); + } + + template + struct Recursive_sort + { const Self& hs; RandomAccessIterator begin,end; - + Recursive_sort(const Self& hs, RandomAccessIterator begin, RandomAccessIterator end) : hs(hs), begin(begin), end(end) {} - + void operator()() const { hs.recursive_sort(begin,end); } }; - + template struct Hilbert_split { RandomAccessIterator& res; RandomAccessIterator begin, end; const Comp& comp; - + Hilbert_split(RandomAccessIterator& res, RandomAccessIterator begin, RandomAccessIterator end, const Comp comp) : res(res), begin(begin), end(end), comp(comp) {} - + void operator()() const { res = internal::hilbert_split(begin, end, comp); } }; - template void sort (RandomAccessIterator begin, RandomAccessIterator end, Parallel_tag) const { #ifndef CGAL_LINKED_WITH_TBB - CGAL_USE(begin); CGAL_USE(end); CGAL_static_assertion_msg (!(boost::is_convertible::value), "Parallel_tag is enabled but TBB is unavailable."); -#else +#else const int y = (x + 1) % 3, z = (x + 2) % 3; if ((end - begin) <= _limit) return; @@ -184,42 +182,41 @@ public: if((end - begin) > 1024){ RandomAccessIterator m1, m2, m3, m4, m5, m6, m7; m4 = internal::hilbert_split(m0, m8, Cmp(_k)); - - tbb::parallel_invoke(Hilbert_split >(m2,m0,m4,Cmp(_k)), - Hilbert_split >(m6,m4,m8,Cmp(_k))); - - tbb::parallel_invoke(Hilbert_split >(m1,m0,m2,Cmp(_k)), - Hilbert_split >(m3,m2,m4,Cmp(_k)), - Hilbert_split >(m5,m4,m6,Cmp(_k)), - Hilbert_split >(m7,m6,m8,Cmp(_k))); - - tbb::parallel_invoke(Recursive_sort(*this, m0, m1), - Recursive_sort(*this, m1, m2), - Recursive_sort(*this, m2, m3), - Recursive_sort(*this, m3, m4), - Recursive_sort(*this, m4, m5), - Recursive_sort(*this, m5, m6), - Recursive_sort(*this, m6, m7), - Recursive_sort(*this, m7, m8)); + tbb::parallel_invoke(Hilbert_split >(m2, m0, m4, Cmp(_k)), + Hilbert_split >(m6, m4, m8, Cmp(_k))); + + tbb::parallel_invoke(Hilbert_split >(m1, m0, m2, Cmp(_k)), + Hilbert_split >(m3, m2, m4, Cmp(_k)), + Hilbert_split >(m5, m4, m6, Cmp(_k)), + Hilbert_split >(m7, m6, m8, Cmp(_k))); + + tbb::parallel_invoke(Recursive_sort(*this, m0, m1), + Recursive_sort(*this, m1, m2), + Recursive_sort(*this, m2, m3), + Recursive_sort(*this, m3, m4), + Recursive_sort(*this, m4, m5), + Recursive_sort(*this, m5, m6), + Recursive_sort(*this, m6, m7), + Recursive_sort(*this, m7, m8)); } else { recursive_sort<0, false, false, false>(begin, end); } #endif } - + template void sort (RandomAccessIterator begin, RandomAccessIterator end, Sequential_tag) const { recursive_sort<0, false, false, false>(begin, end); } - - template - void operator() (RandomAccessIterator begin, RandomAccessIterator end) const - { - sort <0, false, false, false> (begin, end, ConcurrencyTag()); - } + + template + void operator() (RandomAccessIterator begin, RandomAccessIterator end) const + { + sort <0, false, false, false> (begin, end, ConcurrencyTag()); + } }; } // namespace CGAL diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_median_d.h b/Spatial_sorting/include/CGAL/Hilbert_sort_median_d.h index be6cf647254..df4c3858e5c 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_median_d.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_median_d.h @@ -23,138 +23,139 @@ namespace CGAL { namespace internal { - template - struct Hilbert_cmp_d - : public CGAL::cpp98::binary_function - { - typedef typename K::Point_d Point; - K k; - int axe; - bool orient; - Hilbert_cmp_d (int a, bool o, const K &_k = K()) - : k(_k), axe(a), orient(o) {} - bool operator() (const Point &p, const Point &q) const - { - return (orient ? (k.less_coordinate_d_object() (q,p,axe) ) - : (k.less_coordinate_d_object() (p,q,axe) )); - } - }; +template +struct Hilbert_cmp_d + : public CGAL::cpp98::binary_function +{ + typedef typename K::Point_d Point; + K k; + int axe; + bool orient; + Hilbert_cmp_d (int a, bool o, const K &_k = K()) : k(_k), axe(a), orient(o) {} -} + bool operator() (const Point &p, const Point &q) const + { + return (orient ? (k.less_coordinate_d_object() (q,p,axe) ) + : (k.less_coordinate_d_object() (p,q,axe) )); + } +}; + +} // namespace internal template class Hilbert_sort_median_d { public: - typedef K Kernel; - typedef typename Kernel::Point_d Point; - typedef std::vector< bool > Starting_position; + typedef K Kernel; + typedef typename Kernel::Point_d Point; + typedef std::vector< bool > Starting_position; private: - Kernel _k; - std::ptrdiff_t _limit; - mutable int _dimension; - mutable int two_to_dim; + Kernel _k; + std::ptrdiff_t _limit; + mutable int _dimension; + mutable int two_to_dim; - struct Cmp : public internal::Hilbert_cmp_d - { Cmp (int a, bool dir, const Kernel &k) - : internal::Hilbert_cmp_d (a,dir,k) {} }; + struct Cmp + : public internal::Hilbert_cmp_d + { + Cmp (int a, bool dir, const Kernel &k) : internal::Hilbert_cmp_d (a,dir,k) {} + }; public: - Hilbert_sort_median_d(const Kernel &k = Kernel(), std::ptrdiff_t limit = 1) - : _k(k), _limit (limit) - {} + Hilbert_sort_median_d(const Kernel &k = Kernel(), std::ptrdiff_t limit = 1) + : _k(k), _limit (limit) + {} - template - void sort (RandomAccessIterator begin, RandomAccessIterator end, - Starting_position start, int direction) const - { - if (end - begin <= _limit) return; + template + void sort (RandomAccessIterator begin, RandomAccessIterator end, + Starting_position start, int direction) const + { + if (end - begin <= _limit) + return; - int nb_directions = _dimension; - int nb_splits = two_to_dim; + int nb_directions = _dimension; + int nb_splits = two_to_dim; - if ( (end-begin) < (two_to_dim/2) ) { // not many points - nb_splits = 1; - nb_directions = 0; - while ( (end-begin) > nb_splits) { - ++nb_directions; - nb_splits *= 2; // compute 2^nb_directions - } - } - - std::vector places(nb_splits +1); - std::vector dir (nb_splits +1); - places[0]=begin; - places[nb_splits]=end; - - int last_dir = (direction + nb_directions) % _dimension; - int current_dir = direction; - int current_level_step =nb_splits; - do{ - int half_step = current_level_step/2; - int left=0; - int middle = half_step; - int right=current_level_step; - bool orient = start[current_dir]; - do{ - dir[middle] = current_dir; - places[middle] = internal::hilbert_split - (places[left], places[right], Cmp (current_dir,orient,_k)); - left =right; - right+=current_level_step; - middle+=current_level_step; - orient = ! orient; - }while( left< nb_splits); - current_level_step = half_step; - current_dir = (current_dir +1) % _dimension; - }while (current_dir != last_dir); - - if ( end-begin < two_to_dim) return; // less than 2^dim points - - /////////////start recursive calls - last_dir = (direction + _dimension -1) % _dimension; - // first step is special - sort( places[0], places[1], start, last_dir); - - for(int i=1; i - void operator() (RandomAccessIterator begin, RandomAccessIterator end) const - { - _dimension = _k.point_dimension_d_object()(*begin); - two_to_dim = 1; - Starting_position start(_dimension); - - typename std::iterator_traits::difference_type N=end-begin; - N*=2; - for (int i=0; i<_dimension; ++i) start[i]=false; // we start below in all coordinates - for (int i=0; i<_dimension; ++i) { - two_to_dim *= 2; // compute 2^_dimension - N/=2; - if (N==0) break; // not many points, this number of dimension is enough + if ( (end-begin) < (two_to_dim/2) ) { // not many points + nb_splits = 1; + nb_directions = 0; + while ( (end-begin) > nb_splits) { + ++nb_directions; + nb_splits *= 2; // compute 2^nb_directions } - - - // we start with direction 0; - sort (begin, end, start, 0); } + + std::vector places(nb_splits +1); + std::vector dir (nb_splits +1); + places[0]=begin; + places[nb_splits]=end; + + int last_dir = (direction + nb_directions) % _dimension; + int current_dir = direction; + int current_level_step =nb_splits; + do{ + int half_step = current_level_step/2; + int left=0; + int middle = half_step; + int right=current_level_step; + bool orient = start[current_dir]; + do{ + dir[middle] = current_dir; + places[middle] = internal::hilbert_split + (places[left], places[right], Cmp (current_dir,orient,_k)); + left =right; + right+=current_level_step; + middle+=current_level_step; + orient = ! orient; + }while( left< nb_splits); + current_level_step = half_step; + current_dir = (current_dir +1) % _dimension; + }while (current_dir != last_dir); + + if ( end-begin < two_to_dim) return; // less than 2^dim points + + /////////////start recursive calls + last_dir = (direction + _dimension -1) % _dimension; + // first step is special + sort( places[0], places[1], start, last_dir); + + for(int i=1; i + void operator() (RandomAccessIterator begin, RandomAccessIterator end) const + { + _dimension = _k.point_dimension_d_object()(*begin); + two_to_dim = 1; + Starting_position start(_dimension); + + typename std::iterator_traits::difference_type N=end-begin; + N*=2; + for (int i=0; i<_dimension; ++i) + start[i]=false; // we start below in all coordinates + + for (int i=0; i<_dimension; ++i) { + two_to_dim *= 2; // compute 2^_dimension + N/=2; + if (N==0) + break; // not many points, this number of dimension is enough + } + + // we start with direction 0; + sort (begin, end, start, 0); + } }; - - - } // namespace CGAL #endif//CGAL_HILBERT_SORT_MEDIAN_d_H diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_middle_2.h b/Spatial_sorting/include/CGAL/Hilbert_sort_middle_2.h index f347ca1f978..766e4fac4c6 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_middle_2.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_middle_2.h @@ -16,135 +16,135 @@ #include #include #include -#include +#include namespace CGAL { namespace internal { - template struct Fixed_hilbert_cmp_2; +template struct Fixed_hilbert_cmp_2; - template - struct Fixed_hilbert_cmp_2 - : public CGAL::cpp98::binary_function - { - typedef typename K::Point_2 Point; - K k; - double value; - Fixed_hilbert_cmp_2 (double v, const K &_k = K()) : k(_k),value(v) {} - bool operator() (const Point &p) const - { - return ! Fixed_hilbert_cmp_2 (value, k) (p); - } - }; - - template - struct Fixed_hilbert_cmp_2 - : public CGAL::cpp98::binary_function - { - typedef typename K::Point_2 Point; - K k; - double value; - Fixed_hilbert_cmp_2 (double v, const K &_k = K()) : k(_k),value(v) {} - bool operator() (const Point &p) const - { - return to_double(k.compute_x_2_object()(p)) < value; - } - }; - - template - struct Fixed_hilbert_cmp_2 - : public CGAL::cpp98::binary_function - { - typedef typename K::Point_2 Point; - K k; - double value; - Fixed_hilbert_cmp_2 (double v, const K &_k = K()) : k(_k),value(v) {} - bool operator() (const Point &p) const - { - return to_double(k.compute_y_2_object()(p)) < value; - } - }; -} +template +struct Fixed_hilbert_cmp_2 + : public CGAL::cpp98::binary_function +{ + typedef typename K::Point_2 Point; + K k; + double value; + Fixed_hilbert_cmp_2 (double v, const K &_k = K()) : k(_k),value(v) {} + bool operator() (const Point &p) const + { + return ! Fixed_hilbert_cmp_2 (value, k) (p); + } +}; +template +struct Fixed_hilbert_cmp_2 + : public CGAL::cpp98::binary_function +{ + typedef typename K::Point_2 Point; + K k; + double value; + Fixed_hilbert_cmp_2 (double v, const K &_k = K()) : k(_k),value(v) {} + bool operator() (const Point &p) const + { + return to_double(k.compute_x_2_object()(p)) < value; + } +}; + +template +struct Fixed_hilbert_cmp_2 + : public CGAL::cpp98::binary_function +{ + typedef typename K::Point_2 Point; + K k; + double value; + Fixed_hilbert_cmp_2 (double v, const K &_k = K()) : k(_k),value(v) {} + bool operator() (const Point &p) const + { + return to_double(k.compute_y_2_object()(p)) < value; + } +}; + +} // namespace internal template class Hilbert_sort_middle_2 { public: - typedef K Kernel; - typedef typename Kernel::Point_2 Point; - -private: - Kernel _k; - std::ptrdiff_t _limit; + typedef K Kernel; + typedef typename Kernel::Point_2 Point; - template struct Cmp : public internal::Fixed_hilbert_cmp_2 - { Cmp (double v, const Kernel &k) : internal::Fixed_hilbert_cmp_2 (v, k) {} }; +private: + Kernel _k; + std::ptrdiff_t _limit; + + template + struct Cmp + : public internal::Fixed_hilbert_cmp_2 + { + Cmp (double v, const Kernel &k) : internal::Fixed_hilbert_cmp_2 (v, k) {} + }; public: - Hilbert_sort_middle_2 (const Kernel &k = Kernel(), std::ptrdiff_t limit = 1) - : _k(k), _limit (limit) - {} + Hilbert_sort_middle_2 (const Kernel &k = Kernel(), std::ptrdiff_t limit = 1) + : _k(k), _limit (limit) + {} - template - void sort (RandomAccessIterator begin, RandomAccessIterator end, - double xmin, double ymin, double xmax, double ymax) const - { - const int y = (x + 1) % 2; - if (end - begin <= _limit) return; + template + void sort (RandomAccessIterator begin, RandomAccessIterator end, + double xmin, double ymin, double xmax, double ymax) const + { + const int y = (x + 1) % 2; + if (end - begin <= _limit) return; - double xmed= (xmin+xmax)/2; - double ymed= (ymin+ymax)/2; + double xmed= (xmin+xmax)/2; + double ymed= (ymin+ymax)/2; - RandomAccessIterator m0 = begin, m4 = end; + RandomAccessIterator m0 = begin, m4 = end; - RandomAccessIterator m2 = - internal::fixed_hilbert_split (m0, m4, Cmp< x, upx> (xmed,_k)); - RandomAccessIterator m1 = - internal::fixed_hilbert_split (m0, m2, Cmp< y, upy> (ymed,_k)); - RandomAccessIterator m3 = - internal::fixed_hilbert_split (m2, m4, Cmp< y, !upy> (ymed,_k)); + RandomAccessIterator m2 = internal::fixed_hilbert_split (m0, m4, Cmp< x, upx> (xmed,_k)); + RandomAccessIterator m1 = internal::fixed_hilbert_split (m0, m2, Cmp< y, upy> (ymed,_k)); + RandomAccessIterator m3 = internal::fixed_hilbert_split (m2, m4, Cmp< y, !upy> (ymed,_k)); - if (m1!=m4) - sort (m0, m1, ymin, xmin, ymed, xmed); - if (m1!=m0 || m2!=m4) - sort (m1, m2, xmin, ymed, xmed, ymax); - if (m2!=m0 || m3!=m4) - sort (m2, m3, xmed, ymed, xmax, ymax); - if (m3!=m0) - sort (m3, m4, ymed, xmax, ymin, xmed); + if (m1!=m4) + sort (m0, m1, ymin, xmin, ymed, xmed); + if (m1!=m0 || m2!=m4) + sort (m1, m2, xmin, ymed, xmed, ymax); + if (m2!=m0 || m3!=m4) + sort (m2, m3, xmed, ymed, xmax, ymax); + if (m3!=m0) + sort (m3, m4, ymed, xmax, ymin, xmed); + } + + template + void operator() (RandomAccessIterator begin, RandomAccessIterator end) const + { + //Bbox_2 box=bbox_2(begin, end); BUG: WE NEED TO FIX THIS + + K k; + double xmin=to_double(k.compute_x_2_object()(*begin)), + ymin=to_double(k.compute_y_2_object()(*begin)), + xmax=xmin, + ymax=ymin; + + for(RandomAccessIterator it=begin+1; it xmax) + xmax = to_double(k.compute_x_2_object()(*it)); + if ( to_double(k.compute_y_2_object()(*it)) > ymax) + ymax = to_double(k.compute_y_2_object()(*it)); } - template - void operator() (RandomAccessIterator begin, RandomAccessIterator end) const - { - //Bbox_2 box=bbox_2(begin, end); BUG: WE NEED TO FIX THIS - - K k; - double xmin=to_double(k.compute_x_2_object()(*begin)), - ymin=to_double(k.compute_y_2_object()(*begin)), - xmax=xmin, - ymax=ymin; - - for(RandomAccessIterator it=begin+1; it xmax) - xmax = to_double(k.compute_x_2_object()(*it)); - if ( to_double(k.compute_y_2_object()(*it)) > ymax) - ymax = to_double(k.compute_y_2_object()(*it)); - } - - sort <0, false, false> (begin, end, xmin, ymin, xmax, ymax); - } + sort <0, false, false> (begin, end, xmin, ymin, xmax, ymax); + } }; - } // namespace CGAL #endif//CGAL_HILBERT_SORT_MIDDLE_2_H diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_middle_base.h b/Spatial_sorting/include/CGAL/Hilbert_sort_middle_base.h index a331dac49e3..b8998a6f99b 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_middle_base.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_middle_base.h @@ -19,17 +19,19 @@ namespace CGAL { namespace internal { - template - RandomAccessIterator - fixed_hilbert_split (RandomAccessIterator begin, RandomAccessIterator end, - Cmp cmp = Cmp ()) - { - if (begin >= end) return begin; +template +RandomAccessIterator +fixed_hilbert_split (RandomAccessIterator begin, RandomAccessIterator end, + Cmp cmp = Cmp ()) +{ + if (begin >= end) + return begin; - return std::partition (begin, end, cmp); - } + return std::partition (begin, end, cmp); } +} // namespace internal + } // namespace CGAL #endif//CGAL_HILBERT_SORT_MIDDLE_BASE_H diff --git a/Spatial_sorting/include/CGAL/Multiscale_sort.h b/Spatial_sorting/include/CGAL/Multiscale_sort.h index 7d17617b3e1..b2cec8900ac 100644 --- a/Spatial_sorting/include/CGAL/Multiscale_sort.h +++ b/Spatial_sorting/include/CGAL/Multiscale_sort.h @@ -22,28 +22,28 @@ namespace CGAL { template class Multiscale_sort { - Sort _sort; - std::ptrdiff_t _threshold; - double _ratio; + Sort _sort; + std::ptrdiff_t _threshold; + double _ratio; public: - Multiscale_sort (const Sort &sort = Sort(), std::ptrdiff_t threshold = 1, double ratio = 0.5) - : _sort (sort), _threshold (threshold), _ratio (ratio) - { - CGAL_precondition (0. <= ratio && ratio <= 1.); - } + Multiscale_sort (const Sort &sort = Sort(), std::ptrdiff_t threshold = 1, double ratio = 0.5) + : _sort (sort), _threshold (threshold), _ratio (ratio) + { + CGAL_precondition (0. <= ratio && ratio <= 1.); + } - template - void operator() (RandomAccessIterator begin, RandomAccessIterator end) const - { - typedef typename std::iterator_traits::difference_type difference_type; - RandomAccessIterator middle = begin; - if (end - begin >= _threshold) { - middle = begin + difference_type (double(end - begin) * _ratio); - this->operator() (begin, middle); - } - _sort (middle, end); + template + void operator() (RandomAccessIterator begin, RandomAccessIterator end) const + { + typedef typename std::iterator_traits::difference_type difference_type; + RandomAccessIterator middle = begin; + if (end - begin >= _threshold) { + middle = begin + difference_type (double(end - begin) * _ratio); + this->operator() (begin, middle); } + _sort (middle, end); + } }; } // namespace CGAL diff --git a/Spatial_sorting/include/CGAL/Spatial_sort_traits_adapter_2.h b/Spatial_sorting/include/CGAL/Spatial_sort_traits_adapter_2.h index 488599fc8f4..bd1e9069693 100644 --- a/Spatial_sorting/include/CGAL/Spatial_sort_traits_adapter_2.h +++ b/Spatial_sorting/include/CGAL/Spatial_sort_traits_adapter_2.h @@ -9,7 +9,6 @@ // // Author(s) : Sebastien Loriot - #ifndef CGAL_SPATIAL_SORT_TRAITS_ADAPTER_2_H #define CGAL_SPATIAL_SORT_TRAITS_ADAPTER_2_H @@ -19,47 +18,51 @@ #include - namespace CGAL{ - + using ::get; -template -class Spatial_sort_traits_adapter_2:public Base_traits{ +template +class Spatial_sort_traits_adapter_2 + : public Base_traits +{ PointPropertyMap ppmap_; public: Spatial_sort_traits_adapter_2(Base_traits base=Base_traits()):Base_traits(base){} - Spatial_sort_traits_adapter_2(const PointPropertyMap& ppmap,Base_traits base=Base_traits()) - :Base_traits(base),ppmap_(ppmap){} + Spatial_sort_traits_adapter_2(const PointPropertyMap& ppmap, Base_traits base=Base_traits()) + :Base_traits(base), ppmap_(ppmap){} typedef Base_traits Gt; typedef typename boost::property_traits::key_type Point_2; typedef typename boost::call_traits::param_type Arg_type; - struct Less_x_2 : public Base_traits::Less_x_2{ - Less_x_2(const PointPropertyMap& ppmap,const typename Base_traits::Less_x_2& base): - Base_traits::Less_x_2(base),ppmap_(ppmap){} + struct Less_x_2 + : public Base_traits::Less_x_2 + { + Less_x_2(const PointPropertyMap& ppmap, const typename Base_traits::Less_x_2& base): + Base_traits::Less_x_2(base), ppmap_(ppmap){} const PointPropertyMap& ppmap_; - bool operator()(Arg_type p,Arg_type q) const { - return static_cast(this)->operator()(get(ppmap_,p),get(ppmap_,q)); + bool operator()(Arg_type p, Arg_type q) const { + return static_cast(this)->operator()(get(ppmap_,p), get(ppmap_,q)); } }; - struct Less_y_2 : public Base_traits::Less_y_2{ - Less_y_2(const PointPropertyMap& ppmap,const typename Base_traits::Less_y_2& base): - Base_traits::Less_y_2(base),ppmap_(ppmap){} + struct Less_y_2 + : public Base_traits::Less_y_2 + { + Less_y_2(const PointPropertyMap& ppmap, const typename Base_traits::Less_y_2& base): + Base_traits::Less_y_2(base), ppmap_(ppmap){} const PointPropertyMap& ppmap_; - bool operator()(Arg_type p,Arg_type q) const { - return static_cast(this)->operator()(get(ppmap_,p),get(ppmap_,q)); + bool operator()(Arg_type p, Arg_type q) const { + return static_cast(this)->operator()(get(ppmap_,p), get(ppmap_,q)); } }; - Less_x_2 less_x_2_object () const {return Less_x_2(ppmap_,static_cast(this)->less_x_2_object() );} - Less_y_2 less_y_2_object () const {return Less_y_2(ppmap_,static_cast(this)->less_y_2_object() );} - + Less_x_2 less_x_2_object () const {return Less_x_2(ppmap_, static_cast(this)->less_x_2_object() );} + Less_y_2 less_y_2_object () const {return Less_y_2(ppmap_, static_cast(this)->less_y_2_object() );} + const PointPropertyMap& point_property_map() const {return ppmap_;} - }; } //namespace CGAL diff --git a/Spatial_sorting/include/CGAL/Spatial_sort_traits_adapter_3.h b/Spatial_sorting/include/CGAL/Spatial_sort_traits_adapter_3.h index a9f4778345c..ac43a8586d9 100644 --- a/Spatial_sorting/include/CGAL/Spatial_sort_traits_adapter_3.h +++ b/Spatial_sorting/include/CGAL/Spatial_sort_traits_adapter_3.h @@ -17,57 +17,63 @@ #include - namespace CGAL{ using ::get; - -template -class Spatial_sort_traits_adapter_3:public Base_traits{ + +template +class Spatial_sort_traits_adapter_3 + : public Base_traits +{ PointPropertyMap ppmap_; public: Spatial_sort_traits_adapter_3(Base_traits base=Base_traits()):Base_traits(base){} - Spatial_sort_traits_adapter_3(const PointPropertyMap& ppmap,Base_traits base=Base_traits()) - :Base_traits(base),ppmap_(ppmap){} + Spatial_sort_traits_adapter_3(const PointPropertyMap& ppmap, Base_traits base=Base_traits()) + :Base_traits(base), ppmap_(ppmap){} typedef Base_traits Gt; typedef typename boost::property_traits::key_type Point_3; typedef typename boost::call_traits::param_type Arg_type; - struct Less_x_3 : public Base_traits::Less_x_3{ - Less_x_3(const PointPropertyMap& ppmap,const typename Base_traits::Less_x_3& base): - Base_traits::Less_x_3(base),ppmap_(ppmap){} + struct Less_x_3 + : public Base_traits::Less_x_3 + { + Less_x_3(const PointPropertyMap& ppmap, const typename Base_traits::Less_x_3& base): + Base_traits::Less_x_3(base), ppmap_(ppmap){} const PointPropertyMap& ppmap_; - bool operator()(Arg_type p,Arg_type q) const { - return static_cast(this)->operator()(get(ppmap_,p),get(ppmap_,q)); + bool operator()(Arg_type p, Arg_type q) const { + return static_cast(this)->operator()(get(ppmap_,p), get(ppmap_,q)); } }; - struct Less_y_3 : public Base_traits::Less_y_3{ - Less_y_3(const PointPropertyMap& ppmap,const typename Base_traits::Less_y_3& base): + struct Less_y_3 + : public Base_traits::Less_y_3 + { + Less_y_3(const PointPropertyMap& ppmap, const typename Base_traits::Less_y_3& base): Base_traits::Less_y_3(base),ppmap_(ppmap){} const PointPropertyMap& ppmap_; - bool operator()(Arg_type p,Arg_type q) const { - return static_cast(this)->operator()(get(ppmap_,p),get(ppmap_,q)); + bool operator()(Arg_type p, Arg_type q) const { + return static_cast(this)->operator()(get(ppmap_,p), get(ppmap_,q)); } }; - struct Less_z_3 : public Base_traits::Less_z_3{ - Less_z_3(const PointPropertyMap& ppmap,const typename Base_traits::Less_z_3& base): - Base_traits::Less_z_3(base),ppmap_(ppmap){} + struct Less_z_3 + : public Base_traits::Less_z_3 + { + Less_z_3(const PointPropertyMap& ppmap, const typename Base_traits::Less_z_3& base): + Base_traits::Less_z_3(base), ppmap_(ppmap){} const PointPropertyMap& ppmap_; - bool operator()(Arg_type p,Arg_type q) const { - return static_cast(this)->operator()(get(ppmap_,p),get(ppmap_,q)); + bool operator()(Arg_type p, Arg_type q) const { + return static_cast(this)->operator()(get(ppmap_,p), get(ppmap_,q)); } }; - Less_x_3 less_x_3_object () const {return Less_x_3(ppmap_,static_cast(this)->less_x_3_object() );} - Less_y_3 less_y_3_object () const {return Less_y_3(ppmap_,static_cast(this)->less_y_3_object() );} - Less_z_3 less_z_3_object () const {return Less_z_3(ppmap_,static_cast(this)->less_z_3_object() );} - + Less_x_3 less_x_3_object () const {return Less_x_3(ppmap_, static_cast(this)->less_x_3_object() );} + Less_y_3 less_y_3_object () const {return Less_y_3(ppmap_, static_cast(this)->less_y_3_object() );} + Less_z_3 less_z_3_object () const {return Less_z_3(ppmap_, static_cast(this)->less_z_3_object() );} + const PointPropertyMap& point_property_map() const {return ppmap_;} - }; } //namespace CGAL diff --git a/Spatial_sorting/include/CGAL/Spatial_sort_traits_adapter_d.h b/Spatial_sorting/include/CGAL/Spatial_sort_traits_adapter_d.h index 039718fc854..0a6313c244f 100644 --- a/Spatial_sorting/include/CGAL/Spatial_sort_traits_adapter_d.h +++ b/Spatial_sorting/include/CGAL/Spatial_sort_traits_adapter_d.h @@ -20,58 +20,60 @@ namespace CGAL{ using ::get; - -template -class Spatial_sort_traits_adapter_d:public Base_traits{ + +template +class Spatial_sort_traits_adapter_d + : public Base_traits +{ PointPropertyMap ppmap_; public: - Spatial_sort_traits_adapter_d(Base_traits base=Base_traits()):Base_traits(base){} + Spatial_sort_traits_adapter_d(Base_traits base=Base_traits()) : Base_traits(base){} - Spatial_sort_traits_adapter_d(const PointPropertyMap& ppmap,Base_traits base=Base_traits()) - :Base_traits(base),ppmap_(ppmap){} + Spatial_sort_traits_adapter_d(const PointPropertyMap& ppmap, Base_traits base=Base_traits()) + :Base_traits(base), ppmap_(ppmap){} typedef Base_traits Gt; typedef typename boost::property_traits::key_type Point_d; typedef typename boost::call_traits::param_type Arg_type; - - - struct Point_dimension_d: public Base_traits::Point_dimension_d{ - Point_dimension_d(const PointPropertyMap& ppmap,const typename Base_traits::Point_dimension_d& base): - Base_traits::Point_dimension_d(base),ppmap_(ppmap){} + struct Point_dimension_d + : public Base_traits::Point_dimension_d + { + Point_dimension_d(const PointPropertyMap& ppmap, const typename Base_traits::Point_dimension_d& base): + Base_traits::Point_dimension_d(base), ppmap_(ppmap){} const PointPropertyMap& ppmap_; int operator()(Arg_type p) const { - return static_cast(this)->operator()(get(ppmap_,p)); + return static_cast(this)->operator()(get(ppmap_, p)); } }; - struct Less_coordinate_d: public Base_traits::Less_coordinate_d{ - Less_coordinate_d(const PointPropertyMap& ppmap,const typename Base_traits::Less_coordinate_d& base): - Base_traits::Less_coordinate_d(base),ppmap_(ppmap){} + struct Less_coordinate_d + : public Base_traits::Less_coordinate_d + { + Less_coordinate_d(const PointPropertyMap& ppmap, const typename Base_traits::Less_coordinate_d& base): + Base_traits::Less_coordinate_d(base), ppmap_(ppmap){} const PointPropertyMap& ppmap_; - bool operator()(Arg_type p,Arg_type q,int i) const { - return static_cast(this)->operator()(get(ppmap_,p),get(ppmap_,q),i); + bool operator()(Arg_type p, Arg_type q, int i) const { + return static_cast(this)->operator()(get(ppmap_,p), get(ppmap_,q), i); } }; - - struct Compute_coordinate_d: public Base_traits::Compute_coordinate_d{ - Compute_coordinate_d(const PointPropertyMap& ppmap,const typename Base_traits::Compute_coordinate_d& base): - Base_traits::Compute_coordinate_d(base),ppmap_(ppmap){} + struct Compute_coordinate_d + : public Base_traits::Compute_coordinate_d + { + Compute_coordinate_d(const PointPropertyMap& ppmap, const typename Base_traits::Compute_coordinate_d& base): + Base_traits::Compute_coordinate_d(base), ppmap_(ppmap){} const PointPropertyMap& ppmap_; - bool operator()(Arg_type p,int i) const { - return static_cast(this)->operator()(get(ppmap_,p),i); + bool operator()(Arg_type p, int i) const { + return static_cast(this)->operator()(get(ppmap_,p), i); } }; - - - Point_dimension_d point_dimension_d_object () const {return Point_dimension_d(ppmap_,static_cast(this)->point_dimension_d_object() );} - Less_coordinate_d less_coordinate_d_object () const {return Less_coordinate_d(ppmap_,static_cast(this)->less_coordinate_d_object() );} - Compute_coordinate_d compute_coordinate_d_object () const {return Compute_coordinate_d(ppmap_,static_cast(this)->compute_coordinate_d_object() );} - + Point_dimension_d point_dimension_d_object () const {return Point_dimension_d(ppmap_, static_cast(this)->point_dimension_d_object() );} + Less_coordinate_d less_coordinate_d_object () const {return Less_coordinate_d(ppmap_, static_cast(this)->less_coordinate_d_object() );} + Compute_coordinate_d compute_coordinate_d_object () const {return Compute_coordinate_d(ppmap_, static_cast(this)->compute_coordinate_d_object() );} + const PointPropertyMap& point_property_map() const {return ppmap_;} - }; } //namespace CGAL diff --git a/Spatial_sorting/include/CGAL/hilbert_sort.h b/Spatial_sorting/include/CGAL/hilbert_sort.h index 0a1e8552e9b..3fbf0961720 100644 --- a/Spatial_sorting/include/CGAL/hilbert_sort.h +++ b/Spatial_sorting/include/CGAL/hilbert_sort.h @@ -27,120 +27,115 @@ #include namespace CGAL { - - namespace internal { - template - void hilbert_sort (RandomAccessIterator begin, - RandomAccessIterator end, - const Kernel &k, - Policy /*policy*/, - typename Kernel::Point_2 *) - { - typedef std::iterator_traits ITraits; - typedef typename ITraits::difference_type Diff_t; - boost::rand48 random; - boost::random_number_generator rng(random); - CGAL::cpp98::random_shuffle(begin,end, rng); - (Hilbert_sort_2 (k))(begin, end); - } - - template - void hilbert_sort (RandomAccessIterator begin, - RandomAccessIterator end, - const Kernel &k, - Policy /*policy*/, - typename Kernel::Point_3 *) - { - typedef std::iterator_traits ITraits; - typedef typename ITraits::difference_type Diff_t; - boost::rand48 random; - boost::random_number_generator rng(random); - CGAL::cpp98::random_shuffle(begin,end, rng); - (Hilbert_sort_3 (k))(begin, end); - } +template +void hilbert_sort (RandomAccessIterator begin, + RandomAccessIterator end, + const Kernel &k, + Policy /*policy*/, + typename Kernel::Point_2 *) +{ + typedef std::iterator_traits ITraits; + typedef typename ITraits::difference_type Diff_t; + boost::rand48 random; + boost::random_number_generator rng(random); + CGAL::cpp98::random_shuffle(begin,end, rng); + (Hilbert_sort_2 (k))(begin, end); +} + +template +void hilbert_sort (RandomAccessIterator begin, + RandomAccessIterator end, + const Kernel &k, + Policy /*policy*/, + typename Kernel::Point_3 *) +{ + typedef std::iterator_traits ITraits; + typedef typename ITraits::difference_type Diff_t; + boost::rand48 random; + boost::random_number_generator rng(random); + CGAL::cpp98::random_shuffle(begin,end, rng); + (Hilbert_sort_3 (k))(begin, end); +} + +template +void hilbert_sort (RandomAccessIterator begin, + RandomAccessIterator end, + const Kernel &k, + Policy /*policy*/, + typename Kernel::Point_d *) +{ + typedef std::iterator_traits ITraits; + typedef typename ITraits::difference_type Diff_t; + boost::rand48 random; + boost::random_number_generator rng(random); + CGAL::cpp98::random_shuffle(begin,end, rng); + (Hilbert_sort_d (k))(begin, end); +} - template - void hilbert_sort (RandomAccessIterator begin, - RandomAccessIterator end, - const Kernel &k, - Policy /*policy*/, - typename Kernel::Point_d *) - { - typedef std::iterator_traits ITraits; - typedef typename ITraits::difference_type Diff_t; - boost::rand48 random; - boost::random_number_generator rng(random); - CGAL::cpp98::random_shuffle(begin,end, rng); - (Hilbert_sort_d (k))(begin, end); - } } // namespace internal template void hilbert_sort (RandomAccessIterator begin, RandomAccessIterator end) { - typedef std::iterator_traits ITraits; - typedef typename ITraits::value_type value_type; - typedef CGAL::Kernel_traits KTraits; - typedef typename KTraits::Kernel Kernel; + typedef std::iterator_traits ITraits; + typedef typename ITraits::value_type value_type; + typedef CGAL::Kernel_traits KTraits; + typedef typename KTraits::Kernel Kernel; - internal::hilbert_sort(begin, end, Kernel(), Hilbert_sort_median_policy(), - static_cast (0)); + internal::hilbert_sort(begin, end, Kernel(), Hilbert_sort_median_policy(), + static_cast (0)); } template void hilbert_sort (RandomAccessIterator begin, RandomAccessIterator end, - const Kernel &k) + const Kernel &k) { - typedef std::iterator_traits ITraits; - typedef typename ITraits::value_type value_type; + typedef std::iterator_traits ITraits; + typedef typename ITraits::value_type value_type; - internal::hilbert_sort(begin, end, k, Hilbert_sort_median_policy(), - static_cast (0)); + internal::hilbert_sort(begin, end, k, Hilbert_sort_median_policy(), + static_cast (0)); } - template +template void hilbert_sort (RandomAccessIterator begin, RandomAccessIterator end, - Hilbert_sort_median_policy policy) + Hilbert_sort_median_policy policy) { - typedef std::iterator_traits ITraits; - typedef typename ITraits::value_type value_type; - typedef CGAL::Kernel_traits KTraits; - typedef typename KTraits::Kernel Kernel; - - internal::hilbert_sort(begin, end, Kernel(), policy, - static_cast (0)); + typedef std::iterator_traits ITraits; + typedef typename ITraits::value_type value_type; + typedef CGAL::Kernel_traits KTraits; + typedef typename KTraits::Kernel Kernel; + internal::hilbert_sort(begin, end, Kernel(), policy, + static_cast (0)); } - - template +template void hilbert_sort (RandomAccessIterator begin, RandomAccessIterator end, - Hilbert_sort_middle_policy policy) + Hilbert_sort_middle_policy policy) { - typedef std::iterator_traits ITraits; - typedef typename ITraits::value_type value_type; - typedef CGAL::Kernel_traits KTraits; - typedef typename KTraits::Kernel Kernel; - - internal::hilbert_sort(begin, end, Kernel(), policy, - static_cast (0)); + typedef std::iterator_traits ITraits; + typedef typename ITraits::value_type value_type; + typedef CGAL::Kernel_traits KTraits; + typedef typename KTraits::Kernel Kernel; + internal::hilbert_sort(begin, end, Kernel(), policy, + static_cast (0)); } - - template +template void hilbert_sort (RandomAccessIterator begin, RandomAccessIterator end, - const Kernel &k, Policy policy) + const Kernel &k, Policy policy) { - typedef std::iterator_traits ITraits; - typedef typename ITraits::value_type value_type; + typedef std::iterator_traits ITraits; + typedef typename ITraits::value_type value_type; - internal::hilbert_sort(begin, end, - k, policy, static_cast (0)); + internal::hilbert_sort(begin, end, + k, policy, static_cast (0)); } } // namespace CGAL diff --git a/Spatial_sorting/include/CGAL/hilbert_sort_on_sphere.h b/Spatial_sorting/include/CGAL/hilbert_sort_on_sphere.h index 3b6665a6628..57e436c671c 100644 --- a/Spatial_sorting/include/CGAL/hilbert_sort_on_sphere.h +++ b/Spatial_sorting/include/CGAL/hilbert_sort_on_sphere.h @@ -22,12 +22,12 @@ namespace internal { template void hilbert_sort_on_sphere (RandomAccessIterator begin, - RandomAccessIterator end, - const Kernel &k, - Policy, - typename Kernel::Point_3 *, - double sq_r, - const typename Kernel::Point_3 &p) + RandomAccessIterator end, + const Kernel &k, + Policy, + typename Kernel::Point_3 *, + double sq_r, + const typename Kernel::Point_3 &p) { typedef std::iterator_traits ITraits; typedef typename ITraits::difference_type Diff_t; @@ -41,62 +41,63 @@ void hilbert_sort_on_sphere (RandomAccessIterator begin, template void hilbert_sort_on_sphere (RandomAccessIterator begin, RandomAccessIterator end, - double sq_r = 1.0, - const typename CGAL::Kernel_traits::value_type>::Kernel::Point_3 &p = - typename CGAL::Kernel_traits::value_type>::Kernel::Point_3(0,0,0)) + double sq_r = 1.0, + const typename CGAL::Kernel_traits< + typename std::iterator_traits::value_type>::Kernel::Point_3 &p = + typename CGAL::Kernel_traits< + typename std::iterator_traits::value_type>::Kernel::Point_3(0,0,0)) { - typedef std::iterator_traits ITraits; - typedef typename ITraits::value_type value_type; - typedef CGAL::Kernel_traits KTraits; - typedef typename KTraits::Kernel Kernel; - - internal::hilbert_sort_on_sphere(begin, end, Kernel(), Hilbert_sort_median_policy(), - static_cast (0), sq_r, p); + typedef std::iterator_traits ITraits; + typedef typename ITraits::value_type value_type; + typedef CGAL::Kernel_traits KTraits; + typedef typename KTraits::Kernel Kernel; + internal::hilbert_sort_on_sphere(begin, end, Kernel(), Hilbert_sort_median_policy(), static_cast (0), sq_r, p); } template void hilbert_sort_on_sphere (RandomAccessIterator begin, RandomAccessIterator end, Hilbert_sort_median_policy policy, - double sq_r = 1.0, - const typename CGAL::Kernel_traits::value_type>::Kernel::Point_3 &p = - typename CGAL::Kernel_traits::value_type>::Kernel::Point_3(0,0,0)) + double sq_r = 1.0, + const typename CGAL::Kernel_traits< + typename std::iterator_traits::value_type>::Kernel::Point_3 &p = + typename CGAL::Kernel_traits< + typename std::iterator_traits::value_type>::Kernel::Point_3(0,0,0)) { - typedef std::iterator_traits ITraits; - typedef typename ITraits::value_type value_type; - typedef CGAL::Kernel_traits KTraits; - typedef typename KTraits::Kernel Kernel; + typedef std::iterator_traits ITraits; + typedef typename ITraits::value_type value_type; + typedef CGAL::Kernel_traits KTraits; + typedef typename KTraits::Kernel Kernel; - internal::hilbert_sort_on_sphere(begin, end, Kernel(), policy, - static_cast (0), sq_r, p); + internal::hilbert_sort_on_sphere(begin, end, Kernel(), policy, static_cast (0), sq_r, p); } - template void hilbert_sort_on_sphere (RandomAccessIterator begin, RandomAccessIterator end, Hilbert_sort_middle_policy policy, - double sq_r = 1.0, - const typename CGAL::Kernel_traits::value_type>::Kernel::Point_3 &p = - typename CGAL::Kernel_traits::value_type>::Kernel::Point_3(0,0,0)) + double sq_r = 1.0, + const typename CGAL::Kernel_traits< + typename std::iterator_traits::value_type>::Kernel::Point_3 &p = + typename CGAL::Kernel_traits< + typename std::iterator_traits::value_type>::Kernel::Point_3(0,0,0)) { - typedef std::iterator_traits ITraits; - typedef typename ITraits::value_type value_type; - typedef CGAL::Kernel_traits KTraits; - typedef typename KTraits::Kernel Kernel; + typedef std::iterator_traits ITraits; + typedef typename ITraits::value_type value_type; + typedef CGAL::Kernel_traits KTraits; + typedef typename KTraits::Kernel Kernel; - internal::hilbert_sort_on_sphere(begin, end, Kernel(), policy, - static_cast (0), sq_r, p); + internal::hilbert_sort_on_sphere(begin, end, Kernel(), policy, static_cast (0), sq_r, p); } - template -void hilbert_sort_on_sphere (RandomAccessIterator begin, RandomAccessIterator end, const Kernel &k, Policy policy, - double sq_r = 1.0, const typename Kernel::Point_3 &p = typename Kernel::Point_3(0,0,0)) +void hilbert_sort_on_sphere (RandomAccessIterator begin, RandomAccessIterator end, + const Kernel &k, Policy policy, + double sq_r = 1.0, + const typename Kernel::Point_3 &p = typename Kernel::Point_3(0,0,0)) { - typedef std::iterator_traits ITraits; - typedef typename ITraits::value_type value_type; + typedef std::iterator_traits ITraits; + typedef typename ITraits::value_type value_type; - internal::hilbert_sort_on_sphere(begin, end, - k, policy, static_cast (0), sq_r, p); + internal::hilbert_sort_on_sphere(begin, end, k, policy, static_cast (0), sq_r, p); } } // end of namespace CGAL diff --git a/Spatial_sorting/include/CGAL/internal/Transform_coordinates_traits_3.h b/Spatial_sorting/include/CGAL/internal/Transform_coordinates_traits_3.h index 0ce6c186a63..699720504c6 100644 --- a/Spatial_sorting/include/CGAL/internal/Transform_coordinates_traits_3.h +++ b/Spatial_sorting/include/CGAL/internal/Transform_coordinates_traits_3.h @@ -13,10 +13,10 @@ #ifndef CGAL_INTERNAL_SCALE_COORDINATES_ADAPTOR_TRAITS_3_H #define CGAL_INTERNAL_SCALE_COORDINATES_ADAPTOR_TRAITS_3_H -namespace CGAL { +namespace CGAL { namespace internal { - + template struct Transform_constant_struct; @@ -52,162 +52,162 @@ struct Coordinate_value_adaptor; template struct Coordinate_value_adaptor { - static typename R::FT x(const typename R::Point_3& p) {return p.x();} - static typename R::FT y(const typename R::Point_3& p) {return p.y();} + static typename R::FT x(const typename R::Point_3& p) {return p.x();} + static typename R::FT y(const typename R::Point_3& p) {return p.y();} }; template struct Coordinate_value_adaptor { - static typename R::FT x(const typename R::Point_3& p) {return -p.x();} - static typename R::FT y(const typename R::Point_3& p) {return p.y();} + static typename R::FT x(const typename R::Point_3& p) {return -p.x();} + static typename R::FT y(const typename R::Point_3& p) {return p.y();} }; template struct Coordinate_value_adaptor { - static typename R::FT x(const typename R::Point_3& p) {return p.x();} - static typename R::FT y(const typename R::Point_3& p) {return -p.y();} + static typename R::FT x(const typename R::Point_3& p) {return p.x();} + static typename R::FT y(const typename R::Point_3& p) {return -p.y();} }; template struct Coordinate_value_adaptor { - static typename R::FT x(const typename R::Point_3& p) {return -p.x();} - static typename R::FT y(const typename R::Point_3& p) {return -p.y();} + static typename R::FT x(const typename R::Point_3& p) {return -p.x();} + static typename R::FT y(const typename R::Point_3& p) {return -p.y();} }; template struct Coordinate_value_adaptor { - static typename R::FT x(const typename R::Point_3& p) {return p.y();} - static typename R::FT y(const typename R::Point_3& p) {return p.x();} + static typename R::FT x(const typename R::Point_3& p) {return p.y();} + static typename R::FT y(const typename R::Point_3& p) {return p.x();} }; template struct Coordinate_value_adaptor { - static typename R::FT x(const typename R::Point_3& p) {return -p.y();} - static typename R::FT y(const typename R::Point_3& p) {return p.x();} + static typename R::FT x(const typename R::Point_3& p) {return -p.y();} + static typename R::FT y(const typename R::Point_3& p) {return p.x();} }; template struct Coordinate_value_adaptor { - static typename R::FT x(const typename R::Point_3& p) {return p.y();} - static typename R::FT y(const typename R::Point_3& p) {return -p.x();} + static typename R::FT x(const typename R::Point_3& p) {return p.y();} + static typename R::FT y(const typename R::Point_3& p) {return -p.x();} }; template struct Coordinate_value_adaptor { - static typename R::FT x(const typename R::Point_3& p) {return -p.y();} - static typename R::FT y(const typename R::Point_3& p) {return -p.x();} + static typename R::FT x(const typename R::Point_3& p) {return -p.y();} + static typename R::FT y(const typename R::Point_3& p) {return -p.x();} }; template struct Coordinate_value_adaptor { - static typename R::FT x(const typename R::Point_3& p) {return p.x();} - static typename R::FT y(const typename R::Point_3& p) {return p.z();} + static typename R::FT x(const typename R::Point_3& p) {return p.x();} + static typename R::FT y(const typename R::Point_3& p) {return p.z();} }; template struct Coordinate_value_adaptor { - static typename R::FT x(const typename R::Point_3& p) {return -p.x();} - static typename R::FT y(const typename R::Point_3& p) {return p.z();} + static typename R::FT x(const typename R::Point_3& p) {return -p.x();} + static typename R::FT y(const typename R::Point_3& p) {return p.z();} }; template struct Coordinate_value_adaptor { - static typename R::FT x(const typename R::Point_3& p) {return p.x();} - static typename R::FT y(const typename R::Point_3& p) {return -p.z();} + static typename R::FT x(const typename R::Point_3& p) {return p.x();} + static typename R::FT y(const typename R::Point_3& p) {return -p.z();} }; template struct Coordinate_value_adaptor { - static typename R::FT x(const typename R::Point_3& p) {return -p.x();} - static typename R::FT y(const typename R::Point_3& p) {return -p.z();} + static typename R::FT x(const typename R::Point_3& p) {return -p.x();} + static typename R::FT y(const typename R::Point_3& p) {return -p.z();} }; template struct Coordinate_value_adaptor { - static typename R::FT x(const typename R::Point_3& p) {return p.z();} - static typename R::FT y(const typename R::Point_3& p) {return p.x();} + static typename R::FT x(const typename R::Point_3& p) {return p.z();} + static typename R::FT y(const typename R::Point_3& p) {return p.x();} }; template struct Coordinate_value_adaptor { - static typename R::FT x(const typename R::Point_3& p) {return -p.z();} - static typename R::FT y(const typename R::Point_3& p) {return p.x();} + static typename R::FT x(const typename R::Point_3& p) {return -p.z();} + static typename R::FT y(const typename R::Point_3& p) {return p.x();} }; template struct Coordinate_value_adaptor { - static typename R::FT x(const typename R::Point_3& p) {return p.z();} - static typename R::FT y(const typename R::Point_3& p) {return -p.x();} + static typename R::FT x(const typename R::Point_3& p) {return p.z();} + static typename R::FT y(const typename R::Point_3& p) {return -p.x();} }; template struct Coordinate_value_adaptor { - static typename R::FT x(const typename R::Point_3& p) {return -p.z();} - static typename R::FT y(const typename R::Point_3& p) {return -p.x();} + static typename R::FT x(const typename R::Point_3& p) {return -p.z();} + static typename R::FT y(const typename R::Point_3& p) {return -p.x();} }; template struct Coordinate_value_adaptor { - static typename R::FT x(const typename R::Point_3& p) {return p.y();} - static typename R::FT y(const typename R::Point_3& p) {return p.z();} + static typename R::FT x(const typename R::Point_3& p) {return p.y();} + static typename R::FT y(const typename R::Point_3& p) {return p.z();} }; template struct Coordinate_value_adaptor { - static typename R::FT x(const typename R::Point_3& p) {return -p.y();} - static typename R::FT y(const typename R::Point_3& p) {return p.z();} + static typename R::FT x(const typename R::Point_3& p) {return -p.y();} + static typename R::FT y(const typename R::Point_3& p) {return p.z();} }; template struct Coordinate_value_adaptor { - static typename R::FT x(const typename R::Point_3& p) {return p.y();} - static typename R::FT y(const typename R::Point_3& p) {return -p.z();} + static typename R::FT x(const typename R::Point_3& p) {return p.y();} + static typename R::FT y(const typename R::Point_3& p) {return -p.z();} }; template struct Coordinate_value_adaptor { - static typename R::FT x(const typename R::Point_3& p) {return -p.y();} - static typename R::FT y(const typename R::Point_3& p) {return -p.z();} + static typename R::FT x(const typename R::Point_3& p) {return -p.y();} + static typename R::FT y(const typename R::Point_3& p) {return -p.z();} }; template struct Coordinate_value_adaptor { - static typename R::FT x(const typename R::Point_3& p) {return p.z();} - static typename R::FT y(const typename R::Point_3& p) {return p.y();} + static typename R::FT x(const typename R::Point_3& p) {return p.z();} + static typename R::FT y(const typename R::Point_3& p) {return p.y();} }; template struct Coordinate_value_adaptor { - static typename R::FT x(const typename R::Point_3& p) {return -p.z();} - static typename R::FT y(const typename R::Point_3& p) {return p.y();} + static typename R::FT x(const typename R::Point_3& p) {return -p.z();} + static typename R::FT y(const typename R::Point_3& p) {return p.y();} }; template struct Coordinate_value_adaptor { - static typename R::FT x(const typename R::Point_3& p) {return p.z();} - static typename R::FT y(const typename R::Point_3& p) {return -p.y();} + static typename R::FT x(const typename R::Point_3& p) {return p.z();} + static typename R::FT y(const typename R::Point_3& p) {return -p.y();} }; template struct Coordinate_value_adaptor { - static typename R::FT x(const typename R::Point_3& p) {return -p.z();} - static typename R::FT y(const typename R::Point_3& p) {return -p.y();} + static typename R::FT x(const typename R::Point_3& p) {return -p.z();} + static typename R::FT y(const typename R::Point_3& p) {return -p.y();} }; template class Compute_x_2 { public: - typedef typename R::Point_3 Point; + typedef typename R::Point_3 Point; typename R::FT x(const Point &p) const { return Coordinate_value_adaptor::x(p); } typename R::FT operator()(const Point& p) const { return x(p); } }; template -class Compute_y_2 +class Compute_y_2 { public: - typedef typename R::Point_3 Point; + typedef typename R::Point_3 Point; typename R::FT y(const Point &p) const { return Coordinate_value_adaptor::y(p); } typename R::FT operator()(const Point& p) const { return y(p); } }; @@ -216,7 +216,7 @@ template class Less_x_2 { public: - typedef typename R::Point_3 Point; + typedef typename R::Point_3 Point; typename R::FT x(const Point &p) const { return Coordinate_value_adaptor::x(p); } bool operator()(const Point& p, const Point& q) const { return x(p) < x(q); } }; @@ -225,34 +225,33 @@ template class Less_y_2 { public: - typedef typename R::Point_3 Point; + typedef typename R::Point_3 Point; typename R::FT y(const Point &p) const { return Coordinate_value_adaptor::y(p); } bool operator()(const Point& p, const Point& q) const { return y(p) < y(q); } }; template struct Transform_coordinates_traits_3 { - private: - enum {opt = Transform_constant_struct::value}; - - public: - typedef Transform_coordinates_traits_3 Traits; - typedef R Rp; - typedef typename Rp::Point_3 Point_2; - typedef Less_x_2 Less_x; - typedef Less_y_2 Less_y; - typedef Compute_x_2 Compute_x; - typedef Compute_y_2 Compute_y; - - Transform_coordinates_traits_3(){} - Transform_coordinates_traits_3(const Transform_coordinates_traits_3&){} - - Less_x less_x_2_object() const { return Less_x(); } - Less_y less_y_2_object() const { return Less_y(); } - Compute_x compute_x_2_object() const { return Compute_x(); } - Compute_y compute_y_2_object() const { return Compute_y(); } +private: + enum {opt = Transform_constant_struct::value}; + +public: + typedef Transform_coordinates_traits_3 Traits; + typedef R Rp; + typedef typename Rp::Point_3 Point_2; + typedef Less_x_2 Less_x; + typedef Less_y_2 Less_y; + typedef Compute_x_2 Compute_x; + typedef Compute_y_2 Compute_y; + + Transform_coordinates_traits_3(){} + Transform_coordinates_traits_3(const Transform_coordinates_traits_3&){} + + Less_x less_x_2_object() const { return Less_x(); } + Less_y less_y_2_object() const { return Less_y(); } + Compute_x compute_x_2_object() const { return Compute_x(); } + Compute_y compute_y_2_object() const { return Compute_y(); } }; - } } //namespace CGAL::internal diff --git a/Spatial_sorting/include/CGAL/spatial_sort.h b/Spatial_sorting/include/CGAL/spatial_sort.h index d49dbf39927..aa38be26af8 100644 --- a/Spatial_sorting/include/CGAL/spatial_sort.h +++ b/Spatial_sorting/include/CGAL/spatial_sort.h @@ -29,153 +29,146 @@ namespace CGAL { namespace internal { - template - void spatial_sort ( - RandomAccessIterator begin, RandomAccessIterator end, - const Kernel &k, - Policy /*policy*/, - typename Kernel::Point_2 *, - std::ptrdiff_t threshold_hilbert, - std::ptrdiff_t threshold_multiscale, - double ratio) - { - typedef std::iterator_traits Iterator_traits; - typedef typename Iterator_traits::difference_type Diff_t; - typedef Hilbert_sort_2 Sort; - boost::rand48 random; - boost::random_number_generator rng(random); - CGAL::cpp98::random_shuffle(begin,end,rng); +template +void spatial_sort (RandomAccessIterator begin, RandomAccessIterator end, + const Kernel &k, + Policy /*policy*/, + typename Kernel::Point_2 *, + std::ptrdiff_t threshold_hilbert, + std::ptrdiff_t threshold_multiscale, + double ratio) +{ + typedef std::iterator_traits Iterator_traits; + typedef typename Iterator_traits::difference_type Diff_t; + typedef Hilbert_sort_2 Sort; + boost::rand48 random; + boost::random_number_generator rng(random); + CGAL::cpp98::random_shuffle(begin,end,rng); - if (threshold_hilbert==0) threshold_hilbert=4; - if (threshold_multiscale==0) threshold_multiscale=16; - if (ratio==0.0) ratio=0.25; - - (Multiscale_sort (Sort (k, threshold_hilbert), - threshold_multiscale, ratio)) (begin, end); - } - - template - void spatial_sort ( - RandomAccessIterator begin, RandomAccessIterator end, - const Kernel &k, - Policy /*policy*/, - typename Kernel::Point_3 *, - std::ptrdiff_t threshold_hilbert, - std::ptrdiff_t threshold_multiscale, - double ratio) - { - typedef std::iterator_traits Iterator_traits; - typedef typename Iterator_traits::difference_type Diff_t; - typedef Hilbert_sort_3 Sort; - boost::rand48 random; - boost::random_number_generator rng(random); - CGAL::cpp98::random_shuffle(begin,end, rng); - - if (threshold_hilbert==0) threshold_hilbert=8; - if (threshold_multiscale==0) threshold_multiscale=64; - if (ratio==0.0) ratio=0.125; - - (Multiscale_sort (Sort (k, threshold_hilbert), - threshold_multiscale, ratio)) (begin, end); - } - - template - void spatial_sort ( - RandomAccessIterator begin, RandomAccessIterator end, - const Kernel &k, - Policy /*policy*/, - typename Kernel::Point_d *, - std::ptrdiff_t threshold_hilbert, - std::ptrdiff_t threshold_multiscale, - double ratio) - { - typedef std::iterator_traits Iterator_traits; - typedef typename Iterator_traits::difference_type Diff_t; - typedef Hilbert_sort_d Sort; - boost::rand48 random; - boost::random_number_generator rng(random); - CGAL::cpp98::random_shuffle(begin,end, rng); - - if (threshold_hilbert==0) threshold_hilbert=10; - if (threshold_multiscale==0) threshold_multiscale=500; - if (ratio==0.0) ratio=0.05; - - (Multiscale_sort (Sort (k, threshold_hilbert), - threshold_multiscale, ratio)) (begin, end); - } - -} //namespace internal + if (threshold_hilbert==0) threshold_hilbert=4; + if (threshold_multiscale==0) threshold_multiscale=16; + if (ratio==0.0) ratio=0.25; + (Multiscale_sort (Sort (k, threshold_hilbert), threshold_multiscale, ratio)) (begin, end); +} template void spatial_sort (RandomAccessIterator begin, RandomAccessIterator end, const Kernel &k, - Policy policy, - std::ptrdiff_t threshold_hilbert=0, - std::ptrdiff_t threshold_multiscale=0, - double ratio=0.0) + Policy /*policy*/, + typename Kernel::Point_3 *, + std::ptrdiff_t threshold_hilbert, + std::ptrdiff_t threshold_multiscale, + double ratio) { - typedef std::iterator_traits ITraits; - typedef typename ITraits::value_type value_type; + typedef std::iterator_traits Iterator_traits; + typedef typename Iterator_traits::difference_type Diff_t; + typedef Hilbert_sort_3 Sort; + boost::rand48 random; + boost::random_number_generator rng(random); + CGAL::cpp98::random_shuffle(begin,end, rng); - internal::spatial_sort(begin, end, k, policy, static_cast (0), - threshold_hilbert,threshold_multiscale,ratio); + if (threshold_hilbert==0) threshold_hilbert=8; + if (threshold_multiscale==0) threshold_multiscale=64; + if (ratio==0.0) ratio=0.125; + + (Multiscale_sort (Sort (k, threshold_hilbert), threshold_multiscale, ratio)) (begin, end); +} + +template +void spatial_sort (RandomAccessIterator begin, RandomAccessIterator end, + const Kernel &k, + Policy /*policy*/, + typename Kernel::Point_d *, + std::ptrdiff_t threshold_hilbert, + std::ptrdiff_t threshold_multiscale, + double ratio) +{ + typedef std::iterator_traits Iterator_traits; + typedef typename Iterator_traits::difference_type Diff_t; + typedef Hilbert_sort_d Sort; + boost::rand48 random; + boost::random_number_generator rng(random); + CGAL::cpp98::random_shuffle(begin,end, rng); + + if (threshold_hilbert==0) threshold_hilbert=10; + if (threshold_multiscale==0) threshold_multiscale=500; + if (ratio==0.0) ratio=0.05; + + (Multiscale_sort (Sort (k, threshold_hilbert), threshold_multiscale, ratio)) (begin, end); +} + +} //namespace internal + +template +void spatial_sort (RandomAccessIterator begin, RandomAccessIterator end, + const Kernel &k, + Policy policy, + std::ptrdiff_t threshold_hilbert=0, + std::ptrdiff_t threshold_multiscale=0, + double ratio=0.0) +{ + typedef std::iterator_traits ITraits; + typedef typename ITraits::value_type value_type; + + internal::spatial_sort(begin, end, k, policy, static_cast (0), + threshold_hilbert,threshold_multiscale,ratio); } template void spatial_sort (RandomAccessIterator begin, RandomAccessIterator end, - Hilbert_sort_median_policy policy, - std::ptrdiff_t threshold_hilbert=0, - std::ptrdiff_t threshold_multiscale=0, - double ratio=0.0) + Hilbert_sort_median_policy policy, + std::ptrdiff_t threshold_hilbert=0, + std::ptrdiff_t threshold_multiscale=0, + double ratio=0.0) { - typedef std::iterator_traits ITraits; - typedef typename ITraits::value_type value_type; - typedef CGAL::Kernel_traits KTraits; - typedef typename KTraits::Kernel Kernel; + typedef std::iterator_traits ITraits; + typedef typename ITraits::value_type value_type; + typedef CGAL::Kernel_traits KTraits; + typedef typename KTraits::Kernel Kernel; - spatial_sort (begin, end, Kernel(), policy, - threshold_hilbert,threshold_multiscale,ratio); + spatial_sort (begin, end, Kernel(), policy, + threshold_hilbert,threshold_multiscale,ratio); } - + template void spatial_sort (RandomAccessIterator begin, RandomAccessIterator end, - Hilbert_sort_middle_policy policy, - std::ptrdiff_t threshold_hilbert=0, - std::ptrdiff_t threshold_multiscale=0, - double ratio=0.0) + Hilbert_sort_middle_policy policy, + std::ptrdiff_t threshold_hilbert=0, + std::ptrdiff_t threshold_multiscale=0, + double ratio=0.0) { - typedef std::iterator_traits ITraits; - typedef typename ITraits::value_type value_type; - typedef CGAL::Kernel_traits KTraits; - typedef typename KTraits::Kernel Kernel; + typedef std::iterator_traits ITraits; + typedef typename ITraits::value_type value_type; + typedef CGAL::Kernel_traits KTraits; + typedef typename KTraits::Kernel Kernel; - spatial_sort (begin, end, Kernel(), policy, - threshold_hilbert,threshold_multiscale,ratio); + spatial_sort (begin, end, Kernel(), policy, + threshold_hilbert,threshold_multiscale,ratio); } template void spatial_sort (RandomAccessIterator begin, RandomAccessIterator end, const Kernel &k, - std::ptrdiff_t threshold_hilbert=0, - std::ptrdiff_t threshold_multiscale=0, - double ratio=0.0) + std::ptrdiff_t threshold_hilbert=0, + std::ptrdiff_t threshold_multiscale=0, + double ratio=0.0) { - spatial_sort (begin, end, k, - Hilbert_sort_median_policy(), - threshold_hilbert,threshold_multiscale,ratio); + spatial_sort (begin, end, k, + Hilbert_sort_median_policy(), + threshold_hilbert,threshold_multiscale,ratio); } - template +template void spatial_sort (RandomAccessIterator begin, RandomAccessIterator end, - std::ptrdiff_t threshold_hilbert=0, - std::ptrdiff_t threshold_multiscale=0, - double ratio=0.0) + std::ptrdiff_t threshold_hilbert=0, + std::ptrdiff_t threshold_multiscale=0, + double ratio=0.0) { spatial_sort (begin, end, - Hilbert_sort_median_policy(), - threshold_hilbert,threshold_multiscale,ratio); + Hilbert_sort_median_policy(), + threshold_hilbert,threshold_multiscale,ratio); } } // namespace CGAL diff --git a/Spatial_sorting/include/CGAL/spatial_sort_on_sphere.h b/Spatial_sorting/include/CGAL/spatial_sort_on_sphere.h index ada26c748b6..2bcd6ec10e3 100644 --- a/Spatial_sorting/include/CGAL/spatial_sort_on_sphere.h +++ b/Spatial_sorting/include/CGAL/spatial_sort_on_sphere.h @@ -22,116 +22,115 @@ namespace CGAL { namespace internal { template -void spatial_sort_on_sphere ( - RandomAccessIterator begin, RandomAccessIterator end, - const Kernel &k, - Policy /*policy*/, - typename Kernel::Point_3 *, - double sq_r, - const typename Kernel::Point_3 &p, - std::ptrdiff_t threshold_hilbert, - std::ptrdiff_t threshold_multiscale, - double ratio) +void spatial_sort_on_sphere (RandomAccessIterator begin, RandomAccessIterator end, + const Kernel &k, + Policy /*policy*/, + typename Kernel::Point_3 *, + double sq_r, + const typename Kernel::Point_3 &p, + std::ptrdiff_t threshold_hilbert, + std::ptrdiff_t threshold_multiscale, + double ratio) { typedef Hilbert_sort_on_sphere_3 Sort; - typedef std::iterator_traits ITraits; - typedef typename ITraits::difference_type Diff_t; + typedef std::iterator_traits ITraits; + typedef typename ITraits::difference_type Diff_t; - boost::rand48 random; - boost::random_number_generator rng(random); - CGAL::cpp98::random_shuffle(begin,end, rng); + boost::rand48 random; + boost::random_number_generator rng(random); + CGAL::cpp98::random_shuffle(begin,end, rng); - if (threshold_hilbert==0) threshold_hilbert=4; - if (threshold_multiscale==0) threshold_multiscale=16; - if (ratio==0.0) ratio=0.25; + if (threshold_hilbert==0) threshold_hilbert=4; + if (threshold_multiscale==0) threshold_multiscale=16; + if (ratio==0.0) ratio=0.25; - (Multiscale_sort (Sort (k, sq_r, p, threshold_hilbert), - threshold_multiscale, ratio)) (begin, end); + (Multiscale_sort (Sort (k, sq_r, p, threshold_hilbert), + threshold_multiscale, ratio)) (begin, end); } } // end of namespace internal template void spatial_sort_on_sphere (RandomAccessIterator begin, RandomAccessIterator end, - const Kernel &k, - Policy policy, - double sq_r=1.0, - const typename Kernel::Point_3 &p = typename Kernel::Point_3(0,0,0), - std::ptrdiff_t threshold_hilbert=0, - std::ptrdiff_t threshold_multiscale=0, - double ratio=0.0) + const Kernel &k, + Policy policy, + double sq_r=1.0, + const typename Kernel::Point_3 &p = typename Kernel::Point_3(0,0,0), + std::ptrdiff_t threshold_hilbert=0, + std::ptrdiff_t threshold_multiscale=0, + double ratio=0.0) { - typedef std::iterator_traits ITraits; - typedef typename ITraits::value_type value_type; + typedef std::iterator_traits ITraits; + typedef typename ITraits::value_type value_type; - internal::spatial_sort_on_sphere(begin, end, k, policy, static_cast (0), - sq_r,p, threshold_hilbert,threshold_multiscale,ratio); + internal::spatial_sort_on_sphere(begin, end, k, policy, static_cast (0), + sq_r,p, threshold_hilbert,threshold_multiscale,ratio); } template void spatial_sort_on_sphere (RandomAccessIterator begin, RandomAccessIterator end, - Hilbert_sort_median_policy policy, - double sq_r=1.0, - const typename CGAL::Kernel_traits::value_type>::Kernel::Point_3 &p = - typename CGAL::Kernel_traits::value_type>::Kernel::Point_3(0,0,0), - std::ptrdiff_t threshold_hilbert=0, - std::ptrdiff_t threshold_multiscale=0, - double ratio=0.0) + Hilbert_sort_median_policy policy, + double sq_r=1.0, + const typename CGAL::Kernel_traits::value_type>::Kernel::Point_3 &p = + typename CGAL::Kernel_traits::value_type>::Kernel::Point_3(0,0,0), + std::ptrdiff_t threshold_hilbert=0, + std::ptrdiff_t threshold_multiscale=0, + double ratio=0.0) { - typedef std::iterator_traits ITraits; - typedef typename ITraits::value_type value_type; - typedef CGAL::Kernel_traits KTraits; - typedef typename KTraits::Kernel Kernel; + typedef std::iterator_traits ITraits; + typedef typename ITraits::value_type value_type; + typedef CGAL::Kernel_traits KTraits; + typedef typename KTraits::Kernel Kernel; - spatial_sort_on_sphere (begin, end, Kernel(), policy, sq_r, p, - threshold_hilbert,threshold_multiscale,ratio); + spatial_sort_on_sphere (begin, end, Kernel(), policy, sq_r, p, + threshold_hilbert,threshold_multiscale,ratio); } template void spatial_sort_on_sphere (RandomAccessIterator begin, RandomAccessIterator end, - Hilbert_sort_middle_policy policy, - double sq_r=1.0, - const typename CGAL::Kernel_traits::value_type>::Kernel::Point_3 &p = - typename CGAL::Kernel_traits::value_type>::Kernel::Point_3(0,0,0), - std::ptrdiff_t threshold_hilbert=0, - std::ptrdiff_t threshold_multiscale=0, - double ratio=0.0) + Hilbert_sort_middle_policy policy, + double sq_r=1.0, + const typename CGAL::Kernel_traits::value_type>::Kernel::Point_3 &p = + typename CGAL::Kernel_traits::value_type>::Kernel::Point_3(0,0,0), + std::ptrdiff_t threshold_hilbert=0, + std::ptrdiff_t threshold_multiscale=0, + double ratio=0.0) { - typedef std::iterator_traits ITraits; - typedef typename ITraits::value_type value_type; - typedef CGAL::Kernel_traits KTraits; - typedef typename KTraits::Kernel Kernel; + typedef std::iterator_traits ITraits; + typedef typename ITraits::value_type value_type; + typedef CGAL::Kernel_traits KTraits; + typedef typename KTraits::Kernel Kernel; - spatial_sort_on_sphere (begin, end, Kernel(), policy, sq_r,p, - threshold_hilbert,threshold_multiscale,ratio); + spatial_sort_on_sphere (begin, end, Kernel(), policy, sq_r,p, + threshold_hilbert,threshold_multiscale,ratio); } template void spatial_sort_on_sphere (RandomAccessIterator begin, RandomAccessIterator end, - const Kernel &k, - double sq_r = 1.0, - const typename Kernel::Point_3 &p = typename Kernel::Point_3(0,0,0), - std::ptrdiff_t threshold_hilbert=0, - std::ptrdiff_t threshold_multiscale=0, - double ratio=0.0) + const Kernel &k, + double sq_r = 1.0, + const typename Kernel::Point_3 &p = typename Kernel::Point_3(0,0,0), + std::ptrdiff_t threshold_hilbert=0, + std::ptrdiff_t threshold_multiscale=0, + double ratio=0.0) { - spatial_sort_on_sphere (begin, end, k, - Hilbert_sort_median_policy(), sq_r, p, - threshold_hilbert,threshold_multiscale,ratio); + spatial_sort_on_sphere (begin, end, k, + Hilbert_sort_median_policy(), sq_r, p, + threshold_hilbert,threshold_multiscale,ratio); } template void spatial_sort_on_sphere (RandomAccessIterator begin, RandomAccessIterator end, - double sq_r = 1.0, - const typename CGAL::Kernel_traits::value_type>::Kernel::Point_3 &p = - typename CGAL::Kernel_traits::value_type>::Kernel::Point_3(0,0,0), - std::ptrdiff_t threshold_hilbert=0, - std::ptrdiff_t threshold_multiscale=0, - double ratio=0.0) + double sq_r = 1.0, + const typename CGAL::Kernel_traits::value_type>::Kernel::Point_3 &p = + typename CGAL::Kernel_traits::value_type>::Kernel::Point_3(0,0,0), + std::ptrdiff_t threshold_hilbert=0, + std::ptrdiff_t threshold_multiscale=0, + double ratio=0.0) { - spatial_sort_on_sphere (begin, end, - Hilbert_sort_median_policy(), sq_r,p, - threshold_hilbert,threshold_multiscale,ratio); + spatial_sort_on_sphere (begin, end, + Hilbert_sort_median_policy(), sq_r,p, + threshold_hilbert,threshold_multiscale,ratio); } } // end of namespace CGAL From b4121c8bf401c84c7a4766f6e80e24fc8a47b112 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 2 Jan 2020 10:40:29 +0100 Subject: [PATCH 113/185] Clean whitespace/tabs in Spatial_sorting/test --- .../test/Spatial_sorting/test_hilbert.cpp | 963 +++++++++--------- .../test/Spatial_sorting/test_multiscale.cpp | 188 ++-- 2 files changed, 575 insertions(+), 576 deletions(-) diff --git a/Spatial_sorting/test/Spatial_sorting/test_hilbert.cpp b/Spatial_sorting/test/Spatial_sorting/test_hilbert.cpp index ac1e5d47ef9..269504b0451 100644 --- a/Spatial_sorting/test/Spatial_sorting/test_hilbert.cpp +++ b/Spatial_sorting/test/Spatial_sorting/test_hilbert.cpp @@ -32,643 +32,642 @@ typedef CGAL::Creator_uniform_d::iterator, Point>Creator_d; int main () { - int nb_points_2 = 5000, nb_points_3 = 5000, - nb_points_d=10000, small_nb_points_d=3; + int nb_points_2 = 5000, nb_points_3 = 5000, + nb_points_d=10000, small_nb_points_d=3; CGAL::Random random (42); CGAL::Timer cost; - std::cout << "Testing Hilbert sort." << std::endl; + std::cout << "Testing Hilbert sort." << std::endl; - { - std::cout << "Testing 2D: Generating "< v; - v.reserve (nb_points_2); + std::vector v; + v.reserve (nb_points_2); - CGAL::Random_points_in_square_2 gen (1.0, random); + CGAL::Random_points_in_square_2 gen (1.0, random); - for (int i = 0; i < nb_points_2 - 1; ++i) - v.push_back (*gen++); - v.push_back(v[0]); //insert twice the same point + for (int i = 0; i < nb_points_2 - 1; ++i) + v.push_back (*gen++); + v.push_back(v[0]); //insert twice the same point - std::cout << "done." << std::endl; + std::cout << "done." << std::endl; - std::vector v2 (v); + std::vector v2 (v); - std::cout << " Sorting points... " << std::flush; + std::cout << " Sorting points... " << std::flush; - cost.reset();cost.start(); - CGAL::hilbert_sort (v.begin(), v.end()); - cost.stop(); + cost.reset();cost.start(); + CGAL::hilbert_sort (v.begin(), v.end()); + cost.stop(); - std::cout << "done in "< v; + v.reserve(size); + + CGAL::points_on_square_grid_2 (box_size, (std::size_t)size, + std::back_inserter(v), Creator_2() ); + + std::cout << "done." << std::endl; + + std::cout << " Sorting points... " << std::flush; + + cost.reset();cost.start(); + CGAL::hilbert_sort (v.begin(), v.end()); + cost.stop(); + + std::cout << "done in "< v; + v.reserve (nb_points_2); + + CGAL::Random_points_in_square_2 gen (1.0, random); + + for (int i = 0; i < nb_points_2 - 1; ++i) + v.push_back (*gen++); + v.push_back(v[0]); //insert twice the same point + + std::cout << "done." << std::endl; + + std::vector v2 (v); + + std::cout << " Sorting points... " << std::flush; + + cost.reset();cost.start(); + CGAL::hilbert_sort(v.begin(),v.end(), CGAL::Hilbert_sort_middle_policy()); + cost.stop(); + + std::cout << "done in "< v; + v.reserve(size); + + CGAL::points_on_square_grid_2 (box_size, (std::size_t)size, + std::back_inserter(v), Creator_2() ); + + std::cout << "done." << std::endl; + + std::cout << " Sorting points... " << std::flush; + + cost.reset();cost.start(); + CGAL::hilbert_sort(v.begin(),v.end(), CGAL::Hilbert_sort_middle_policy()); + cost.stop(); + + std::cout << "done in "< v; - v.reserve(size); + std::cout << "OK." << std::endl; + } - CGAL::points_on_square_grid_2 (box_size, (std::size_t)size, - std::back_inserter(v), Creator_2() ); + { + std::cout << "Testing 3D: Generating "< v; + v.reserve (nb_points_3); - std::cout << " Sorting points... " << std::flush; + CGAL::Random_points_in_cube_3 gen (1.0, random); - cost.reset();cost.start(); - CGAL::hilbert_sort (v.begin(), v.end()); - cost.stop(); + for (int i = 0; i < nb_points_3 - 1; ++i) + v.push_back (*gen++); + v.push_back(v[0]); //insert twice the same point - std::cout << "done in "< v2 (v); - for (int i = 0; i < size-1; ++i) - assert(CGAL::squared_distance( v[i], v[i+1]) - 4.0 < 0.1 ); + std::cout << " Sorting points... " << std::flush; - std::cout << "OK." << std::endl; + cost.reset();cost.start(); + CGAL::hilbert_sort (v.begin(), v.end()); + cost.stop(); + + std::cout << "done in "< v; + v.reserve(size); + + CGAL::points_on_cube_grid_3 (box_size, (std::size_t)size, + std::back_inserter(v), Creator_3() ); + + std::cout << "done." << std::endl; + + std::cout << " Sorting points... " << std::flush; + + cost.reset();cost.start(); + CGAL::hilbert_sort (v.begin(), v.end()); + cost.stop(); + + std::cout << "done in "< v; + v.reserve (nb_points_3); + + CGAL::Random_points_in_cube_3 gen (1.0, random); + + for (int i = 0; i < nb_points_3 - 1; ++i) + v.push_back (*gen++); + v.push_back(v[0]); //insert twice the same point + + std::cout << "done." << std::endl; + + std::vector v2 (v); + + std::cout << " Sorting points... " << std::flush; + + cost.reset();cost.start(); + CGAL::hilbert_sort(v.begin(),v.end(),CGAL::Hilbert_sort_middle_policy()); + cost.stop(); + + std::cout << "done in "< v; + v.reserve(size); + + CGAL::points_on_cube_grid_3 (box_size, (std::size_t)size, + std::back_inserter(v), Creator_3() ); + + std::cout << "done." << std::endl; + + std::cout << " Sorting points... " << std::flush; + + cost.reset();cost.start(); + CGAL::hilbert_sort(v.begin(),v.end(),CGAL::Hilbert_sort_middle_policy()); + cost.stop(); + + std::cout << "done in "< v; - v.reserve (nb_points_2); + std::vector v; + v.reserve (nb_points_3); - CGAL::Random_points_in_square_2 gen (1.0, random); + CGAL::Random_points_on_sphere_3 gen (1.0, random); - for (int i = 0; i < nb_points_2 - 1; ++i) - v.push_back (*gen++); - v.push_back(v[0]); //insert twice the same point + for (int i = 0; i < nb_points_3 - 1; ++i) + v.push_back (*gen++); + v.push_back(v[0]); //insert twice the same point - std::cout << "done." << std::endl; + std::cout << "done." << std::endl; - std::vector v2 (v); + std::vector v2 (v); - std::cout << " Sorting points... " << std::flush; + std::cout << " Sorting points... " << std::flush; - cost.reset();cost.start(); - CGAL::hilbert_sort(v.begin(),v.end(), CGAL::Hilbert_sort_middle_policy()); - cost.stop(); + cost.reset();cost.start(); + CGAL::hilbert_sort(v.begin(),v.end()); + cost.stop(); - std::cout << "done in "< v; - v.reserve(size); + std::cout << "no points lost." << std::endl; + } + { + std::cout << "Testing Spherical (median policy) + given sphere: Generating "< v; + v.reserve (nb_points_3); - std::cout << "done." << std::endl; + CGAL::Random_points_on_sphere_3 gen (2.0, random); - std::cout << " Sorting points... " << std::flush; + for (int i = 0; i < nb_points_3 - 1; ++i) + v.push_back (*gen++ + Vector_3(3,5,5)); + v.push_back(v[0]); //insert twice the same point - cost.reset();cost.start(); - CGAL::hilbert_sort(v.begin(),v.end(), CGAL::Hilbert_sort_middle_policy()); - cost.stop(); + std::cout << "done." << std::endl; - std::cout << "done in "< v2 (v); - std::cout << " Checking... " << std::flush; + std::cout << " Sorting points... " << std::flush; - for (int i = 0; i < size-1; ++i) { - assert(CGAL::squared_distance( v[i], v[i+1]) - 4.0 < 0.1 ); - } - std::cout << "OK." << std::endl; - } + cost.reset();cost.start(); + CGAL::hilbert_sort_on_sphere(v.begin(),v.end(), 4, CGAL::ORIGIN + Vector_3(3,5,5)); + cost.stop(); - { - std::cout << "Testing 3D: Generating "< v; - v.reserve (nb_points_3); + std::cout << " Checking... " << std::flush; - CGAL::Random_points_in_cube_3 gen (1.0, random); + std::sort (v.begin(), v.end(), K().less_xyz_3_object()); + std::sort (v2.begin(), v2.end(), K().less_xyz_3_object()); + assert(v == v2); - for (int i = 0; i < nb_points_3 - 1; ++i) - v.push_back (*gen++); - v.push_back(v[0]); //insert twice the same point + std::cout << "no points lost." << std::endl; + } + { + std::cout << "Testing Spherical (middle policy): Generating "< v; + v.reserve (nb_points_3); - std::vector v2 (v); + CGAL::Random_points_on_sphere_3 gen (1.0, random); - std::cout << " Sorting points... " << std::flush; + for (int i = 0; i < nb_points_3 - 1; ++i) + v.push_back (*gen++); + v.push_back(v[0]); //insert twice the same point - cost.reset();cost.start(); - CGAL::hilbert_sort (v.begin(), v.end()); - cost.stop(); + std::cout << "done." << std::endl; - std::cout << "done in "< v2 (v); - std::cout << " Checking... " << std::flush; + std::cout << " Sorting points... " << std::flush; - std::sort (v.begin(), v.end(), K().less_xyz_3_object()); - std::sort (v2.begin(), v2.end(), K().less_xyz_3_object()); - assert(v == v2); + cost.reset();cost.start(); + CGAL::hilbert_sort_on_sphere(v.begin(),v.end(),CGAL::Hilbert_sort_middle_policy()); + cost.stop(); - std::cout << "no points lost." << std::endl; - } - { - int size=512; // 2^(xd) with x=3 d=3 - double box_size = 7.0; // 2^x -1 + std::cout << "done in "< v; - v.reserve(size); + std::sort (v.begin(), v.end(), K().less_xyz_3_object()); + std::sort (v2.begin(), v2.end(), K().less_xyz_3_object()); + assert(v == v2); - CGAL::points_on_cube_grid_3 (box_size, (std::size_t)size, - std::back_inserter(v), Creator_3() ); + std::cout << "no points lost." << std::endl; + } + { + std::cout << "Testing Spherical (middle policy) + given sphere: Generating "< v; + v.reserve (nb_points_3); - std::cout << " Sorting points... " << std::flush; + CGAL::Random_points_on_sphere_3 gen (2.0, random); - cost.reset();cost.start(); - CGAL::hilbert_sort (v.begin(), v.end()); - cost.stop(); + for (int i = 0; i < nb_points_3 - 1; ++i) + v.push_back (*gen++ + Vector_3(3,5,5)); + v.push_back(v[0]); //insert twice the same point - std::cout << "done in "< v2 (v); - for (int i = 0; i < size-1; ++i) - assert(CGAL::squared_distance( v[i], v[i+1]) - 4.0 < 0.1 ); + std::cout << " Sorting points... " << std::flush; - std::cout << "OK." << std::endl; - } + cost.reset();cost.start(); + CGAL::hilbert_sort_on_sphere(v.begin(),v.end(),CGAL::Hilbert_sort_middle_policy(), 4, CGAL::ORIGIN + Vector_3(3,5,5)); + cost.stop(); - { - std::cout << "Testing 3D (middle policy): Generating "< v; - v.reserve (nb_points_3); + std::cout << " Checking... " << std::flush; - CGAL::Random_points_in_cube_3 gen (1.0, random); + std::sort (v.begin(), v.end(), K().less_xyz_3_object()); + std::sort (v2.begin(), v2.end(), K().less_xyz_3_object()); + assert(v == v2); - for (int i = 0; i < nb_points_3 - 1; ++i) - v.push_back (*gen++); - v.push_back(v[0]); //insert twice the same point + std::cout << "no points lost." << std::endl; + } + { + int dim =5; + std::cout << "Testing "< v; + v.reserve (nb_points_d); - std::vector v2 (v); + CGAL::Random_points_in_cube_d gen (dim, 1.0, random); - std::cout << " Sorting points... " << std::flush; + for (int i = 0; i < nb_points_d - 1; ++i) + v.push_back (*gen++); + v.push_back(v[0]); //insert twice the same point - cost.reset();cost.start(); - CGAL::hilbert_sort(v.begin(),v.end(),CGAL::Hilbert_sort_middle_policy()); - cost.stop(); + std::cout << "done." << std::endl; - std::cout << "done in "< v2 (v); - std::cout << " Checking... " << std::flush; + std::cout << " Sorting points... " << std::flush; - std::sort (v.begin(), v.end(), K().less_xyz_3_object()); - std::sort (v2.begin(), v2.end(), K().less_xyz_3_object()); - assert(v == v2); + cost.reset();cost.start(); + CGAL::hilbert_sort (v.begin(), v.end(),CGAL::Hilbert_sort_median_policy()); + cost.stop(); - std::cout << "no points lost." << std::endl; - } - { - int size=4096; // 2^(xd) with x=4 d=3 - double box_size = 15.0; // 2^x -1 + std::cout << "done in "< v; - v.reserve(size); + std::sort (v.begin(), v.end(), Kd().less_lexicographically_d_object()); + std::sort (v2.begin(), v2.end(),Kd().less_lexicographically_d_object()); + assert(v == v2); - CGAL::points_on_cube_grid_3 (box_size, (std::size_t)size, - std::back_inserter(v), Creator_3() ); + std::cout << "no points lost." << std::endl; + } + { + int dim = 1000; + std::cout << "Testing "< v; + v.reserve (nb_points_d); - std::cout << " Sorting points... " << std::flush; + CGAL::Random_points_in_cube_d gen (dim, 1.0, random); - cost.reset();cost.start(); - CGAL::hilbert_sort(v.begin(),v.end(),CGAL::Hilbert_sort_middle_policy()); - cost.stop(); + for (int i = 0; i < nb_points_d - 1; ++i) + v.push_back (*gen++); + v.push_back(v[0]); //insert twice the same point - std::cout << "done in "< v2 (v); - for (int i = 0; i < size-1; ++i) { - assert(CGAL::squared_distance( v[i], v[i+1]) - 4.0 < 0.1 ); - } - std::cout << "OK." << std::endl; - } - { - std::cout << "Testing Spherical (median policy): Generating "< v; - v.reserve (nb_points_3); + cost.reset();cost.start(); + CGAL::hilbert_sort (v.begin(), v.end()); + cost.stop(); - CGAL::Random_points_on_sphere_3 gen (1.0, random); + std::cout << "done in "< v2 (v); + std::cout << "no points lost." << std::endl; + } + { + int dim = 10; + std::cout << "Testing "< v; + v.reserve (nb_points_d); - cost.reset();cost.start(); - CGAL::hilbert_sort(v.begin(),v.end()); - cost.stop(); + CGAL::Random_points_in_cube_d gen (dim, 1.0, random); - std::cout << "done in "< v2 (v); - std::cout << "no points lost." << std::endl; - } - { - std::cout << "Testing Spherical (median policy) + given sphere: Generating "< v; - v.reserve (nb_points_3); + cost.reset();cost.start(); + CGAL::hilbert_sort (v.begin(), v.end(), + CGAL::Hilbert_sort_middle_policy()); + cost.stop(); - CGAL::Random_points_on_sphere_3 gen (2.0, random); + std::cout << "done in "< v2 (v); + std::cout << "no points lost." << std::endl; + } + { + int dim=5; + std::cout << "Testing "< v; + v.reserve (nb_points_d); - cost.reset();cost.start(); - CGAL::hilbert_sort_on_sphere(v.begin(),v.end(), 4, CGAL::ORIGIN + Vector_3(3,5,5)); - cost.stop(); + CGAL::Random_points_in_cube_d gen (dim, 1.0, random); - std::cout << "done in "< v2 (v); - std::cout << "no points lost." << std::endl; - } - { - std::cout << "Testing Spherical (middle policy): Generating "< v; - v.reserve (nb_points_3); + cost.reset();cost.start(); + CGAL::hilbert_sort (v.begin(), v.end()); + cost.stop(); - CGAL::Random_points_on_sphere_3 gen (1.0, random); + std::cout << "done in "< v2 (v); + std::cout << "no points lost." << std::endl; + } + { + int dim=5; + int size=32768; // 2^(x.dim) with x=3 + double box_size = 7.0; // 2^x -1 - std::cout << " Sorting points... " << std::flush; + std::cout << "Testing "< v(size); - std::cout << "done in "< v; - v.reserve (nb_points_3); + std::cout << "done in "< gen (2.0, random); + std::cout << " Checking... " << std::flush; - for (int i = 0; i < nb_points_3 - 1; ++i) - v.push_back (*gen++ + Vector_3(3,5,5)); - v.push_back(v[0]); //insert twice the same point + for (int i = 0; i < size-1; ++i) + assert(CGAL::squared_distance( v[i], v[i+1]) - 4.0 < 0.1 ); - std::cout << "done." << std::endl; + std::cout << "OK." << std::endl; + } + { + int dim=3; + int size=32768; // 2^(x.dim) with x=5 + double box_size = 31.0; // 2^x -1 - std::vector v2 (v); + std::cout << "Testing "< v(size); - cost.reset();cost.start(); - CGAL::hilbert_sort_on_sphere(v.begin(),v.end(),CGAL::Hilbert_sort_middle_policy(), 4, CGAL::ORIGIN + Vector_3(3,5,5)); - cost.stop(); + CGAL::points_on_cube_grid_d (dim, box_size, (std::size_t)size, + v.begin(), Creator_d(dim) ); - std::cout << "done in "< v; - v.reserve (nb_points_d); + std::cout << " Checking... " << std::flush; - CGAL::Random_points_in_cube_d gen (dim, 1.0, random); + for (int i = 0; i < size-1; ++i) + assert(CGAL::squared_distance( v[i], v[i+1]) - 4.0 < 0.1 ); - for (int i = 0; i < nb_points_d - 1; ++i) - v.push_back (*gen++); - v.push_back(v[0]); //insert twice the same point + std::cout << "OK." << std::endl; + } - std::cout << "done." << std::endl; + { + int dim=5; + int size=32768; // 2^(x.dim) with x=3 + double box_size = 7.0; // 2^x -1 - std::vector v2 (v); + std::cout << "Testing "< v(size); - cost.reset();cost.start(); - CGAL::hilbert_sort (v.begin(), v.end(),CGAL::Hilbert_sort_median_policy()); - cost.stop(); + CGAL::points_on_cube_grid_d (dim, box_size, (std::size_t)size, + v.begin(), Creator_d(dim) ); - std::cout << "done in "< v; - v.reserve (nb_points_d); + std::cout << " Checking... " << std::flush; - CGAL::Random_points_in_cube_d gen (dim, 1.0, random); + for (int i = 0; i < size-1; ++i) + assert(CGAL::squared_distance( v[i], v[i+1]) - 4.0 < 0.1 ); - for (int i = 0; i < nb_points_d - 1; ++i) - v.push_back (*gen++); - v.push_back(v[0]); //insert twice the same point + std::cout << "OK." << std::endl; + } - std::cout << "done." << std::endl; + { + int dim = 50; + std::cout << "Testing "< v2 (v); + std::vector v; + v.reserve (nb_points_d); - std::cout << " Sorting points... " << std::flush; + CGAL::Random_points_in_cube_d gen (dim, 1.0, random); - cost.reset();cost.start(); - CGAL::hilbert_sort (v.begin(), v.end()); - cost.stop(); + for (int i = 0; i < nb_points_d - 1; ++i) + v.push_back (*gen++); + v.push_back(v[0]); //insert twice the same point - std::cout << "done in "< v2 (v); - std::sort (v.begin(), v.end(), Kd().less_lexicographically_d_object()); - std::sort (v2.begin(), v2.end(),Kd().less_lexicographically_d_object()); - assert(v == v2); + std::cout << " Sorting points... " << std::flush; - std::cout << "no points lost." << std::endl; - } - { - int dim = 10; - std::cout << "Testing "< v; - v.reserve (nb_points_d); + std::cout << "done in "< gen (dim, 1.0, random); + std::cout << " Checking... " << std::flush; - for (int i = 0; i < nb_points_d - 1; ++i) - v.push_back (*gen++); - v.push_back(v[0]); //insert twice the same point + std::sort (v.begin(), v.end(), Kd().less_lexicographically_d_object()); + std::sort (v2.begin(), v2.end(),Kd().less_lexicographically_d_object()); + assert(v == v2); - std::cout << "done." << std::endl; + std::cout << "no points lost." << std::endl; + } - std::vector v2 (v); - - std::cout << " Sorting points ... " << std::flush; - - cost.reset();cost.start(); - CGAL::hilbert_sort (v.begin(), v.end(), - CGAL::Hilbert_sort_middle_policy()); - cost.stop(); - - std::cout << "done in "< v; - v.reserve (nb_points_d); - - CGAL::Random_points_in_cube_d gen (dim, 1.0, random); - - for (int i = 0; i < nb_points_d - 1; ++i) - v.push_back (*gen++); - v.push_back(v[0]); //insert twice the same point - - std::cout << "done." << std::endl; - - std::vector v2 (v); - - std::cout << " Sorting points... " << std::flush; - - cost.reset();cost.start(); - CGAL::hilbert_sort (v.begin(), v.end()); - cost.stop(); - - std::cout << "done in "< v(size); - - CGAL::points_on_cube_grid_d (dim, box_size, (std::size_t)size, - v.begin(), Creator_d(dim) ); - - std::cout << "done." << std::endl; - - std::cout << " Sorting points... " << std::flush; - - cost.reset();cost.start(); - CGAL::hilbert_sort (v.begin(), v.begin()+size); - cost.stop(); - - std::cout << "done in "< v(size); - - CGAL::points_on_cube_grid_d (dim, box_size, (std::size_t)size, - v.begin(), Creator_d(dim) ); - - std::cout << "done." << std::endl; - - std::cout << " Sorting points... " << std::flush; - - cost.reset();cost.start(); - CGAL::hilbert_sort (v.begin(), v.begin()+size, - CGAL::Hilbert_sort_middle_policy()); - cost.stop(); - - std::cout << "done in "< v(size); - - CGAL::points_on_cube_grid_d (dim, box_size, (std::size_t)size, - v.begin(), Creator_d(dim) ); - - std::cout << "done." << std::endl; - - std::cout << " Sorting points... " << std::flush; - - cost.reset();cost.start(); - CGAL::hilbert_sort (v.begin(), v.begin()+size, - CGAL::Hilbert_sort_middle_policy()); - cost.stop(); - - std::cout << "done in "< v; - v.reserve (nb_points_d); - - CGAL::Random_points_in_cube_d gen (dim, 1.0, random); - - for (int i = 0; i < nb_points_d - 1; ++i) - v.push_back (*gen++); - v.push_back(v[0]); //insert twice the same point - - std::cout << "done." << std::endl; - - std::vector v2 (v); - - std::cout << " Sorting points... " << std::flush; - - cost.reset();cost.start(); - CGAL::hilbert_sort (v.begin(), v.end()); - cost.stop(); - - std::cout << "done in "< sort." << std::endl; + std::cout << "Testing Multiscale sort." << std::endl; - { - std::cout << "Testing 2D: Generating points... " << std::flush; + { + std::cout << "Testing 2D: Generating points... " << std::flush; - std::vector v; - v.reserve (nb_points_2); + std::vector v; + v.reserve (nb_points_2); - CGAL::Random_points_in_square_2 gen (1.0, random); + CGAL::Random_points_in_square_2 gen (1.0, random); - for (int i = 0; i < nb_points_2; ++i) - v.push_back (*gen++); + for (int i = 0; i < nb_points_2; ++i) + v.push_back (*gen++); - std::cout << "done." << std::endl; + std::cout << "done." << std::endl; - std::vector v2 (v); + std::vector v2 (v); - std::cout << " Sorting points... " << std::flush; + std::cout << " Sorting points... " << std::flush; - CGAL::spatial_sort (v.begin(), v.end()); + CGAL::spatial_sort (v.begin(), v.end()); - std::cout << "done." << std::endl; + std::cout << "done." << std::endl; - std::cout << " Checking... " << std::flush; + std::cout << " Checking... " << std::flush; - std::sort (v.begin(), v.end(), K().less_xy_2_object()); - std::sort (v2.begin(), v2.end(), K().less_xy_2_object()); - assert(v == v2); + std::sort (v.begin(), v.end(), K().less_xy_2_object()); + std::sort (v2.begin(), v2.end(), K().less_xy_2_object()); + assert(v == v2); - std::cout << "no points lost." << std::endl; - } + std::cout << "no points lost." << std::endl; + } - { - std::cout << "Testing 3D: Generating points... " << std::flush; + { + std::cout << "Testing 3D: Generating points... " << std::flush; - std::vector v; - v.reserve (nb_points_3); + std::vector v; + v.reserve (nb_points_3); - CGAL::Random_points_in_cube_3 gen (1.0, random); + CGAL::Random_points_in_cube_3 gen (1.0, random); - for (int i = 0; i < nb_points_3; ++i) - v.push_back (*gen++); + for (int i = 0; i < nb_points_3; ++i) + v.push_back (*gen++); - std::cout << "done." << std::endl; + std::cout << "done." << std::endl; - std::vector v2 (v); + std::vector v2 (v); - std::cout << " Sorting points... " << std::flush; + std::cout << " Sorting points... " << std::flush; - CGAL::spatial_sort (v.begin(), v.end()); + CGAL::spatial_sort (v.begin(), v.end()); - std::cout << "done." << std::endl; + std::cout << "done." << std::endl; - std::cout << " Checking... " << std::flush; + std::cout << " Checking... " << std::flush; - std::sort (v.begin(), v.end(), K().less_xyz_3_object()); - std::sort (v2.begin(), v2.end(), K().less_xyz_3_object()); - assert(v == v2); + std::sort (v.begin(), v.end(), K().less_xyz_3_object()); + std::sort (v2.begin(), v2.end(), K().less_xyz_3_object()); + assert(v == v2); - std::cout << "no points lost." << std::endl; - } + std::cout << "no points lost." << std::endl; + } - { - std::cout << "Testing Spherical: Generating points... " << std::flush; + { + std::cout << "Testing Spherical: Generating points... " << std::flush; - std::vector v; - v.reserve (nb_points_3); + std::vector v; + v.reserve (nb_points_3); - CGAL::Random_points_on_sphere_3 gen (1.0, random); + CGAL::Random_points_on_sphere_3 gen (1.0, random); - for (int i = 0; i < nb_points_3; ++i) - v.push_back (*gen++); + for (int i = 0; i < nb_points_3; ++i) + v.push_back (*gen++); - std::cout << "done." << std::endl; + std::cout << "done." << std::endl; - std::vector v2 (v); + std::vector v2 (v); - std::cout << " Sorting points... " << std::flush; + std::cout << " Sorting points... " << std::flush; - CGAL::spatial_sort_on_sphere (v.begin(), v.end()); + CGAL::spatial_sort_on_sphere (v.begin(), v.end()); - std::cout << "done." << std::endl; + std::cout << "done." << std::endl; - std::cout << " Checking... " << std::flush; + std::cout << " Checking... " << std::flush; - std::sort (v.begin(), v.end(), K().less_xyz_3_object()); - std::sort (v2.begin(), v2.end(), K().less_xyz_3_object()); - assert(v == v2); + std::sort (v.begin(), v.end(), K().less_xyz_3_object()); + std::sort (v2.begin(), v2.end(), K().less_xyz_3_object()); + assert(v == v2); - std::cout << "no points lost." << std::endl; - } + std::cout << "no points lost." << std::endl; + } - { - std::cout << "Testing Spherical + given sphere: Generating points... " << std::flush; + { + std::cout << "Testing Spherical + given sphere: Generating points... " << std::flush; - std::vector v; - v.reserve (nb_points_3); + std::vector v; + v.reserve (nb_points_3); - CGAL::Random_points_on_sphere_3 gen (3.0, random); + CGAL::Random_points_on_sphere_3 gen (3.0, random); - for (int i = 0; i < nb_points_3; ++i) - v.push_back (*gen++ + Vector_3(10,10,3)); + for (int i = 0; i < nb_points_3; ++i) + v.push_back (*gen++ + Vector_3(10,10,3)); - std::cout << "done." << std::endl; + std::cout << "done." << std::endl; - std::vector v2 (v); + std::vector v2 (v); - std::cout << " Sorting points... " << std::flush; + std::cout << " Sorting points... " << std::flush; - CGAL::spatial_sort_on_sphere (v.begin(), v.end(), 9, Point_3(10,10,3)); + CGAL::spatial_sort_on_sphere (v.begin(), v.end(), 9, Point_3(10,10,3)); - std::cout << "done." << std::endl; + std::cout << "done." << std::endl; - std::cout << " Checking... " << std::flush; + std::cout << " Checking... " << std::flush; - std::sort (v.begin(), v.end(), K().less_xyz_3_object()); - std::sort (v2.begin(), v2.end(), K().less_xyz_3_object()); - assert(v == v2); + std::sort (v.begin(), v.end(), K().less_xyz_3_object()); + std::sort (v2.begin(), v2.end(), K().less_xyz_3_object()); + assert(v == v2); - std::cout << "no points lost." << std::endl; - } + std::cout << "no points lost." << std::endl; + } - { - int dim=5; - std::cout << "Testing "< v; - v.reserve (nb_points_d); + std::vector v; + v.reserve (nb_points_d); - CGAL::Random_points_in_cube_d gen (dim, 1.0, random); + CGAL::Random_points_in_cube_d gen (dim, 1.0, random); - for (int i = 0; i < nb_points_d; ++i) - v.push_back (*gen++); + for (int i = 0; i < nb_points_d; ++i) + v.push_back (*gen++); - std::cout << "done." << std::endl; + std::cout << "done." << std::endl; - std::vector v2 (v); + std::vector v2 (v); - std::cout << " Sorting points... " << std::flush; + std::cout << " Sorting points... " << std::flush; - CGAL::spatial_sort (v.begin(), v.end()); + CGAL::spatial_sort (v.begin(), v.end()); - std::cout << "done." << std::endl; + std::cout << "done." << std::endl; - std::cout << " Checking... " << std::flush; + std::cout << " Checking... " << std::flush; - std::sort (v.begin(), v.end(), Kd().less_lexicographically_d_object()); - std::sort (v2.begin(), v2.end(),Kd().less_lexicographically_d_object()); - assert(v == v2); + std::sort (v.begin(), v.end(), Kd().less_lexicographically_d_object()); + std::sort (v2.begin(), v2.end(),Kd().less_lexicographically_d_object()); + assert(v == v2); - std::cout << "no points lost." << std::endl; - } + std::cout << "no points lost." << std::endl; + } - return 0; + return 0; } From 8765e05dc88e6c43c155bf1812d4e6be23342b63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 2 Jan 2020 11:17:02 +0100 Subject: [PATCH 114/185] Test that the parallel sorting gives the same result as the sequential --- .../include/CGAL/Hilbert_sort_median_2.h | 1 + .../test/Spatial_sorting/CMakeLists.txt | 14 +++--- .../test/Spatial_sorting/test_hilbert.cpp | 44 +++++++++++++------ 3 files changed, 39 insertions(+), 20 deletions(-) diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h b/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h index 330bea5e374..3c0d5cdbc10 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h @@ -12,6 +12,7 @@ #ifndef CGAL_HILBERT_SORT_MEDIAN_2_H #define CGAL_HILBERT_SORT_MEDIAN_2_H +#include #include #include #include diff --git a/Spatial_sorting/test/Spatial_sorting/CMakeLists.txt b/Spatial_sorting/test/Spatial_sorting/CMakeLists.txt index c8901de1414..e7261976569 100644 --- a/Spatial_sorting/test/Spatial_sorting/CMakeLists.txt +++ b/Spatial_sorting/test/Spatial_sorting/CMakeLists.txt @@ -5,16 +5,18 @@ cmake_minimum_required(VERSION 3.1...3.15) project( Spatial_sorting_Tests ) - find_package(CGAL QUIET) if ( CGAL_FOUND ) - # create a target per cppfile - file(GLOB cppfiles RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) - foreach(cppfile ${cppfiles}) - create_single_source_cgal_program( "${cppfile}" ) - endforeach() + create_single_source_cgal_program( "test_hilbert.cpp" ) + create_single_source_cgal_program( "test_multiscale.cpp" ) + + find_package (TBB QUIET) + if( TBB_FOUND ) + include( CGAL_target_use_TBB ) + CGAL_target_use_TBB( test_hilbert ) + endif( TBB_FOUND ) else() diff --git a/Spatial_sorting/test/Spatial_sorting/test_hilbert.cpp b/Spatial_sorting/test/Spatial_sorting/test_hilbert.cpp index 269504b0451..bc33af3e569 100644 --- a/Spatial_sorting/test/Spatial_sorting/test_hilbert.cpp +++ b/Spatial_sorting/test/Spatial_sorting/test_hilbert.cpp @@ -40,7 +40,7 @@ int main () std::cout << "Testing Hilbert sort." << std::endl; { - std::cout << "Testing 2D: Generating "< v; v.reserve (nb_points_2); @@ -63,18 +63,23 @@ int main () std::cout << "done in "<(v2.begin(), v2.end()); + cost.stop(); + + std::cout << "done in " << cost.time() << "seconds." << std::endl; + + std::cout << " Checking... " << std::flush; assert(v == v2); - std::cout << "no points lost." << std::endl; + std::cout << "Ok" << std::endl; } { int size=256; // 2^(xd) with x=4 d=2 double box_size = 15.0; // 2^x -1 - std::cout << "Testing 2D: Generating "< v; v.reserve(size); @@ -161,7 +166,7 @@ int main () } { - std::cout << "Testing 3D: Generating "< v; v.reserve (nb_points_3); @@ -184,10 +189,15 @@ int main () std::cout << "done in "<(v2.begin(), v2.end()); + cost.stop(); + + std::cout << "done in " << cost.time() << "seconds." << std::endl; + + std::cout << " Checking... " << std::flush; assert(v == v2); std::cout << "no points lost." << std::endl; @@ -196,7 +206,7 @@ int main () int size=512; // 2^(xd) with x=3 d=3 double box_size = 7.0; // 2^x -1 - std::cout << "Testing 3D: Generating "< v; v.reserve(size); @@ -281,6 +291,7 @@ int main () for (int i = 0; i < size-1; ++i) { assert(CGAL::squared_distance( v[i], v[i+1]) - 4.0 < 0.1 ); } + std::cout << "OK." << std::endl; } { @@ -307,10 +318,15 @@ int main () std::cout << "done in "<(v2.begin(), v2.end()); + cost.stop(); + + std::cout << "done in " << cost.time() << "seconds." << std::endl; + + std::cout << " Checking... " << std::flush; assert(v == v2); std::cout << "no points lost." << std::endl; From e221c6083d3a2e0ccbf26526ae161f81eef53f8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 2 Jan 2020 13:28:58 +0100 Subject: [PATCH 115/185] Fix missing 'typedefs' --- .../doc/Spatial_sorting/CGAL/Spatial_sort_traits_adapter_3.h | 4 ++-- .../doc/Spatial_sorting/CGAL/Spatial_sort_traits_adapter_d.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/Spatial_sort_traits_adapter_3.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/Spatial_sort_traits_adapter_3.h index 1ed457ea225..8e4e0e5c419 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/Spatial_sort_traits_adapter_3.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/Spatial_sort_traits_adapter_3.h @@ -25,8 +25,8 @@ public: /*! -*/ -boost::property_traits::key_type Point_3; +*/ +typedef boost::property_traits::key_type Point_3; /// @} diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/Spatial_sort_traits_adapter_d.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/Spatial_sort_traits_adapter_d.h index c6f00b5c5aa..d3ef4083476 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/Spatial_sort_traits_adapter_d.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/Spatial_sort_traits_adapter_d.h @@ -26,7 +26,7 @@ public: /*! */ -boost::property_traits::key_type Point_d; +typedef boost::property_traits::key_type Point_d; /// @} From 1ff41a4370a23a5a95058e260305d34147b80269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 2 Jan 2020 13:30:00 +0100 Subject: [PATCH 116/185] Change template name such that it isn't a concept's name --- .../doc/Spatial_sorting/CGAL/Hilbert_sort_2.h | 5 ++-- .../doc/Spatial_sorting/CGAL/Hilbert_sort_3.h | 5 ++-- .../doc/Spatial_sorting/CGAL/Hilbert_sort_d.h | 5 ++-- .../CGAL/Hilbert_sort_on_sphere_3.h | 5 ++-- .../Spatial_sorting/CGAL/Multiscale_sort.h | 9 +++---- .../doc/Spatial_sorting/CGAL/hilbert_sort.h | 23 +++++++++--------- .../CGAL/hilbert_sort_on_sphere.h | 14 +++++------ .../doc/Spatial_sorting/CGAL/spatial_sort.h | 24 +++++++++---------- .../CGAL/spatial_sort_on_sphere.h | 20 ++++++++-------- 9 files changed, 57 insertions(+), 53 deletions(-) diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_2.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_2.h index 5f5b006e003..1311943f09c 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_2.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_2.h @@ -35,9 +35,10 @@ Hilbert_sort_2(const Traits &traits = Traits()); /*! It sorts the range `[begin, end)`. -\tparam RandomAccessIterator must be an iterator with value type `Traits::Point_2`. +\tparam InputPointIterator must be a model of `RandomAccessIterator` with value type `Traits::Point_2`. */ -template void operator() (RandomAccessIterator begin, RandomAccessIterator end) const; +template +void operator() (InputPointIterator begin, InputPointIterator end) const; /// @} diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_3.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_3.h index bb366239adc..9db7dcf6b53 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_3.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_3.h @@ -33,9 +33,10 @@ Hilbert_sort_3(const Traits &traits = Traits()); /*! It sorts the range `[begin, end)`. -\tparam RandomAccessIterator must be an iterator with value type `Traits::Point_3`. +\tparam InputPointIterator must be a model of `RandomAccessIterator` with value type `Traits::Point_3`. */ -template void operator() (RandomAccessIterator begin, RandomAccessIterator end) const; +template +void operator() (InputPointIterator begin, InputPointIterator end) const; /// @} diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_d.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_d.h index 5974f4cca65..0a09b9d6962 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_d.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_d.h @@ -29,9 +29,10 @@ Hilbert_sort_d(const Traits &traits = Traits()); /*! It sorts the range `[begin, end)`. -\tparam RandomAccessIterator must be an iteratoe with value type `Traits::Point_d`. +\tparam InputPointIterator must be a model of `RandomAccessIterator` with value type `Traits::Point_d`. */ -template void operator() (RandomAccessIterator begin, RandomAccessIterator end) const; +template +void operator() (InputPointIterator begin, InputPointIterator end) const; /// @} diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_on_sphere_3.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_on_sphere_3.h index 773753b749c..d6ea474fd39 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_on_sphere_3.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_on_sphere_3.h @@ -37,9 +37,10 @@ Hilbert_sort_on_sphere_3(const Traits &traits = Traits(), /*! It sorts the range `[begin, end)` along a hilbert curve on the sphere centered at `p` with squared radius `sq_r`; these arguments are passed in the construction of the object `Hilbert_sort_on_sphere_3`. -\tparam RandomAccessIterator must be an iterator with value type `Traits::Point_3`. +\tparam InputPointIterator must be a model of `RandomAccessIterator` with value type `Traits::Point_3`. */ -template void operator() (RandomAccessIterator begin, RandomAccessIterator end) const; +template +void operator() (InputPointIterator begin, InputPointIterator end) const; /// @} diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/Multiscale_sort.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/Multiscale_sort.h index a3c2cea1fc0..59ed9a347ce 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/Multiscale_sort.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/Multiscale_sort.h @@ -30,10 +30,11 @@ Multiscale_sort (const Sort &sort = Sort(), std::ptrdiff_t threshold = 1, double /// @{ /*! -It sorts the range `[begin, end)`. -`Sort::operator()(RandomAccessIterator begin, RandomAccessIterator end)` must be defined. -*/ -template void operator() (RandomAccessIterator begin, RandomAccessIterator end) const; +sorts the range `[begin, end)`. +`Sort::operator()(InputIterator begin, InputIterator end)` must be defined. +*/ +template +void operator() (InputIterator begin, InputIterator end) const; /// @} diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h index a6d77e5cf80..5703b56199e 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h @@ -8,21 +8,20 @@ along a Hilbert curve. It sorts the range `[begin, end)` in place. -\tparam ConcurrencyTag must be `Sequential_tag`, `Parallel_tag`, or `Parallel_if_available_tag`. -With parallelism and TBB enabled, the sorting will be -done using up to four threads in 2D, and up to eight threads in 3D with the median policy. +\tparam ConcurrencyTag enables sequential versus parallel algorithm. +Possible values are `Sequential_tag`, `Parallel_tag`, and `Parallel_if_available_tag`. +With parallelism enabled, sorting will be performed using up to four threads in 2D, +and up to eight threads in 3D. +Parallel sorting is available only when the median strategy policy (the default policy) is used. -\tparam RandomAccessIterator -`std::iterator_traits::%value_type` must be convertible to +\tparam InputPointIterator must be a model of `RandomAccessIterator` and +`std::iterator_traits::%value_type` must be convertible to `Traits::Point_2`, `Traits::Point_3`, or `Traits::Point_d`. \tparam Traits must be a model for concept `SpatialSortingTraits_2`, `SpatialSortingTraits_3`, or `SpatialSortingTraits_d`. The default traits class `Default_traits` is the kernel in which the type -`std::iterator_traits::%value_type` is defined. - -\tparam PolicyTag The default policy is `Hilbert_sort_median_policy()` and the -other option is `Hilbert_sort_middle_policy()`. +`std::iterator_traits::%value_type` is defined. \cgalHeading{Implementation} @@ -34,10 +33,10 @@ Creates an instance of and calls its `operator()`. */ -template +template void -hilbert_sort( RandomAccessIterator begin, - RandomAccessIterator end, +hilbert_sort( InputPointIterator begin, + InputPointIterator end, const Traits& traits = Default_traits, PolicyTag policy = Default_policy); diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort_on_sphere.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort_on_sphere.h index 7da9fab177f..f488ff62b12 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort_on_sphere.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort_on_sphere.h @@ -35,14 +35,14 @@ Creates an instance of `Hilbert_sort_on_sphere`, and calls its `operator()`. */ -template +template void -hilbert_sort_on_sphere( RandomAccessIterator begin, -RandomAccessIterator end, -const Traits& traits = Default_traits, -PolicyTag policy = Default_policy, -double sqr_radius = 1.0, -const Traits::Point_3 ¢er = Default_center); +hilbert_sort_on_sphere( InputPointIterator begin, + InputPointIterator end, + const Traits& traits = Default_traits, + PolicyTag policy = Default_policy, + double sqr_radius = 1.0, + const Traits::Point_3 ¢er = Default_center); } /* namespace CGAL */ diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h index a2d7aabe8bf..e285025a210 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h @@ -14,20 +14,20 @@ It sorts the range `[begin, end)` in place. With parallelism and TBB enabled, the sorting will be done using up to four threads in 2D, and up to eight threads in 3D with the median policy. -\tparam RandomAccessIterator `std::iterator_traits::%value_type` must be convertible to -`Traits::Point_2`, `Traits::Point_3`, or `Traits::Point_d`. +\tparam InputPointIterator must be a model of `RandomAccessIterator` and +`std::iterator_traits::%value_type` must be convertible to +`Traits::Point_2`, `Traits::Point_3`, or `Traits::Point_d`. \tparam Traits must be a model for concept `SpatialSortingTraits_2`, `SpatialSortingTraits_3`, or `SpatialSortingTraits_d`. The default traits class `Default_traits` is the kernel in which the type -`std::iterator_traits::%value_type` is defined. +`std::iterator_traits::%value_type` is defined. \tparam PolicyTag The default policy is `Hilbert_sort_median_policy` and the other option is `Hilbert_sort_middle_policy`. The default values for the thresholds and the ratio depend on the dimension. - \cgalHeading{Implementation} Creates an instance of `Multiscale_sort` @@ -45,15 +45,15 @@ times the original size of the set, Hilbert sort is applied on the second subset. */ -template +template void -spatial_sort( RandomAccessIterator begin, -RandomAccessIterator end, -const Traits& traits = Default_traits, -PolicyTag policy = Default_policy, -std::ptrdiff_t threshold_hilbert=default, -std::ptrdiff_t threshold_multiscale=default, -double ratio=default); +spatial_sort( InputPointIterator begin, + InputPointIterator end, + const Traits& traits = Default_traits, + PolicyTag policy = Default_policy, + std::ptrdiff_t threshold_hilbert=default, + std::ptrdiff_t threshold_multiscale=default, + double ratio=default); } /* namespace CGAL */ diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort_on_sphere.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort_on_sphere.h index aa0ae22b797..7cf427da1f7 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort_on_sphere.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort_on_sphere.h @@ -54,17 +54,17 @@ times the original size of the set, `Hilbert_sort_on_sphere_3` functor is applie second subset. */ -template +template void -spatial_sort_on_sphere( RandomAccessIterator begin, -RandomAccessIterator end, -const Traits& traits = Default_traits, -PolicyTag policy = Default_policy, -double sqr_radius = 1.0, -const Traits::Point_3 ¢er = Default_center, -std::ptrdiff_t threshold_hilbert=default, -std::ptrdiff_t threshold_multiscale=default, -double ratio=default); +spatial_sort_on_sphere( InputPointIterator begin, + InputPointIterator end, + const Traits& traits = Default_traits, + PolicyTag policy = Default_policy, + double sqr_radius = 1.0, + const Traits::Point_3& center = Default_center, + std::ptrdiff_t threshold_hilbert=default, + std::ptrdiff_t threshold_multiscale=default, + double ratio=default); } /* namespace CGAL */ From ca098f58bf21988767ae8a9ac4e4dd9828b1f1ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 2 Jan 2020 13:32:09 +0100 Subject: [PATCH 117/185] Fix links to Median/Middle policies --- .../CGAL/Hilbert_policy_tags.h | 116 +++++++----------- .../doc/Spatial_sorting/CGAL/Hilbert_sort_2.h | 4 +- .../doc/Spatial_sorting/CGAL/Hilbert_sort_3.h | 4 +- .../doc/Spatial_sorting/CGAL/Hilbert_sort_d.h | 4 + .../CGAL/Hilbert_sort_on_sphere_3.h | 4 + .../doc/Spatial_sorting/CGAL/hilbert_sort.h | 3 + .../CGAL/hilbert_sort_on_sphere.h | 5 +- .../doc/Spatial_sorting/CGAL/spatial_sort.h | 5 +- 8 files changed, 64 insertions(+), 81 deletions(-) diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_policy_tags.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_policy_tags.h index bf27d940310..45293faa567 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_policy_tags.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_policy_tags.h @@ -4,12 +4,46 @@ namespace CGAL { /*! \ingroup PkgSpatialSortingUtils +`Median` is a tag class. It can be used to parameterize a strategy policy +in order to specify the strategy for spatial sorting. +`Hilbert_policy` can be passed to +as parameter to `hilbert_sort()` to choose the sorting policy. + +\cgalModels `DefaultConstructible` +\cgalModels `CopyConstructible` + +\sa `Middle` +\sa `Hilbert_policy` +\sa `Hilbert_sort_median_policy` +\sa `Hilbert_sort_middle_policy` +*/ +struct Median { }; + +/*! +\ingroup PkgSpatialSortingUtils + +`Middle` is a tag class. It can be used to parameterize a strategy policy +in order to specify the strategy for spatial sorting. +`Hilbert_policy` can be passed to +as parameter to `hilbert_sort()` to choose the sorting policy. + +\cgalModels `DefaultConstructible` +\cgalModels `CopyConstructible` + +\sa `Median` +\sa `Hilbert_policy` +\sa `Hilbert_sort_median_policy` +\sa `Hilbert_sort_middle_policy` +*/ +struct Middle { }; + +/*! +\ingroup PkgSpatialSortingUtils + `Hilbert_policy` is a policy class which can be used to parameterize a strategy policy in order to specify the strategy for spatial sorting. -`Hilbert_policy` or `Hilbert_policy` -can be passed as parameter to -`hilbert_sort()` to choose the sorting policy. - +`Hilbert_policy` or `Hilbert_policy` +can be passed as parameter to `hilbert_sort()` to choose the sorting policy. \tparam Tag must be either `Median` or `Middle`. @@ -20,90 +54,22 @@ can be passed as parameter to \sa `Middle` \sa `Hilbert_sort_median_policy` \sa `Hilbert_sort_middle_policy` - */ template< typename Tag > -struct Hilbert_policy { - - - -}; /* end Hilbert_policy */ -} /* end namespace CGAL */ - -namespace CGAL { +struct Hilbert_policy { }; /*! \ingroup PkgSpatialSortingUtils A typedef to `Hilbert_policy`. - */ - - typedef Hilbert_policy Hilbert_sort_median_policy; -} /* end namespace CGAL */ - -namespace CGAL { +typedef Hilbert_policy Hilbert_sort_median_policy; /*! \ingroup PkgSpatialSortingUtils A typedef to `Hilbert_policy`. - */ +typedef Hilbert_policy Hilbert_sort_middle_policy; - typedef Hilbert_policy Hilbert_sort_middle_policy; -} /* end namespace CGAL */ - -namespace CGAL { - -/*! -\ingroup PkgSpatialSortingUtils - -`Median` is a tag class. It can be used to parameterize a strategy policy -in order to specify the strategy for spatial sorting. -`Hilbert_policy` can be passed to -as parameter to -`hilbert_sort` to choose the sorting policy. - -\cgalModels `DefaultConstructible` -\cgalModels `CopyConstructible` - -\sa `Middle` -\sa `Hilbert_policy` -\sa `Hilbert_sort_median_policy` -\sa `Hilbert_sort_middle_policy` - -*/ - -struct Median { - - -}; /* end Median */ -} /* end namespace CGAL */ - -namespace CGAL { - -/*! -\ingroup PkgSpatialSortingUtils - -`Middle` is a tag class. It can be used to parameterize a strategy policy -in order to specify the strategy for spatial sorting. -`Hilbert_policy` can be passed to -as parameter to -`hilbert_sort` to choose the sorting policy. - -\cgalModels `DefaultConstructible` -\cgalModels `CopyConstructible` - -\sa `Median` -\sa `Hilbert_policy` -\sa `Hilbert_sort_median_policy` -\sa `Hilbert_sort_middle_policy` - -*/ - -struct Middle { - - -}; /* end Middle */ } /* end namespace CGAL */ diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_2.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_2.h index 1311943f09c..f3195c7954b 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_2.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_2.h @@ -11,7 +11,9 @@ or the middle depending on the `PolicyTag`. \tparam Traits must be a model of the concept `SpatialSortingTraits_2`. -\tparam PolicyTag must be `Hilbert_sort_median_policy` or `Hilbert_sort_middle_policy`. +\tparam PolicyTag is used to specify the strategy policy. +Possible values are \link CGAL::Hilbert_sort_median_policy `Hilbert_sort_median_policy` \endlink +(the default policy) or \link CGAL::Hilbert_sort_middle_policy `Hilbert_sort_middle_policy` \endlink. \tparam ConcurrencyTag must be `Sequential_tag`, `Parallel_tag`, or `Parallel_if_available_tag. With parallelism and TBB enabled, for the median policy up to four threads are used in parallel. diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_3.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_3.h index 9db7dcf6b53..83c71cbcbeb 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_3.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_3.h @@ -9,7 +9,9 @@ or the middle depending on the `PolicyTag`. \tparam Traits must be a model of the concept `SpatialSortingTraits_3`. -\tparam PolicyTag must be `Hilbert_sort_median_policy` or `Hilbert_sort_middle_policy`. +\tparam PolicyTag is used to specify the strategy policy. +Possible values are \link CGAL::Hilbert_sort_median_policy `Hilbert_sort_median_policy` \endlink +(the default policy) or \link CGAL::Hilbert_sort_middle_policy `Hilbert_sort_middle_policy` \endlink. \tparam ConcurrencyTag must be `Sequential_tag`,`Parallel_tag`, or `Parallel_if_available_tag`. With parallelism and TBB enabled, for the median policy up to eight threads are used in parallel. diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_d.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_d.h index 0a09b9d6962..5e5b5b11e24 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_d.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_d.h @@ -9,6 +9,10 @@ or the middle depending on the `PolicyTag`. \tparam Traits must be a model for `SpatialSortingTraits_d`. +\tparam PolicyTag is used to specify the strategy policy. +Possible values are \link CGAL::Hilbert_sort_median_policy `Hilbert_sort_median_policy` \endlink +(the default policy) or \link CGAL::Hilbert_sort_middle_policy `Hilbert_sort_middle_policy` \endlink. + */ template< typename Traits, typename PolicyTag > class Hilbert_sort_d { diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_on_sphere_3.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_on_sphere_3.h index d6ea474fd39..cfc2b40d19d 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_on_sphere_3.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_on_sphere_3.h @@ -12,6 +12,10 @@ If input points are not close to the input sphere, this function still works, bu \tparam Traits must be a model for `SpatialSortingTraits_3`. +\tparam PolicyTag is used to specify the strategy policy. +Possible values are \link CGAL::Hilbert_sort_median_policy `Hilbert_sort_median_policy` \endlink +(the default policy) or \link CGAL::Hilbert_sort_middle_policy `Hilbert_sort_middle_policy` \endlink. + */ template< typename Traits, typename PolicyTag > class Hilbert_sort_on_sphere_3 { diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h index 5703b56199e..56611e6687d 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h @@ -23,6 +23,9 @@ Parallel sorting is available only when the median strategy policy (the default The default traits class `Default_traits` is the kernel in which the type `std::iterator_traits::%value_type` is defined. +\tparam PolicyTag is used to specify the strategy policy. +Possible values are \link CGAL::Hilbert_sort_median_policy `Hilbert_sort_median_policy` \endlink +(the default policy) or \link CGAL::Hilbert_sort_middle_policy `Hilbert_sort_middle_policy` \endlink. \cgalHeading{Implementation} diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort_on_sphere.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort_on_sphere.h index f488ff62b12..f7d073b941e 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort_on_sphere.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort_on_sphere.h @@ -16,8 +16,9 @@ It sorts the range `[begin, end)` in place. The default traits class `Default_traits` is the kernel in which the type `std::iterator_traits::%value_type` is defined. -\tparam PolicyTag The default policy is `Hilbert_sort_median_policy()` and the -other option is `Hilbert_sort_middle_policy()`. +\tparam PolicyTag is used to specify the strategy policy. +Possible values are \link CGAL::Hilbert_sort_median_policy `Hilbert_sort_median_policy` \endlink +(the default policy) or \link CGAL::Hilbert_sort_middle_policy `Hilbert_sort_middle_policy` \endlink. The input sphere is given by a squared radius and a center, parameter `sqr_radius` and parameter `center` respectively. The default squared radius of the sphere is 1.0. diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h index e285025a210..762fb0454ff 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h @@ -23,8 +23,9 @@ done using up to four threads in 2D, and up to eight threads in 3D with the medi The default traits class `Default_traits` is the kernel in which the type `std::iterator_traits::%value_type` is defined. -\tparam PolicyTag The default policy is `Hilbert_sort_median_policy` and the -other option is `Hilbert_sort_middle_policy`. +\tparam PolicyTag is used to specify the strategy policy. +Possible values are \link CGAL::Hilbert_sort_median_policy `Hilbert_sort_median_policy` \endlink +(the default policy) or \link CGAL::Hilbert_sort_middle_policy `Hilbert_sort_middle_policy` \endlink. The default values for the thresholds and the ratio depend on the dimension. From dad8ab5d857eb1f6fa83e2a744f334630ccd5220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 2 Jan 2020 13:32:33 +0100 Subject: [PATCH 118/185] Rephrase doc of tparam ConcurrencyTag in hilbert_sort / spatial_sort --- .../doc/Spatial_sorting/CGAL/Hilbert_sort_2.h | 11 ++++++----- .../doc/Spatial_sorting/CGAL/Hilbert_sort_3.h | 9 ++++++--- .../doc/Spatial_sorting/CGAL/hilbert_sort_on_sphere.h | 6 +++--- .../doc/Spatial_sorting/CGAL/spatial_sort.h | 8 +++++--- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_2.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_2.h index f3195c7954b..65cab7f099c 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_2.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_2.h @@ -5,9 +5,8 @@ namespace CGAL { The function object `Hilbert_sort_2` sorts iterator ranges of `Traits::Point_2` along a Hilbert curve by recursively subdividing -at the median -or the middle depending on the `PolicyTag`. - +at the median or the middle, depending on the `PolicyTag` (see Section \ref sechilbert_sorting +for more information on the policies). \tparam Traits must be a model of the concept `SpatialSortingTraits_2`. @@ -15,8 +14,10 @@ or the middle depending on the `PolicyTag`. Possible values are \link CGAL::Hilbert_sort_median_policy `Hilbert_sort_median_policy` \endlink (the default policy) or \link CGAL::Hilbert_sort_middle_policy `Hilbert_sort_middle_policy` \endlink. -\tparam ConcurrencyTag must be `Sequential_tag`, `Parallel_tag`, or `Parallel_if_available_tag. With parallelism -and TBB enabled, for the median policy up to four threads are used in parallel. +\tparam ConcurrencyTag enables sequential versus parallel algorithm. +Possible values are `Sequential_tag`, `Parallel_tag`, and `Parallel_if_available_tag`. +With parallelism enabled, sorting will be performed using up to four threads. +Parallel sorting is available only when the median strategy policy (the default policy) is used. */ template< typename Traits, typename PolicyTag, typename ConcurrencyTag = Sequential_tag > class Hilbert_sort_2 { diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_3.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_3.h index 83c71cbcbeb..4e2f4028dff 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_3.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/Hilbert_sort_3.h @@ -5,7 +5,8 @@ namespace CGAL { The function object `Hilbert_sort_3` sorts iterator ranges of `Traits::Point_3` along a Hilbert curve by recursively subdividing at the median -or the middle depending on the `PolicyTag`. +or the middle, depending on the `PolicyTag`(see Section \ref sechilbert_sorting +for more information on the policies). \tparam Traits must be a model of the concept `SpatialSortingTraits_3`. @@ -13,8 +14,10 @@ or the middle depending on the `PolicyTag`. Possible values are \link CGAL::Hilbert_sort_median_policy `Hilbert_sort_median_policy` \endlink (the default policy) or \link CGAL::Hilbert_sort_middle_policy `Hilbert_sort_middle_policy` \endlink. -\tparam ConcurrencyTag must be `Sequential_tag`,`Parallel_tag`, or `Parallel_if_available_tag`. With parallelism -and TBB enabled, for the median policy up to eight threads are used in parallel. +\tparam ConcurrencyTag enables sequential versus parallel algorithm. +Possible values are `Sequential_tag`, `Parallel_tag`, and `Parallel_if_available_tag`. +With parallelism enabled, sorting will be performed using up to eight threads. +Parallel sorting is available only when the median strategy policy (the default policy) is used. */ template< typename Traits, typename PolicyTag, typename ConcurrencyTag = Sequential_tag > class Hilbert_sort_3 { diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort_on_sphere.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort_on_sphere.h index f7d073b941e..9d21e132c14 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort_on_sphere.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort_on_sphere.h @@ -9,12 +9,12 @@ If input points are not close to the input sphere, this function still works, bu It sorts the range `[begin, end)` in place. -\tparam RandomAccessIterator `std::iterator_traits::%value_type` must be convertible to -`Traits::Point_3`. +\tparam InputPointIterator must be a model of `RandomAccessIterator` and +`std::iterator_traits::%value_type` must be convertible to `Traits::Point_3`. \tparam Traits must be a model for concept `SpatialSortingTraits_3`. The default traits class `Default_traits` is the kernel in which the type -`std::iterator_traits::%value_type` is defined. +`std::iterator_traits::%value_type` is defined. \tparam PolicyTag is used to specify the strategy policy. Possible values are \link CGAL::Hilbert_sort_median_policy `Hilbert_sort_median_policy` \endlink diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h index 762fb0454ff..38e37c16894 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h @@ -10,9 +10,11 @@ of being close in the order. It sorts the range `[begin, end)` in place. -\tparam ConcurrencyTag must be `Sequential_tag`, `Parallel_tag`, or `Parallel_if_available_tag`. -With parallelism and TBB enabled, the sorting will be -done using up to four threads in 2D, and up to eight threads in 3D with the median policy. +\tparam ConcurrencyTag enables sequential versus parallel algorithm. +Possible values are `Sequential_tag`, `Parallel_tag`, and `Parallel_if_available_tag`. +With parallelism enabled, sorting will be performed using up to four threads in 2D, +and up to eight threads in 3D. +Parallel sorting is available only when the median strategy policy (the default policy) is used. \tparam InputPointIterator must be a model of `RandomAccessIterator` and `std::iterator_traits::%value_type` must be convertible to From 05fccab96dad9af23527ae047c77a613735c396f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 2 Jan 2020 13:33:08 +0100 Subject: [PATCH 119/185] Properly document spatial_sort_on_sphere --- .../CGAL/hilbert_sort_on_sphere.h | 6 +---- .../CGAL/spatial_sort_on_sphere.h | 27 +++++++------------ 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort_on_sphere.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort_on_sphere.h index 9d21e132c14..bdcb1c47f24 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort_on_sphere.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort_on_sphere.h @@ -24,11 +24,7 @@ The input sphere is given by a squared radius and a center, parameter `sqr_radiu The default squared radius of the sphere is 1.0. The default center of the sphere is the origin (0,0,0). -\cgalHeading{Precondition} - -
      -
    1. `sqr_radius` greater than 0. -
    +\pre `sqr_radius` greater than 0. \cgalHeading{Implementation} diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort_on_sphere.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort_on_sphere.h index 7cf427da1f7..bb673d663cb 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort_on_sphere.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort_on_sphere.h @@ -12,30 +12,23 @@ If input points are not close to the input sphere, this function still works, bu It sorts the range `[begin, end)` in place. -The default traits class `Default_traits` is the kernel in which the type -`std::iterator_traits::%value_type` is defined. - -The default policy is `Hilbert_sort_median_policy()` and the -other option is `Hilbert_sort_middle_policy()`. - The input sphere is given by a squared radius and a center, parameter `sqr_radius` and parameter `center` respectively. The default squared radius of the sphere is 1.0. The default center of the sphere is the origin (0,0,0). -\cgalHeading{Requirements} +\tparam InputPointIterator must be a model of `RandomAccessIterator` and +`std::iterator_traits::%value_type` must be convertible to +`Traits::Point_3`. -
      -
    1. `std::iterator_traits::%value_type` is convertible to -`Traits::Point_3`. -
    2. `Traits` is a model for concept `SpatialSortingTraits_3`. -
    +\tparam Traits must be a model for concept `SpatialSortingTraits_3`. +The default traits class `Default_traits` is the kernel in which the type +`std::iterator_traits::%value_type` is defined. -\cgalHeading{Precondition} - -
      -
    1. `sqr_radius` greater than 0. -
    +\tparam PolicyTag is used to specify the strategy policy. +Possible values are \link CGAL::Hilbert_sort_median_policy `Hilbert_sort_median_policy` \endlink +(the default policy) or \link CGAL::Hilbert_sort_middle_policy `Hilbert_sort_middle_policy` \endlink. +\pre `sqr_radius` greater than 0. \cgalHeading{Implementation} From 763ac6072c1bfc88c7d01a2389bc208c3fe4b114 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 2 Jan 2020 13:33:32 +0100 Subject: [PATCH 120/185] Improve user manual section about parallelism --- .../doc/Spatial_sorting/Spatial_sorting.txt | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt b/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt index ec6924332cb..979a2d7d08d 100644 --- a/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt +++ b/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt @@ -208,18 +208,21 @@ In this example program, the sorted sequence of points is retrieved using the indices of the points in a vector of pairs of points and integers. \cgalExample{Spatial_sorting/sp_sort_using_property_map_d.cpp} -\section Spatial_sortingParallel Spatial Sorting in Parallel +\section Spatial_sortingParallel Parallel Spatial Sorting -The Hilbert sort and spatial sort functions when using the median policy and with TBB -enabled, are parallized and use up to four/eight threads for 2D/3D. +In 2D (3D), Hilbert or spatial sorting recursively subdivides the input range in four (eight) subranges. +Therefore, a natural way to parallelize the sorting algorithm is to split the initial range in four (eight) subranges, +and let a single thread handle any further subdivision and sorting for a given subrange. +This parallel algorithm is only available when the median strategy policy is being used (this is the case +by default), as this policy ensures balance between all subranges. This is not necessarily +the case with the middle strategy, where the subrange sizes can greatly vary. -By default the sequential version is used. The parallel version is used -by adding the template parameter `CGAL::Parallel_tag`. In case it is not sure -whether TBB is enabled use `CGAL::Parallel_if_available_tag`. +The parallel version of the algorithm is enabled by specifying the template parameter `CGAL::Parallel_tag`. +In case it is not sure whether TBB is available and linked with \cgal, +`CGAL::Parallel_if_available_tag` can be used. By default, the sequential version is used. \cgalExample{Spatial_sorting/parallel_spatial_sort_2.cpp} - \section Spatial_sortingDesign Design and Implementation History The first implementation of Hilbert and spatial sorting (2D and 3D) in CGAL was done by Cristophe Delage. Then, Olivier Devillers improved its design, From bfeb6177867088d3dd37575624ddb88932a2ed10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 2 Jan 2020 13:33:46 +0100 Subject: [PATCH 121/185] Update history --- Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt b/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt index 979a2d7d08d..92112f23f07 100644 --- a/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt +++ b/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt @@ -225,10 +225,12 @@ In case it is not sure whether TBB is available and linked with \cgal, \section Spatial_sortingDesign Design and Implementation History -The first implementation of Hilbert and spatial sorting (2D and 3D) in CGAL was done by Cristophe Delage. Then, Olivier Devillers improved its design, -and implemented its multidimensional version. Finally, Pedro Machado Manhaes de Castro and Olivier Devillers added Hilbert sorting -on the sphere as well. +The first implementation of Hilbert and spatial sorting (2D and 3D) in \cgal was done by Cristophe Delage. +Olivier Devillers improved its design, and implemented its multidimensional version. +Pedro Machado Manhaes de Castro and Olivier Devillers added Hilbert sorting on the sphere. + +Andreas Fabri added a parallel version of hilbert and spatial sorting. */ } /* namespace CGAL */ From af1ae5114f3afe2a55d37fe81bdcffbc0b92f26c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 2 Jan 2020 13:33:56 +0100 Subject: [PATCH 122/185] Update cutoffs under which sequential version is used regardless of tag (after some experiments using random points in 2D/3D) --- Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h | 2 +- Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h b/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h index 3c0d5cdbc10..4b1ea293ad0 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h @@ -164,7 +164,7 @@ public: RandomAccessIterator m0 = begin, m4 = end; - if((end - begin) > 1024){ + if((end - begin) > 8192){ // 2^13, empirically a good cutoff RandomAccessIterator m1, m2, m3; m2 = internal::hilbert_split (m0, m4, Cmp< x, upx> (_k)); diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h b/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h index 5e8525bb7c1..0536ef8be94 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h @@ -179,14 +179,13 @@ public: if ((end - begin) <= _limit) return; RandomAccessIterator m0 = begin, m8 = end; - if((end - begin) > 1024){ + if((end - begin) > 2048){ // 2^11, empirically a good cutoff RandomAccessIterator m1, m2, m3, m4, m5, m6, m7; m4 = internal::hilbert_split(m0, m8, Cmp(_k)); tbb::parallel_invoke(Hilbert_split >(m2, m0, m4, Cmp(_k)), Hilbert_split >(m6, m4, m8, Cmp(_k))); - tbb::parallel_invoke(Hilbert_split >(m1, m0, m2, Cmp(_k)), Hilbert_split >(m3, m2, m4, Cmp(_k)), Hilbert_split >(m5, m4, m6, Cmp(_k)), From 4b97135cbfc6eff878002189ef2ac1038932e5b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 2 Jan 2020 13:35:08 +0100 Subject: [PATCH 123/185] Use CGAL::Real_timer in hilbert_sort tests --- .../test/Spatial_sorting/test_hilbert.cpp | 145 +++++++++--------- 1 file changed, 72 insertions(+), 73 deletions(-) diff --git a/Spatial_sorting/test/Spatial_sorting/test_hilbert.cpp b/Spatial_sorting/test/Spatial_sorting/test_hilbert.cpp index bc33af3e569..a5ca80472f0 100644 --- a/Spatial_sorting/test/Spatial_sorting/test_hilbert.cpp +++ b/Spatial_sorting/test/Spatial_sorting/test_hilbert.cpp @@ -16,8 +16,7 @@ #include #include - -#include +#include typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef K::Point_2 Point_2; @@ -32,10 +31,10 @@ typedef CGAL::Creator_uniform_d::iterator, Point>Creator_d; int main () { - int nb_points_2 = 5000, nb_points_3 = 5000, + int nb_points_2 = 10000, nb_points_3 = 10000, nb_points_d=10000, small_nb_points_d=3; CGAL::Random random (42); - CGAL::Timer cost; + CGAL::Real_timer timer; std::cout << "Testing Hilbert sort." << std::endl; @@ -57,19 +56,19 @@ int main () std::cout << " Sorting points... " << std::flush; - cost.reset();cost.start(); + timer.reset();timer.start(); CGAL::hilbert_sort (v.begin(), v.end()); - cost.stop(); + timer.stop(); - std::cout << "done in "<(v2.begin(), v2.end()); - cost.stop(); + timer.stop(); - std::cout << "done in " << cost.time() << "seconds." << std::endl; + std::cout << "done in " << timer.time() << "seconds." << std::endl; std::cout << " Checking... " << std::flush; assert(v == v2); @@ -90,11 +89,11 @@ int main () std::cout << " Sorting points... " << std::flush; - cost.reset();cost.start(); + timer.reset();timer.start(); CGAL::hilbert_sort (v.begin(), v.end()); - cost.stop(); + timer.stop(); - std::cout << "done in "<(v2.begin(), v2.end()); - cost.stop(); + timer.stop(); - std::cout << "done in " << cost.time() << "seconds." << std::endl; + std::cout << "done in " << timer.time() << "seconds." << std::endl; std::cout << " Checking... " << std::flush; assert(v == v2); @@ -218,11 +217,11 @@ int main () std::cout << " Sorting points... " << std::flush; - cost.reset();cost.start(); + timer.reset();timer.start(); CGAL::hilbert_sort (v.begin(), v.end()); - cost.stop(); + timer.stop(); - std::cout << "done in "<(v2.begin(), v2.end()); - cost.stop(); + timer.stop(); - std::cout << "done in " << cost.time() << "seconds." << std::endl; + std::cout << "done in " << timer.time() << "seconds." << std::endl; std::cout << " Checking... " << std::flush; assert(v == v2); @@ -349,11 +348,11 @@ int main () std::cout << " Sorting points... " << std::flush; - cost.reset();cost.start(); + timer.reset();timer.start(); CGAL::hilbert_sort_on_sphere(v.begin(),v.end(), 4, CGAL::ORIGIN + Vector_3(3,5,5)); - cost.stop(); + timer.stop(); - std::cout << "done in "< Date: Thu, 2 Jan 2020 13:45:44 +0100 Subject: [PATCH 124/185] Rename and clean parallel_spatial_sort_2 (since it uses 3D points) --- .../examples/Spatial_sorting/CMakeLists.txt | 2 +- ...sort_2.cpp => parallel_spatial_sort_3.cpp} | 25 +++++++++---------- 2 files changed, 13 insertions(+), 14 deletions(-) rename Spatial_sorting/examples/Spatial_sorting/{parallel_spatial_sort_2.cpp => parallel_spatial_sort_3.cpp} (56%) diff --git a/Spatial_sorting/examples/Spatial_sorting/CMakeLists.txt b/Spatial_sorting/examples/Spatial_sorting/CMakeLists.txt index 7b34b2a525f..0cd2ea143b2 100644 --- a/Spatial_sorting/examples/Spatial_sorting/CMakeLists.txt +++ b/Spatial_sorting/examples/Spatial_sorting/CMakeLists.txt @@ -18,7 +18,7 @@ if ( CGAL_FOUND ) find_package( TBB QUIET ) if( TBB_FOUND ) include( CGAL_target_use_TBB ) - CGAL_target_use_TBB( parallel_spatial_sort_2 ) + CGAL_target_use_TBB( parallel_spatial_sort_3 ) endif() else() diff --git a/Spatial_sorting/examples/Spatial_sorting/parallel_spatial_sort_2.cpp b/Spatial_sorting/examples/Spatial_sorting/parallel_spatial_sort_3.cpp similarity index 56% rename from Spatial_sorting/examples/Spatial_sorting/parallel_spatial_sort_2.cpp rename to Spatial_sorting/examples/Spatial_sorting/parallel_spatial_sort_3.cpp index ee5d788c6ef..b71cfa6887e 100644 --- a/Spatial_sorting/examples/Spatial_sorting/parallel_spatial_sort_2.cpp +++ b/Spatial_sorting/examples/Spatial_sorting/parallel_spatial_sort_3.cpp @@ -1,34 +1,33 @@ #include -#include -#include #include +#include +#include #include #include - -typedef CGAL::Exact_predicates_inexact_constructions_kernel K; -typedef K::Point_3 Point_3; -typedef CGAL::Creator_uniform_3 Creator_3; +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef K::Point_3 Point_3; +typedef CGAL::Creator_uniform_3 Creator_3; int main() { + std::size_t pt_nb = 10000; std::vector points; - points.reserve (2000); + points.reserve(pt_nb); - CGAL::Random_points_in_cube_3 gen (1.0); - - for (int i = 0; i < 2000; ++i){ - points.push_back (*gen++); - } + CGAL::Random_points_in_cube_3 gen(1.0); + + for(std::size_t i=0; i(points.begin(),points.end()); + CGAL::spatial_sort(points.begin(), points.end()); return 0; } From 25236ef5947fb1fb970d9531af9951d902efd744 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 2 Jan 2020 13:46:48 +0100 Subject: [PATCH 125/185] Fix typos --- Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt | 2 +- Spatial_sorting/doc/Spatial_sorting/examples.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt b/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt index 92112f23f07..8793def5572 100644 --- a/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt +++ b/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt @@ -230,7 +230,7 @@ Olivier Devillers improved its design, and implemented its multidimensional vers Pedro Machado Manhaes de Castro and Olivier Devillers added Hilbert sorting on the sphere. -Andreas Fabri added a parallel version of hilbert and spatial sorting. +Andreas Fabri added a parallel version of Hilbert and spatial sorting. */ } /* namespace CGAL */ diff --git a/Spatial_sorting/doc/Spatial_sorting/examples.txt b/Spatial_sorting/doc/Spatial_sorting/examples.txt index 2b187d153b5..8417048ad59 100644 --- a/Spatial_sorting/doc/Spatial_sorting/examples.txt +++ b/Spatial_sorting/doc/Spatial_sorting/examples.txt @@ -1,5 +1,5 @@ /*! -\example Spatial_sorting/parallel_spatial_sort_2.cpp +\example Spatial_sorting/parallel_spatial_sort_3.cpp \example Spatial_sorting/hilbert.cpp \example Spatial_sorting/hilbert_policies.cpp \example Spatial_sorting/small_example_delaunay_2.cpp From fc1e9e4a462d2578b2120f23441c1739432bbc83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 2 Jan 2020 14:53:53 +0100 Subject: [PATCH 126/185] Fix typo --- Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt b/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt index 8793def5572..cd4815c648f 100644 --- a/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt +++ b/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt @@ -221,7 +221,7 @@ The parallel version of the algorithm is enabled by specifying the template para In case it is not sure whether TBB is available and linked with \cgal, `CGAL::Parallel_if_available_tag` can be used. By default, the sequential version is used. -\cgalExample{Spatial_sorting/parallel_spatial_sort_2.cpp} +\cgalExample{Spatial_sorting/parallel_spatial_sort_3.cpp} \section Spatial_sortingDesign Design and Implementation History From 08ef100083c5a19bf21d1f4ae7d714424912167e Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sun, 5 Jan 2020 10:59:43 -0800 Subject: [PATCH 127/185] Straight_skeleton_builder_2_impl.h: Get more precision for free. Fixes issue #4445 The compute speed of double precision does not depend on the number of decimals, so it's free and better to use more than 5 or 6 decimals for PI. --- .../Straight_skeleton_2/Straight_skeleton_builder_2_impl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Straight_skeleton_2/include/CGAL/Straight_skeleton_2/Straight_skeleton_builder_2_impl.h b/Straight_skeleton_2/include/CGAL/Straight_skeleton_2/Straight_skeleton_builder_2_impl.h index 5fd1a2ab1c0..580891ee897 100644 --- a/Straight_skeleton_2/include/CGAL/Straight_skeleton_2/Straight_skeleton_builder_2_impl.h +++ b/Straight_skeleton_2/include/CGAL/Straight_skeleton_2/Straight_skeleton_builder_2_impl.h @@ -1421,8 +1421,8 @@ double angle_wrt_X ( Point const& a, Point const& b ) double dx = to_double(b.x() - a.x() ) ; double dy = to_double(b.y() - a.y() ) ; double atan = std::atan2(dy,dx); - double rad = atan >= 0.0 ? atan : 2.0 * 3.141592 + atan ; - double deg = rad * 180.0 / 3.141592 ; + double rad = atan >= 0.0 ? atan : 2.0 * 3.141592653589793238462643 + atan ; + double deg = rad * 180.0 / 3.141592653589793238462643; return deg ; } From 3c7eb2c6b96527c15d069582a738fcd1ec5acfd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 7 Jan 2020 15:31:07 +0100 Subject: [PATCH 128/185] Use CGAL_PI instead of hardcoding it --- .../DH_speed_test_100_vertices.cpp | 4 ++-- .../MV_speed_test_100_vertices.cpp | 4 ++-- .../WP_speed_test_100_vertices.cpp | 4 ++-- Generator/include/CGAL/point_generators_d.h | 8 ++++---- .../scene.h | 8 +++++--- .../include/CGAL/bilateral_smooth_point_set.h | 3 ++- Ridges_3/include/CGAL/Umbilics.h | 19 ++++++++++--------- .../include/CGAL/Snap_rounding_kd_2.h | 3 ++- .../Straight_skeleton_builder_2_impl.h | 7 ++++--- 9 files changed, 33 insertions(+), 27 deletions(-) diff --git a/Barycentric_coordinates_2/benchmark/Barycentric_coordinates_2/Discrete_harmonic_coordinates/DH_speed_test_100_vertices.cpp b/Barycentric_coordinates_2/benchmark/Barycentric_coordinates_2/Discrete_harmonic_coordinates/DH_speed_test_100_vertices.cpp index 561a45ccecd..0b37ce54e32 100644 --- a/Barycentric_coordinates_2/benchmark/Barycentric_coordinates_2/Discrete_harmonic_coordinates/DH_speed_test_100_vertices.cpp +++ b/Barycentric_coordinates_2/benchmark/Barycentric_coordinates_2/Discrete_harmonic_coordinates/DH_speed_test_100_vertices.cpp @@ -2,6 +2,7 @@ // We test speed of discrete harmonic coordinates on a set of automatically generated // points inside a regular polygon with 100 vertices. We use inexact kernel. +#include #include #include #include @@ -28,12 +29,11 @@ void generate_regular_polygon(const int number_of_vertices, const double polygon { const int n = number_of_vertices; const double r = polygon_radius; - const double number_pi = 3.14159; vertices.resize(n); for(int i = 0; i < n; ++i) - vertices[i] = Point(Scalar(r*sin((number_pi / n) + ((i * 2.0 * number_pi) / n))), Scalar(-r*cos((number_pi / n) + ((i * 2.0 * number_pi) / n)))); + vertices[i] = Point(Scalar(r*sin((CGAL_PI / n) + ((i * 2.0 * CGAL_PI) / n))), Scalar(-r*cos((CGAL_PI / n) + ((i * 2.0 * CGAL_PI) / n)))); } int main() diff --git a/Barycentric_coordinates_2/benchmark/Barycentric_coordinates_2/Mean_value_coordinates/MV_speed_test_100_vertices.cpp b/Barycentric_coordinates_2/benchmark/Barycentric_coordinates_2/Mean_value_coordinates/MV_speed_test_100_vertices.cpp index 261c4315dfb..1d568bf03db 100644 --- a/Barycentric_coordinates_2/benchmark/Barycentric_coordinates_2/Mean_value_coordinates/MV_speed_test_100_vertices.cpp +++ b/Barycentric_coordinates_2/benchmark/Barycentric_coordinates_2/Mean_value_coordinates/MV_speed_test_100_vertices.cpp @@ -2,6 +2,7 @@ // We test speed of mean value coordinates on a set of automatically generated // points inside a regular polygon with 100 vertices. We use inexact kernel. +#include #include #include #include @@ -28,12 +29,11 @@ void generate_regular_polygon(const int number_of_vertices, const double polygon { const int n = number_of_vertices; const double r = polygon_radius; - const double number_pi = 3.14159; vertices.resize(n); for(int i = 0; i < n; ++i) - vertices[i] = Point(Scalar(r*sin((number_pi / n) + ((i * 2.0 * number_pi) / n))), Scalar(-r*cos((number_pi / n) + ((i * 2.0 * number_pi) / n)))); + vertices[i] = Point(Scalar(r*sin((CGAL_PI / n) + ((i * 2.0 * CGAL_PI) / n))), Scalar(-r*cos((CGAL_PI / n) + ((i * 2.0 * CGAL_PI) / n)))); } int main() diff --git a/Barycentric_coordinates_2/benchmark/Barycentric_coordinates_2/Wachspress_coordinates/WP_speed_test_100_vertices.cpp b/Barycentric_coordinates_2/benchmark/Barycentric_coordinates_2/Wachspress_coordinates/WP_speed_test_100_vertices.cpp index 97468098ea0..0d28ec26fd2 100644 --- a/Barycentric_coordinates_2/benchmark/Barycentric_coordinates_2/Wachspress_coordinates/WP_speed_test_100_vertices.cpp +++ b/Barycentric_coordinates_2/benchmark/Barycentric_coordinates_2/Wachspress_coordinates/WP_speed_test_100_vertices.cpp @@ -2,6 +2,7 @@ // We test speed of Wachspress coordinates on a set of automatically generated // points inside a regular polygon with 100 vertices. We use inexact kernel. +#include #include #include #include @@ -28,12 +29,11 @@ void generate_regular_polygon(const int number_of_vertices, const double polygon { const int n = number_of_vertices; const double r = polygon_radius; - const double number_pi = 3.14159; vertices.resize(n); for(int i = 0; i < n; ++i) - vertices[i] = Point(Scalar(r*sin((number_pi / n) + ((i * 2.0 * number_pi) / n))), Scalar(-r*cos((number_pi / n) + ((i * 2.0 * number_pi) / n)))); + vertices[i] = Point(Scalar(r*sin((CGAL_PI / n) + ((i * 2.0 * CGAL_PI) / n))), Scalar(-r*cos((CGAL_PI / n) + ((i * 2.0 * CGAL_PI) / n)))); } int main() diff --git a/Generator/include/CGAL/point_generators_d.h b/Generator/include/CGAL/point_generators_d.h index 9661e647a42..9fc0b0b9193 100644 --- a/Generator/include/CGAL/point_generators_d.h +++ b/Generator/include/CGAL/point_generators_d.h @@ -18,6 +18,8 @@ #include #include +#include + #include #include @@ -56,11 +58,10 @@ generate_point() { for(int i=0; i_rnd.get_double(); a = std::sqrt( -2* std::log(1-a) ); double b=this->_rnd.get_double(); - b = std::cos(2*pi*b); + b = std::cos(2*CGAL_PI*b); coord[i]= a*b; norm += coord[i]*coord[i]; } @@ -104,11 +105,10 @@ generate_point() { for(int i=0; i_rnd.get_double(); a = std::sqrt( -2* std::log(1-a) ); double b=this->_rnd.get_double(); - b = std::cos(2*pi*b); + b = std::cos(2*CGAL_PI*b); coord[i]= a*b; norm += coord[i]*coord[i]; } diff --git a/Optimal_transportation_reconstruction_2/demo/Optimal_transportation_reconstruction_2/scene.h b/Optimal_transportation_reconstruction_2/demo/Optimal_transportation_reconstruction_2/scene.h index 5c2444aefc9..5693f0fbb30 100644 --- a/Optimal_transportation_reconstruction_2/demo/Optimal_transportation_reconstruction_2/scene.h +++ b/Optimal_transportation_reconstruction_2/demo/Optimal_transportation_reconstruction_2/scene.h @@ -18,9 +18,11 @@ #define cimg_display 0 // To avoid X11 or Windows-GDI dependency #include #endif -#include #include // std::pair #include + +#include +#include #include #include #include @@ -953,7 +955,7 @@ public: void append_star(const int nb_branches, const int density) { std::cerr << "append star..."; - const double deg_in_rad = 3.1415926535897932384626 / 180.0; + const double deg_in_rad = CGAL_PI / 180.0; const double incr = 180.0 / nb_branches; double angle = 0.0; const Point center(0.5, 0.5); @@ -970,7 +972,7 @@ public: void append_predefined_increasingly_sharp_angles(const int density, const double min_angle) { - const double deg_in_rad = 3.1415926535897932384626 / 180.0; + const double deg_in_rad = CGAL_PI / 180.0; double prev_angle = 0.0; double curr_angle = min_angle; double incr = min_angle; diff --git a/Point_set_processing_3/include/CGAL/bilateral_smooth_point_set.h b/Point_set_processing_3/include/CGAL/bilateral_smooth_point_set.h index e80d6a9be52..4adb2278c15 100644 --- a/Point_set_processing_3/include/CGAL/bilateral_smooth_point_set.h +++ b/Point_set_processing_3/include/CGAL/bilateral_smooth_point_set.h @@ -16,6 +16,7 @@ #include +#include #include #include #include @@ -143,7 +144,7 @@ compute_denoise_projection( FT project_weight_sum = FT(0.0); Vector normal_sum = CGAL::NULL_VECTOR; - FT cos_sigma = cos(sharpness_angle / 180.0 * 3.1415926); + FT cos_sigma = cos(sharpness_angle * CGAL_PI / 180.0); FT sharpness_bandwidth = std::pow((CGAL::max)(1e-8, 1 - cos_sigma), 2); typename std::vector >::const_iterator diff --git a/Ridges_3/include/CGAL/Umbilics.h b/Ridges_3/include/CGAL/Umbilics.h index 6d1c2a017be..973184e60ab 100644 --- a/Ridges_3/include/CGAL/Umbilics.h +++ b/Ridges_3/include/CGAL/Umbilics.h @@ -13,15 +13,17 @@ #include +#include +#include +#include +#include +#include + +#include #include #include #include -#include -#include -#include -#include -#include namespace CGAL { @@ -230,7 +232,6 @@ compute_type(Umbilic& umb) { Vector_3 dir, dirnext, normal; double cosinus, angle=0, angleSum=0; - const double pi=3.141592653589793; vertex_descriptor v; typename std::list::const_iterator itb = umb.contour_list().begin(), itlast = --umb.contour_list().end(); @@ -266,9 +267,9 @@ compute_type(Umbilic& umb) else angle = -acos(cosinus); angleSum += angle; - if ((angleSum > (pi/2)) && (angleSum < (3*pi/2))) umb.umbilic_type() = HYPERBOLIC_UMBILIC ; - else if ((angleSum < (-pi/2)) && (angleSum > (-3*pi/2))) umb.umbilic_type() = ELLIPTIC_UMBILIC; - else if ((angleSum <= (pi/2)) && (angleSum >= (-pi/2))) return 0;//is not considered as an umbilic + if ((angleSum > (CGAL_PI/2)) && (angleSum < (3*CGAL_PI/2))) umb.umbilic_type() = HYPERBOLIC_UMBILIC ; + else if ((angleSum < (-CGAL_PI/2)) && (angleSum > (-3*CGAL_PI/2))) umb.umbilic_type() = ELLIPTIC_UMBILIC; + else if ((angleSum <= (CGAL_PI/2)) && (angleSum >= (-CGAL_PI/2))) return 0;//is not considered as an umbilic else umb.umbilic_type() = NON_GENERIC_UMBILIC; return 1; } diff --git a/Snap_rounding_2/include/CGAL/Snap_rounding_kd_2.h b/Snap_rounding_2/include/CGAL/Snap_rounding_kd_2.h index 82bcff43495..cf7b6c2def6 100644 --- a/Snap_rounding_2/include/CGAL/Snap_rounding_kd_2.h +++ b/Snap_rounding_2/include/CGAL/Snap_rounding_kd_2.h @@ -25,6 +25,7 @@ #include #include #include +#include #include @@ -394,7 +395,7 @@ public: Multiple_kd_tree(const Point_saved_pair_list & inp_points_list, int inp_number_of_trees, const Segment_list & seg_list) : - pi(3.1415), half_pi(1.57075), + pi(CGAL_PI), half_pi(0.5 * CGAL_PI), number_of_trees(inp_number_of_trees), input_points_list(inp_points_list) { diff --git a/Straight_skeleton_2/include/CGAL/Straight_skeleton_2/Straight_skeleton_builder_2_impl.h b/Straight_skeleton_2/include/CGAL/Straight_skeleton_2/Straight_skeleton_builder_2_impl.h index 580891ee897..413b9a9e5af 100644 --- a/Straight_skeleton_2/include/CGAL/Straight_skeleton_2/Straight_skeleton_builder_2_impl.h +++ b/Straight_skeleton_2/include/CGAL/Straight_skeleton_2/Straight_skeleton_builder_2_impl.h @@ -22,9 +22,10 @@ #include #endif #include -#include +#include #include +#include #if defined(BOOST_MSVC) # pragma warning(push) @@ -1421,8 +1422,8 @@ double angle_wrt_X ( Point const& a, Point const& b ) double dx = to_double(b.x() - a.x() ) ; double dy = to_double(b.y() - a.y() ) ; double atan = std::atan2(dy,dx); - double rad = atan >= 0.0 ? atan : 2.0 * 3.141592653589793238462643 + atan ; - double deg = rad * 180.0 / 3.141592653589793238462643; + double rad = atan >= 0.0 ? atan : 2.0 * CGAL_PI + atan ; + double deg = rad * 180.0 / CGAL_PI; return deg ; } From c77865e1da90c44e2d21289118789ee472941cee Mon Sep 17 00:00:00 2001 From: Oleg Alexandrov Date: Wed, 8 Jan 2020 08:21:59 -0800 Subject: [PATCH 129/185] Add a missing line in the text and reword --- INSTALL.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 91a981a2f70..90814ba5987 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -9,6 +9,7 @@ found in `/path/to/cgal.git/Scripts/scripts/` at the root of the example/test di Here is a recipe for the examples of the 2D Triangulation package: ``` {.bash} + git clone https://github.com/CGAL/cgal.git /path/to/cgal.git cd /path/to/cgal.git/Triangulation_2/examples/Triangulation_2 /path/to/cgal.git/Scripts/scripts/cgal_create_cmake_script cd /path/to/cgal.git/Triangulation_2/examples/Triangulation_2 @@ -18,7 +19,6 @@ Here is a recipe for the examples of the 2D Triangulation package: make ``` -Note that this page describes the setting of CGAL as a sources release and, as such, -files are organized in a slightly different way, see the [Layout of the CGAL Git Repository](README.md). +If, instead of the git repository you downloaded a source release, the files will be organized in a slightly different way, see the [Layout of the CGAL Git Repository](README.md). -For more information head over to the [CGAL manual](https://doc.cgal.org/latest/Manual/general_intro.html). +For more information see the [CGAL manual](https://doc.cgal.org/latest/Manual/general_intro.html). From cec720a69cbfaa1b2076dca32c30c013339f7838 Mon Sep 17 00:00:00 2001 From: Oleg Alexandrov Date: Wed, 8 Jan 2020 18:25:25 -0800 Subject: [PATCH 130/185] Add control over hole size in the hole-filling example --- .../Polygon_mesh_processing.txt | 9 ++- .../hole_filling_example_SM.cpp | 59 +++++++++++++++++-- 2 files changed, 59 insertions(+), 9 deletions(-) diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt index d543aa198bd..2240feae4c8 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt @@ -412,10 +412,13 @@ one incident non-null face) after each hole filling step. Holes are filled one after the other, and the process stops when there is no border edge left. This process is illustrated by the example below, where holes are -iteratively filled, refined and faired to get a faired mesh with no hole. +iteratively filled, refined and faired. Optionally, only holes +not exceeding a certain diameter or number of edges can be filled. +This example assumes that the mesh is stored in a `Surface_mesh` +datastructure. Analogous examples when using the `Polyhedron_3` +class and a few others are part of the code base. - -\cgalExample{Polygon_mesh_processing/hole_filling_example.cpp} +\cgalExample{Polygon_mesh_processing/hole_filling_example_SM.cpp} \cgalFigureBegin{Triangulated_fork, fork.jpg} Holes in the fork model are filled with triangle patches. diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/hole_filling_example_SM.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/hole_filling_example_SM.cpp index 47d9d9454e4..7e165163539 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/hole_filling_example_SM.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/hole_filling_example_SM.cpp @@ -6,32 +6,77 @@ #include #include #include +#include typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; typedef Kernel::Point_3 Point; typedef CGAL::Surface_mesh Mesh; -typedef boost::graph_traits::halfedge_descriptor halfedge_descriptor; +typedef boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef boost::graph_traits::face_descriptor face_descriptor; -typedef boost::graph_traits::vertex_descriptor vertex_descriptor; +typedef boost::graph_traits::vertex_descriptor vertex_descriptor; + +bool is_small_hole(halfedge_descriptor h, Mesh & mesh, + std::set & examined_points, + double max_hole_diam, int max_num_hole_edges) +{ + int num_hole_edges = 0; + auto cvpm = CGAL::get_const_property_map(CGAL::vertex_point, mesh); + CGAL::Halfedge_around_face_circulator circ(h, mesh), done(circ); + CGAL::Bbox_3 hole_bbox; + + do { + Point p = get(cvpm, target(*circ, mesh)); + + if (examined_points.find(p) != examined_points.end()) + return false; + examined_points.insert(p); + + hole_bbox += CGAL::Bbox_3(p.x(), p.y(), p.z(), p.x(), p.y(), p.z()); + num_hole_edges++; + + // Exit early, to avoid unnecessary traversal of large holes + if (num_hole_edges > max_num_hole_edges) return false; + if (hole_bbox.xmax() - hole_bbox.xmin() > max_hole_diam) return false; + if (hole_bbox.ymax() - hole_bbox.ymin() > max_hole_diam) return false; + if (hole_bbox.zmax() - hole_bbox.zmin() > max_hole_diam) return false; + } while (++circ != done); + + return true; +} + +// Incrementally fill the holes that are no larger than given diameter +// and with no more than a given number of edges (if specified). int main(int argc, char* argv[]) { const char* filename = (argc > 1) ? argv[1] : "data/mech-holes-shark.off"; - std::ifstream input(filename); + // Both of these must be positive in order to be considered + double max_hole_diam = (argc > 2) ? boost::lexical_cast(argv[2]): -1.0; + int max_num_hole_edges = (argc > 3) ? boost::lexical_cast(argv[3]) : -1; + + std::ifstream input(filename); Mesh mesh; if ( !input || !(input >> mesh) ) { std::cerr << "Not a valid off file." << std::endl; return 1; } - // Incrementally fill the holes + // Avoid examining a hole we studied before using a different half edge. + std::set examined_points; + unsigned int nb_holes = 0; for(halfedge_descriptor h : halfedges(mesh)) { if(is_border(h,mesh)) { + + if(max_hole_diam > 0 && max_num_hole_edges > 0 && + !is_small_hole(h, mesh, examined_points, + max_hole_diam, max_num_hole_edges)) + continue; + std::vector patch_facets; std::vector patch_vertices; bool success = std::get<0>( @@ -52,8 +97,10 @@ int main(int argc, char* argv[]) std::cout << std::endl; std::cout << nb_holes << " holes have been filled" << std::endl; - - std::ofstream out("filled_SM.off"); + + std::string outfile = "filled_SM.off"; + std::ofstream out(outfile.c_str()); + std::cout << "Mesh written to: " << outfile << std::endl; out.precision(17); out << mesh << std::endl; return 0; From def8ebda4b6f56ea62fe251a97607532b3ed1db7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 9 Jan 2020 08:19:30 +0100 Subject: [PATCH 131/185] improve example by using CGAL functions --- .../hole_filling_example_SM.cpp | 67 ++++++++----------- 1 file changed, 28 insertions(+), 39 deletions(-) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/hole_filling_example_SM.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/hole_filling_example_SM.cpp index 7e165163539..960fc7d9c51 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/hole_filling_example_SM.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/hole_filling_example_SM.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -17,30 +18,23 @@ typedef boost::graph_traits::face_descriptor face_descriptor; typedef boost::graph_traits::vertex_descriptor vertex_descriptor; bool is_small_hole(halfedge_descriptor h, Mesh & mesh, - std::set & examined_points, double max_hole_diam, int max_num_hole_edges) { int num_hole_edges = 0; - auto cvpm = CGAL::get_const_property_map(CGAL::vertex_point, mesh); - CGAL::Halfedge_around_face_circulator circ(h, mesh), done(circ); CGAL::Bbox_3 hole_bbox; + for (halfedge_descriptor hc : CGAL::halfedges_around_face(h, mesh)) + { + const Point& p = mesh.point(target(hc, mesh)); - do { - Point p = get(cvpm, target(*circ, mesh)); - - if (examined_points.find(p) != examined_points.end()) - return false; - examined_points.insert(p); - - hole_bbox += CGAL::Bbox_3(p.x(), p.y(), p.z(), p.x(), p.y(), p.z()); - num_hole_edges++; + hole_bbox += p.bbox(); + ++num_hole_edges; // Exit early, to avoid unnecessary traversal of large holes if (num_hole_edges > max_num_hole_edges) return false; if (hole_bbox.xmax() - hole_bbox.xmin() > max_hole_diam) return false; if (hole_bbox.ymax() - hole_bbox.ymin() > max_hole_diam) return false; if (hole_bbox.zmax() - hole_bbox.zmin() > max_hole_diam) return false; - } while (++circ != done); + } return true; } @@ -63,36 +57,31 @@ int main(int argc, char* argv[]) return 1; } - // Avoid examining a hole we studied before using a different half edge. - std::set examined_points; - unsigned int nb_holes = 0; - for(halfedge_descriptor h : halfedges(mesh)) + std::vector border_cycles; + + // collect one halfedge per boundary cycle + CGAL::Polygon_mesh_processing::extract_boundary_cycles(mesh, std::back_inserter(border_cycles)); + + for(halfedge_descriptor h : border_cycles) { - if(is_border(h,mesh)) - { + if(max_hole_diam > 0 && max_num_hole_edges > 0 && + !is_small_hole(h, mesh, max_hole_diam, max_num_hole_edges)) + continue; - if(max_hole_diam > 0 && max_num_hole_edges > 0 && - !is_small_hole(h, mesh, examined_points, - max_hole_diam, max_num_hole_edges)) - continue; + std::vector patch_facets; + std::vector patch_vertices; + bool success = std::get<0>( + CGAL::Polygon_mesh_processing::triangulate_refine_and_fair_hole( + mesh, + h, + std::back_inserter(patch_facets), + std::back_inserter(patch_vertices)) ); - std::vector patch_facets; - std::vector patch_vertices; - bool success = std::get<0>( - CGAL::Polygon_mesh_processing::triangulate_refine_and_fair_hole( - mesh, - h, - std::back_inserter(patch_facets), - std::back_inserter(patch_vertices), - CGAL::Polygon_mesh_processing::parameters::vertex_point_map(get(CGAL::vertex_point, mesh)). - geom_traits(Kernel())) ); - - std::cout << "* Number of facets in constructed patch: " << patch_facets.size() << std::endl; - std::cout << " Number of vertices in constructed patch: " << patch_vertices.size() << std::endl; - std::cout << " Is fairing successful: " << success << std::endl; - nb_holes++; - } + std::cout << "* Number of facets in constructed patch: " << patch_facets.size() << std::endl; + std::cout << " Number of vertices in constructed patch: " << patch_vertices.size() << std::endl; + std::cout << " Is fairing successful: " << success << std::endl; + ++nb_holes; } std::cout << std::endl; From 70dce7552ff91d3b516c7d47dcadfc16251592fc Mon Sep 17 00:00:00 2001 From: Oleg Alexandrov Date: Thu, 9 Jan 2020 09:08:08 -0800 Subject: [PATCH 132/185] Wipe a repeated line --- INSTALL.md | 1 - 1 file changed, 1 deletion(-) diff --git a/INSTALL.md b/INSTALL.md index 90814ba5987..c9a998db063 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -12,7 +12,6 @@ Here is a recipe for the examples of the 2D Triangulation package: git clone https://github.com/CGAL/cgal.git /path/to/cgal.git cd /path/to/cgal.git/Triangulation_2/examples/Triangulation_2 /path/to/cgal.git/Scripts/scripts/cgal_create_cmake_script - cd /path/to/cgal.git/Triangulation_2/examples/Triangulation_2 mkdir -p build/debug cd build/debug cmake -DCGAL_DIR:PATH=/path/to/cgal.git ../.. From fe0cf2574c71b9ff472d9073f310f0e87179edbd Mon Sep 17 00:00:00 2001 From: Mael Date: Tue, 14 Jan 2020 14:57:02 +0100 Subject: [PATCH 133/185] Use std::distance rather than arithmetic to get range size Co-Authored-By: Sebastien Loriot --- Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h b/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h index 4b1ea293ad0..2acab9ca276 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h @@ -159,12 +159,12 @@ public: "Parallel_tag is enabled but TBB is unavailable."); #else const int y = (x + 1) % 2; - if (end - begin <= _limit) + if (std::distance(begin,end)) <= _limit) return; RandomAccessIterator m0 = begin, m4 = end; - if((end - begin) > 8192){ // 2^13, empirically a good cutoff + if((std::distance(begin,end)) > 8192){ // 2^13, empirically a good cutoff RandomAccessIterator m1, m2, m3; m2 = internal::hilbert_split (m0, m4, Cmp< x, upx> (_k)); From dfc9e8f0dba6fee28586626ff6f19042a4ab35f9 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 15 Jan 2020 12:46:54 +0100 Subject: [PATCH 134/185] Rework call_test to avoid error --- Intersections_3/test/Intersections_3/call_test.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/Intersections_3/test/Intersections_3/call_test.cpp b/Intersections_3/test/Intersections_3/call_test.cpp index 768c7d4ac6e..fb8eeb720c9 100644 --- a/Intersections_3/test/Intersections_3/call_test.cpp +++ b/Intersections_3/test/Intersections_3/call_test.cpp @@ -52,11 +52,13 @@ void call_do_intersect_with_kernel(const A& a, const B& b, const K&) { } -int main() +int main(int argc, char**) { CGAL::Interval_nt_advanced::Protector p; CGAL_USE(p); - try { + //we only want to check compilation + if(argc > 666 ) + { call_intersection_global(S(), S()); call_intersection_global(S(), L()); call_intersection_global(S(), Pl()); @@ -264,10 +266,6 @@ int main() call_do_intersect_with_kernel(Bbox_3(), S(), K()); call_do_intersect_with_kernel(Bbox_3(), Sph(), K()); call_do_intersect_with_kernel(Bbox_3(), Tr(), K()); - // There is no kernel to call - // call_do_intersect_with_kernel(Bbox_3(), Bbox_3(), K()); - } catch(...) { - // as long as this test compiles, it is fine - } +} return EXIT_SUCCESS; } From d2d846322560aaf8aef1e3fcd4f6b5650fdbb621 Mon Sep 17 00:00:00 2001 From: Maxime GIMENO Date: Wed, 15 Jan 2020 15:10:11 +0100 Subject: [PATCH 135/185] Update Intersections_3/test/Intersections_3/call_test.cpp Co-Authored-By: Laurent Rineau --- Intersections_3/test/Intersections_3/call_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Intersections_3/test/Intersections_3/call_test.cpp b/Intersections_3/test/Intersections_3/call_test.cpp index fb8eeb720c9..96da5418020 100644 --- a/Intersections_3/test/Intersections_3/call_test.cpp +++ b/Intersections_3/test/Intersections_3/call_test.cpp @@ -266,6 +266,6 @@ int main(int argc, char**) call_do_intersect_with_kernel(Bbox_3(), S(), K()); call_do_intersect_with_kernel(Bbox_3(), Sph(), K()); call_do_intersect_with_kernel(Bbox_3(), Tr(), K()); -} + } return EXIT_SUCCESS; } From cccaeaebdb7122ded223050c63ddac9ad1cbdec7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 15 Jan 2020 17:44:01 +0100 Subject: [PATCH 136/185] fix iterator type required --- Convex_hull_2/doc/Convex_hull_2/CGAL/ch_jarvis.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Convex_hull_2/doc/Convex_hull_2/CGAL/ch_jarvis.h b/Convex_hull_2/doc/Convex_hull_2/CGAL/ch_jarvis.h index 5268a5498a7..d9af9b3f99d 100644 --- a/Convex_hull_2/doc/Convex_hull_2/CGAL/ch_jarvis.h +++ b/Convex_hull_2/doc/Convex_hull_2/CGAL/ch_jarvis.h @@ -12,12 +12,12 @@ cyclic sequence of extreme points is cut into a linear sequence. \pre The source range [`first`,`beyond`) does not contain `result`. The default traits class `Default_traits` is the kernel in which the -value type of `InputIterator` is defined. +value type of `ForwardIterator` is defined. \cgalHeading{Requirements}
      -
    1. The value type of `InputIterator` and +
    2. The value type of `ForwardIterator` and `OutputIterator` is equivalent to `Traits::Point_2`.
    3. `Traits` defines the following subset of types from the concept `ConvexHullTraits_2` and their corresponding member @@ -46,10 +46,10 @@ in the worst case for \f$ n\f$ input points with \f$ h\f$ extreme points. */ -template +template OutputIterator -ch_jarvis( InputIterator first, -InputIterator beyond, +ch_jarvis( ForwardIterator first, +ForwardIterator beyond, OutputIterator result, const Traits & ch_traits = Default_traits); From 2c2313ea44e45e6b9d08b16bbe49780ce2ef74ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 16 Jan 2020 12:23:21 +0100 Subject: [PATCH 137/185] Do not use inheritance in concepts --- TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h | 1 - TDS_2/doc/TDS_2/Concepts/TriangulationDSVertexBase_2.h | 1 - TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h | 1 - TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h | 1 - 4 files changed, 4 deletions(-) diff --git a/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h b/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h index 2a99e243ab9..8ef6ea99deb 100644 --- a/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h +++ b/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h @@ -56,7 +56,6 @@ actually uses as a base class for the class */ class TriangulationDSFaceBase_2 - : public TriangulationDataStructure_2::Face { public: diff --git a/TDS_2/doc/TDS_2/Concepts/TriangulationDSVertexBase_2.h b/TDS_2/doc/TDS_2/Concepts/TriangulationDSVertexBase_2.h index 534accb027c..e7915a48888 100644 --- a/TDS_2/doc/TDS_2/Concepts/TriangulationDSVertexBase_2.h +++ b/TDS_2/doc/TDS_2/Concepts/TriangulationDSVertexBase_2.h @@ -52,7 +52,6 @@ of `CGAL::Triangulation_data_structure_2::Vertex`. */ class TriangulationDSVertexBase_2 - : public TriangulationDataStructure_2::Vertex { public: diff --git a/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h b/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h index 8f32290698d..2856e1d70bd 100644 --- a/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h +++ b/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h @@ -41,7 +41,6 @@ More information can be found in Section \ref TDS3secdesign. */ class TriangulationDSCellBase_3 - : public TriangulationDataStructure_3::Cell { public: diff --git a/TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h b/TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h index 73566772f4c..e1d35cb88fc 100644 --- a/TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h +++ b/TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h @@ -36,7 +36,6 @@ More information can be found in Section \ref TDS3secdesign. */ class TriangulationDSVertexBase_3 - : public TriangulationDataStructure_3::Vertex { public: From 8827fc4724e73252ce19d6b05cc27704cf166735 Mon Sep 17 00:00:00 2001 From: Mael Date: Fri, 17 Jan 2020 09:04:52 +0100 Subject: [PATCH 138/185] Distinguish between provided examples and external programs + other improvements --- INSTALL.md | 49 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index c9a998db063..bdb24fdbadb 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,23 +1,52 @@ +Building an Example Using CGAL +============================== + +Since Version 5.0, CGAL is a header-only library, hence it is not needed to build it. Usage of CGAL should simply amount to: + +``` {.bash} +git clone https://github.com/CGAL/cgal.git /path/to/cgal.git +cd /path/to/cgal.git/Triangulation_2/examples/Triangulation_2 +mkdir -p build/debug +cd build/debug +cmake -DCMAKE_BUILD_TYPE=Debug -DCGAL_DIR=/path/to/cgal.git +make +``` + +in the case of building some CGAL-provided examples in debug mode. + +Note that although CGAL is a header-only library, some parts of it must link to several external libraries, such as GMP, MPFR, etc. + Building a Program Using CGAL ============================= -Since Version 5.0, CGAL is header-only, hence it does not create a library. Some parts of it, however, link to several external libraries, such as GMP, MPFR, etc. - -If you are trying to build examples or tests that do not already have a `CMakeLists.txt`, -you can trigger its creation by calling the script [`cgal_create_cmake_script`](Scripts/scripts/cgal_create_cmake_script) -found in `/path/to/cgal.git/Scripts/scripts/` at the root of the example/test directory. -Here is a recipe for the examples of the 2D Triangulation package: +If you are trying to build a program that is not provided with CGAL and does not already have a `CMakeLists.txt`, +you can trigger the creation of a basic `CmakeLists.txt` by calling the script [`cgal_create_cmake_script`](Scripts/scripts/cgal_create_cmake_script) +found in `/path/to/cgal.git/Scripts/scripts/` at the root of your program directory. ``` {.bash} git clone https://github.com/CGAL/cgal.git /path/to/cgal.git - cd /path/to/cgal.git/Triangulation_2/examples/Triangulation_2 + cd /path/to/your/program /path/to/cgal.git/Scripts/scripts/cgal_create_cmake_script mkdir -p build/debug cd build/debug - cmake -DCGAL_DIR:PATH=/path/to/cgal.git ../.. - make + cmake -DCMAKE_BUILD_TYPE=Debug -DCGAL_DIR:PATH=/path/to/cgal.git ../.. + make your_program ``` -If, instead of the git repository you downloaded a source release, the files will be organized in a slightly different way, see the [Layout of the CGAL Git Repository](README.md). +Since the basic `CmakeLists.txt` created by the script `cgal_create_cmake_script` cannot +guess which part(s) of CGAL you are using, it does not link with any optional third party +dependency of CGAL. You should look at the documentation of the package(s) that you +are using to learn which dependencies you must add. The `CmakeLists.txt` +of the examples and demos provided with the package(s) that you are using can be used +to complete your basic `CmakeLists.txt`. + + +Repository Structure +==================== + +If you have downloaded a source release instead of cloning the Git repository, the files will be organized in a slightly different way, see the [Layout of the CGAL Git Repository](README.md). + +Documentation +============= For more information see the [CGAL manual](https://doc.cgal.org/latest/Manual/general_intro.html). From dd6cf454dc483cc7bd3f764f60182d0a112017b2 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 17 Jan 2020 09:58:44 +0100 Subject: [PATCH 139/185] add precision(17) to most examples involving surface_mesh or polyhedron. --- BGL/examples/BGL_LCC/copy_lcc.cpp | 1 + BGL/examples/BGL_polyhedron_3/copy_polyhedron.cpp | 2 ++ BGL/examples/BGL_surface_mesh/write_inp.cpp | 1 + .../examples/Polygon_mesh_processing/corefinement_LCC.cpp | 1 + .../examples/Polygon_mesh_processing/corefinement_SM.cpp | 1 + .../corefinement_consecutive_bool_op.cpp | 1 + .../corefinement_difference_remeshed.cpp | 2 ++ .../Polygon_mesh_processing/corefinement_mesh_union.cpp | 1 + .../corefinement_mesh_union_and_intersection.cpp | 2 ++ .../corefinement_mesh_union_with_attributes.cpp | 1 + .../Polygon_mesh_processing/corefinement_polyhedron_union.cpp | 1 + .../isotropic_remeshing_of_patch_example.cpp | 1 + .../examples/Polygon_mesh_processing/mesh_smoothing_example.cpp | 1 + .../Polygon_mesh_processing/orient_polygon_soup_example.cpp | 2 ++ .../Polygon_mesh_processing/random_perturbation_SM_example.cpp | 1 + .../examples/Polygon_mesh_processing/refine_fair_example.cpp | 2 ++ .../Polygon_mesh_processing/shape_smoothing_example.cpp | 1 + .../examples/Polygon_mesh_processing/stitch_borders_example.cpp | 1 + .../Polygon_mesh_processing/surface_mesh_intersection.cpp | 1 + .../Polygon_mesh_processing/triangulate_faces_example.cpp | 1 + Polyhedron/examples/Polyhedron/polyhedron_prog_cut_cube.cpp | 2 +- Polyhedron/examples/Polyhedron/polyhedron_prog_subdiv.cpp | 2 +- .../Polyhedron/polyhedron_prog_subdiv_with_boundary.cpp | 2 +- Surface_mesh/examples/Surface_mesh/sm_join.cpp | 2 +- Surface_mesh/test/Surface_mesh/sm_ply_io.cpp | 1 - 25 files changed, 29 insertions(+), 5 deletions(-) diff --git a/BGL/examples/BGL_LCC/copy_lcc.cpp b/BGL/examples/BGL_LCC/copy_lcc.cpp index d47c0216fbb..ecc43fefc59 100644 --- a/BGL/examples/BGL_LCC/copy_lcc.cpp +++ b/BGL/examples/BGL_LCC/copy_lcc.cpp @@ -55,6 +55,7 @@ int main(int argc, char* argv[]) CGAL::copy_face_graph(T1, S, CGAL::parameters::vertex_to_vertex_output_iterator(std::inserter(v2v, v2v.end())) .halfedge_to_halfedge_output_iterator(std::inserter(h2h, h2h.end()))); std::ofstream out("reverse.off"); + out.precision(17); out << S; } return 0; diff --git a/BGL/examples/BGL_polyhedron_3/copy_polyhedron.cpp b/BGL/examples/BGL_polyhedron_3/copy_polyhedron.cpp index 76aa1235c54..3f9e7b76bef 100644 --- a/BGL/examples/BGL_polyhedron_3/copy_polyhedron.cpp +++ b/BGL/examples/BGL_polyhedron_3/copy_polyhedron.cpp @@ -43,6 +43,7 @@ int main(int argc, char* argv[]) { CGAL::copy_face_graph(S, T1); std::ofstream out("sm.off"); + out.precision(17); out << T1; } @@ -81,6 +82,7 @@ int main(int argc, char* argv[]) boost::unordered_map f2f; CGAL::copy_face_graph(T1, S, std::inserter(v2v, v2v.end()), std::inserter(h2h, h2h.end())); std::ofstream out("reverse.off"); + out.precision(17); out << S; CGAL::copy_face_graph(T1, S, CGAL::parameters::vertex_to_vertex_map(boost::make_assoc_property_map(v2v)) .halfedge_to_halfedge_output_iterator(std::inserter(h2h, h2h.end())) diff --git a/BGL/examples/BGL_surface_mesh/write_inp.cpp b/BGL/examples/BGL_surface_mesh/write_inp.cpp index fce8f932b11..ba9e3545bb5 100644 --- a/BGL/examples/BGL_surface_mesh/write_inp.cpp +++ b/BGL/examples/BGL_surface_mesh/write_inp.cpp @@ -20,6 +20,7 @@ int main() CGAL::make_quad(Point(0,0,1), Point(1,0,1),Point(1,1,1),Point(0,1,1), sm); std::ofstream out("out.inp"); + out.precision(17); CGAL::write_inp(out, sm, "out.inp", "S4R"); return 0; } diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_LCC.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_LCC.cpp index f7239c96f24..5abd976cb9a 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_LCC.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_LCC.cpp @@ -34,6 +34,7 @@ int main(int argc, char* argv[]) << num_vertices(mesh2) << "\n"; std::ofstream output("mesh1_refined.off"); + output.precision(17); CGAL::write_off(output, mesh1); output.close(); output.open("mesh2_refined.off"); diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_SM.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_SM.cpp index 3eacde99ed9..77244f43fa6 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_SM.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_SM.cpp @@ -41,6 +41,7 @@ int main(int argc, char* argv[]) << num_vertices(mesh2) << "\n"; std::ofstream output("mesh1_refined.off"); + output.precision(17); output << mesh1; output.close(); output.open("mesh2_refined.off"); diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_consecutive_bool_op.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_consecutive_bool_op.cpp index cf90534b84a..bbe55ca4cbc 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_consecutive_bool_op.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_consecutive_bool_op.cpp @@ -136,6 +136,7 @@ int main(int argc, char* argv[]) { std::cout << "Intersection and union were successfully computed\n"; std::ofstream output("inter_union.off"); + output.precision(17); output << mesh2; return 0; } diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_difference_remeshed.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_difference_remeshed.cpp index 3a5068aa00b..f12868c033a 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_difference_remeshed.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_difference_remeshed.cpp @@ -67,6 +67,7 @@ int main(int argc, char* argv[]) { std::cout << "Difference was successfully computed\n"; std::ofstream output("difference.off"); + output.precision(17); output << mesh1; } else{ @@ -111,6 +112,7 @@ int main(int argc, char* argv[]) params::edge_is_constrained_map(is_constrained_map) ); std::ofstream output("difference_remeshed.off"); + output.precision(17); output << mesh1; return 0; diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_mesh_union.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_mesh_union.cpp index f03403dd58b..150a1db0782 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_mesh_union.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_mesh_union.cpp @@ -37,6 +37,7 @@ int main(int argc, char* argv[]) { std::cout << "Union was successfully computed\n"; std::ofstream output("union.off"); + output.precision(17); output << out; return 0; } diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_mesh_union_and_intersection.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_mesh_union_and_intersection.cpp index 359dd989a2c..dda4e2f1f96 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_mesh_union_and_intersection.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_mesh_union_and_intersection.cpp @@ -55,6 +55,7 @@ int main(int argc, char* argv[]) { std::cout << "Union was successfully computed\n"; std::ofstream output("union.off"); + output.precision(17); output << out_union; } else @@ -64,6 +65,7 @@ int main(int argc, char* argv[]) { std::cout << "Intersection was successfully computed\n"; std::ofstream output("intersection.off"); + output.precision(17); output << out_intersection; } else diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_mesh_union_with_attributes.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_mesh_union_with_attributes.cpp index 142902bf63a..05e5d219ba9 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_mesh_union_with_attributes.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_mesh_union_with_attributes.cpp @@ -94,6 +94,7 @@ int main(int argc, char* argv[]) { std::cout << "Union was successfully computed\n"; std::ofstream output("union.off"); + output.precision(17); output << out; return 0; } diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_polyhedron_union.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_polyhedron_union.cpp index c6080f57f03..96d76e874a6 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_polyhedron_union.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_polyhedron_union.cpp @@ -39,6 +39,7 @@ int main(int argc, char* argv[]) { std::cout << "Union was successfully computed\n"; std::ofstream output("union.off"); + output.precision(17); output << out; return 0; } diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/isotropic_remeshing_of_patch_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/isotropic_remeshing_of_patch_example.cpp index 52ce2fae96f..504dd5745f6 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/isotropic_remeshing_of_patch_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/isotropic_remeshing_of_patch_example.cpp @@ -74,6 +74,7 @@ int main(int argc, char* argv[]) ); std::ofstream out("out.off"); + out.precision(17); out << mesh; std::cout << "Remeshing done." << std::endl; diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/mesh_smoothing_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/mesh_smoothing_example.cpp index 6a1d5c2199a..ac081ec84ef 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/mesh_smoothing_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/mesh_smoothing_example.cpp @@ -48,6 +48,7 @@ int main(int argc, char** argv) .edge_is_constrained_map(eif)); std::ofstream output("mesh_smoothed.off"); + output.precision(17); output << mesh; std::cout << "Done!" << std::endl; diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/orient_polygon_soup_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/orient_polygon_soup_example.cpp index 3c073c82c8b..2eec424e91c 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/orient_polygon_soup_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/orient_polygon_soup_example.cpp @@ -44,11 +44,13 @@ int main(int argc, char* argv[]) CGAL::Polygon_mesh_processing::orient_to_bound_a_volume(mesh); std::ofstream out("tet-oriented1.off"); + out.precision(17); out << mesh; out.close(); CGAL::Polygon_mesh_processing::reverse_face_orientations(mesh); std::ofstream out2("tet-oriented2.off"); + out2.precision(17); out2 << mesh; out2.close(); diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/random_perturbation_SM_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/random_perturbation_SM_example.cpp index 8d4d69dbe98..e040195334f 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/random_perturbation_SM_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/random_perturbation_SM_example.cpp @@ -33,6 +33,7 @@ int main(int argc, char* argv[]) PMP::parameters::vertex_point_map(mesh.points()).geom_traits(K())); std::ofstream out("data/eight_perturbed.off"); + out.precision(17); out << mesh; out.close(); diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/refine_fair_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/refine_fair_example.cpp index 253e76bb122..23b9af70099 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/refine_fair_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/refine_fair_example.cpp @@ -62,6 +62,7 @@ int main(int argc, char* argv[]) CGAL::Polygon_mesh_processing::parameters::density_control_factor(2.)); std::ofstream refined_off("refined.off"); + refined_off.precision(17); refined_off << poly; refined_off.close(); std::cout << "Refinement added " << new_vertices.size() << " vertices." << std::endl; @@ -75,6 +76,7 @@ int main(int argc, char* argv[]) std::cout << "Fairing : " << (success ? "succeeded" : "failed") << std::endl; std::ofstream faired_off("faired.off"); + faired_off.precision(17); faired_off << poly; faired_off.close(); diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/shape_smoothing_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/shape_smoothing_example.cpp index fe6501c877e..6d5e7f75bd5 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/shape_smoothing_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/shape_smoothing_example.cpp @@ -41,6 +41,7 @@ int main(int argc, char* argv[]) .vertex_is_constrained_map(vcmap)); std::ofstream output("mesh_shape_smoothed.off"); + output.precision(17); output << mesh; std::cout << "Done!" << std::endl; diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/stitch_borders_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/stitch_borders_example.cpp index 89ff02c4405..bd364a60773 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/stitch_borders_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/stitch_borders_example.cpp @@ -34,6 +34,7 @@ int main(int argc, char* argv[]) std::cout << "\t Number of facets :\t" << mesh.size_of_facets() << std::endl; std::ofstream output("mesh_stitched.off"); + output.precision(17); output << std::setprecision(17) << mesh; return 0; diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/surface_mesh_intersection.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/surface_mesh_intersection.cpp index d519723fd02..20ccbf2da0f 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/surface_mesh_intersection.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/surface_mesh_intersection.cpp @@ -43,6 +43,7 @@ int main(int argc, char* argv[]) //dump polylines std::ofstream output("intersection_polylines.cgal"); + output.precision(17); for(const std::vector& polyline : polylines) { output << polyline.size() << " "; diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/triangulate_faces_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/triangulate_faces_example.cpp index 94d1a0f8aff..63528119d44 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/triangulate_faces_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/triangulate_faces_example.cpp @@ -32,6 +32,7 @@ int main(int argc, char* argv[]) std::cerr << "Error: non-triangular face left in mesh." << std::endl; std::ofstream cube_off(outfilename); + cube_off.precision(17); cube_off << mesh; return 0; diff --git a/Polyhedron/examples/Polyhedron/polyhedron_prog_cut_cube.cpp b/Polyhedron/examples/Polyhedron/polyhedron_prog_cut_cube.cpp index c244c1c1c74..04ba2ad4f51 100644 --- a/Polyhedron/examples/Polyhedron/polyhedron_prog_cut_cube.cpp +++ b/Polyhedron/examples/Polyhedron/polyhedron_prog_cut_cube.cpp @@ -66,6 +66,6 @@ int main() { Point( 0.0, 0.0, 1.5), Point( 0.0, 0.5, 0.0)); CGAL::polyhedron_cut_plane_3( P, h, pl); - std::cout << P; + std::cout < Date: Fri, 17 Jan 2020 11:55:38 +0100 Subject: [PATCH 140/185] clean-up --- Polyhedron/examples/Polyhedron/polyhedron_prog_cut_cube.cpp | 2 +- Surface_mesh/examples/Surface_mesh/sm_join.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Polyhedron/examples/Polyhedron/polyhedron_prog_cut_cube.cpp b/Polyhedron/examples/Polyhedron/polyhedron_prog_cut_cube.cpp index 04ba2ad4f51..b4ae577dd27 100644 --- a/Polyhedron/examples/Polyhedron/polyhedron_prog_cut_cube.cpp +++ b/Polyhedron/examples/Polyhedron/polyhedron_prog_cut_cube.cpp @@ -66,6 +66,6 @@ int main() { Point( 0.0, 0.0, 1.5), Point( 0.0, 0.5, 0.0)); CGAL::polyhedron_cut_plane_3( P, h, pl); - std::cout < Date: Fri, 17 Jan 2020 14:55:06 +0100 Subject: [PATCH 141/185] Tiny rephrase --- INSTALL.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index bdb24fdbadb..8b12e288e91 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,5 +1,5 @@ -Building an Example Using CGAL -============================== +Building an Example or a Demo of CGAL +===================================== Since Version 5.0, CGAL is a header-only library, hence it is not needed to build it. Usage of CGAL should simply amount to: @@ -19,7 +19,7 @@ Note that although CGAL is a header-only library, some parts of it must link to Building a Program Using CGAL ============================= -If you are trying to build a program that is not provided with CGAL and does not already have a `CMakeLists.txt`, +If you wish to build a program that is not provided with CGAL and does not already have a `CMakeLists.txt`, you can trigger the creation of a basic `CmakeLists.txt` by calling the script [`cgal_create_cmake_script`](Scripts/scripts/cgal_create_cmake_script) found in `/path/to/cgal.git/Scripts/scripts/` at the root of your program directory. From 5d1d8897b8797359868e5c0123d3e46e82a1d7c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 21 Jan 2020 22:20:29 +0100 Subject: [PATCH 142/185] Fix parentheses issues --- Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h b/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h index 2acab9ca276..3d389481e97 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h @@ -159,12 +159,12 @@ public: "Parallel_tag is enabled but TBB is unavailable."); #else const int y = (x + 1) % 2; - if (std::distance(begin,end)) <= _limit) + if (std::distance(begin,end) <= _limit) return; RandomAccessIterator m0 = begin, m4 = end; - if((std::distance(begin,end)) > 8192){ // 2^13, empirically a good cutoff + if(std::distance(begin,end) > 8192){ // 2^13, empirically a good cutoff RandomAccessIterator m1, m2, m3; m2 = internal::hilbert_split (m0, m4, Cmp< x, upx> (_k)); From 8a0005573ed34ac0efa586f92cbe8969cdef8edc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 23 Jan 2020 11:58:01 +0100 Subject: [PATCH 143/185] Relax assertion due to numerical errors that can sneak in Logically speaking, the vector nb is the bisector of ni and nj, so ni.nb and nj.nb are positive by construction. --- .../CGAL/Polygon_mesh_processing/compute_normal.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/compute_normal.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/compute_normal.h index e3696de26ff..89c9593b761 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/compute_normal.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/compute_normal.h @@ -6,7 +6,7 @@ // $URL$ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// +// // // Author(s) : Jane Tournois // Mael Rouxel-Labbé @@ -271,6 +271,8 @@ bool does_enclose_other_normals(const std::size_t i, const std::size_t j, const // with theta_j - theta_i = theta_bound const FT sp_diff_bound = nbn * 0.00017453292431333; const FT sp_bl = sp(nb, nl); + + // norm of nl is 1 by construction if(CGAL::abs(sp_bi - sp_bl) <= sp_diff_bound) continue; @@ -382,9 +384,10 @@ compute_most_visible_normal_2_points(std::vector= - std::numeric_limits::epsilon()); - CGAL_assertion(sp_bi >= 0); + sp_bi = (std::max)(FT(0), sp_bi); if(sp_bi <= min_sp) continue; From ef1236dd2bcc986ff8c057cccd25ab18ccdcd6b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 23 Jan 2020 12:04:20 +0100 Subject: [PATCH 144/185] Add #include --- .../include/CGAL/Polygon_mesh_processing/compute_normal.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/compute_normal.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/compute_normal.h index 89c9593b761..a4ba7099f7b 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/compute_normal.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/compute_normal.h @@ -27,6 +27,7 @@ #include #include +#include #include #include From b8f90e1a753118609aecc65b635e2776590fdeeb Mon Sep 17 00:00:00 2001 From: Maxime GIMENO Date: Thu, 23 Jan 2020 14:55:17 +0100 Subject: [PATCH 145/185] Update Polyhedron/examples/Polyhedron/polyhedron_prog_subdiv.cpp Co-Authored-By: Laurent Rineau --- Polyhedron/examples/Polyhedron/polyhedron_prog_subdiv.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polyhedron/examples/Polyhedron/polyhedron_prog_subdiv.cpp b/Polyhedron/examples/Polyhedron/polyhedron_prog_subdiv.cpp index ef1e442df60..e71fe9213ff 100644 --- a/Polyhedron/examples/Polyhedron/polyhedron_prog_subdiv.cpp +++ b/Polyhedron/examples/Polyhedron/polyhedron_prog_subdiv.cpp @@ -102,6 +102,6 @@ int main(int argc, char* argv[]) { std::exit(1); } subdiv( P); - std::cout << std::setprecision(17)< Date: Mon, 30 Sep 2019 12:51:00 +0200 Subject: [PATCH 146/185] Add test for bench --- .../Bounded_distance_placement.h | 4 + .../test_edge_collapse_bounded_distance.cpp | 149 ++++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h create mode 100644 Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h new file mode 100644 index 00000000000..e742d37f13e --- /dev/null +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h @@ -0,0 +1,4 @@ +#ifndef BOUNDED_DISTANCE_PLACEMENT_H +#define BOUNDED_DISTANCE_PLACEMENT_H + +#endif // BOUNDED_DISTANCE_PLACEMENT_H diff --git a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp new file mode 100644 index 00000000000..b1083f387f1 --- /dev/null +++ b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp @@ -0,0 +1,149 @@ +#include +#include + +#include +#include + +// Simplification function +#include +#include +#include +#include + +//AABB_tree +#include +#include +#include + +//Timer +#include + +//filter{ + +typedef CGAL::Simple_cartesian Kernel; +typedef CGAL::Surface_mesh Surface; + +typedef CGAL::AABB_face_graph_triangle_primitive Primitive; +typedef CGAL::AABB_traits Traits; +typedef CGAL::AABB_tree Tree; + +namespace SMS = CGAL::Surface_mesh_simplification ; + +namespace CGAL { + +namespace Surface_mesh_simplification +{ + +template +class Bounded_distance_placement +{ +public: + + typedef typename Placement::TM TM ; + +public: + + Bounded_distance_placement(const double sq_dist, + const Tree& tree, + const Placement& placement = Placement() ) + : mPlacement(placement), tree(tree), threshold_sq_dist(sq_dist) + { + } + + template + boost::optional + operator()( Profile const& aProfile) const + { + boost::optional op = mPlacement(aProfile); + typedef typename Profile::Point Point; + if(op){ + const Point* p = boost::get(&op); + if(tree.squared_distance(*p) > threshold_sq_dist){ + return boost::none; + } + } + return op; + } + +private: + + Placement mPlacement ; + const Tree& tree; + double threshold_sq_dist; + +}; +} +} +//} end filter + + + +int main( int argc, char** argv ) +{ + Surface surface_mesh; + std::ifstream is(argc > 1 ? argv[1] : "input.off"); + is >> surface_mesh; + // This is a stop predicate (defines when the algorithm terminates). + // In this example, the simplification stops when the number of undirected edges + // left in the surface mesh drops below the specified number (1000) + SMS::Count_stop_predicate stop(num_halfedges(surface_mesh)/10); + + typedef SMS::Bounded_distance_placement, Tree > Filtered_placement; + typedef SMS::LindstromTurk_placement Placement; + double copy_time, tree_time, placement1_time, placement2_time; + + std::cout<<"input has "<()) + .get_placement(placement2) + ); + timer.stop(); + placement2_time=timer.time(); + timer.reset(); + timer.start(); + SMS::edge_collapse( copy_mesh, + stop, + CGAL::parameters::get_cost (SMS::LindstromTurk_cost()) + .get_placement(placement1) + ); + timer.stop(); + placement1_time=timer.time(); + surface_mesh.collect_garbage(); + copy_mesh.collect_garbage(); + std::cout<<"Filtered placement total time = "< Date: Mon, 30 Sep 2019 13:09:18 +0200 Subject: [PATCH 147/185] WIP waiting for the missing intersections --- .../test_edge_collapse_bounded_distance.cpp | 48 +++++++++++-------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp index b1083f387f1..22726ae3afe 100644 --- a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp +++ b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp @@ -15,10 +15,11 @@ #include #include + //Timer #include - //filter{ +#include typedef CGAL::Simple_cartesian Kernel; typedef CGAL::Surface_mesh Surface; @@ -34,7 +35,7 @@ namespace CGAL { namespace Surface_mesh_simplification { -template +template class Bounded_distance_placement { public: @@ -44,9 +45,8 @@ public: public: Bounded_distance_placement(const double sq_dist, - const Tree& tree, const Placement& placement = Placement() ) - : mPlacement(placement), tree(tree), threshold_sq_dist(sq_dist) + : mPlacement(placement), threshold_sq_dist(sq_dist) { } @@ -58,17 +58,35 @@ public: typedef typename Profile::Point Point; if(op){ const Point* p = boost::get(&op); - if(tree.squared_distance(*p) > threshold_sq_dist){ + const typename Profile::Triangle_vector& triangles = aProfile.triangles(); + typename Profile::Triangle_vector::const_iterator it = triangles.begin(); + bool does_intersect = false; + CGAL::Sphere_3 s(*p, threshold_sq_dist); + if(aProfile.left_face_exists()){ + ++it; + } + if(aProfile.right_face_exists()){ + ++it; + } + while(it!= triangles.end()){ + typename Profile::Triangle t = *it; + if(CGAL::do_intersect(t, s)){ + does_intersect = true; + break; + } + } + if(!does_intersect) + { return boost::none; } } return op; } + private: Placement mPlacement ; - const Tree& tree; double threshold_sq_dist; }; @@ -88,9 +106,9 @@ int main( int argc, char** argv ) // left in the surface mesh drops below the specified number (1000) SMS::Count_stop_predicate stop(num_halfedges(surface_mesh)/10); - typedef SMS::Bounded_distance_placement, Tree > Filtered_placement; + typedef SMS::Bounded_distance_placement > Filtered_placement; typedef SMS::LindstromTurk_placement Placement; - double copy_time, tree_time, placement1_time, placement2_time; + double placement1_time, placement2_time; std::cout<<"input has "< Date: Mon, 30 Sep 2019 13:37:18 +0200 Subject: [PATCH 148/185] Add Policy for bounded distance placement --- .../Bounded_distance_placement.h | 92 ++++++++++++++++++- .../test_edge_collapse_bounded_distance.cpp | 80 +--------------- 2 files changed, 94 insertions(+), 78 deletions(-) diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h index e742d37f13e..dddd601bf65 100644 --- a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h @@ -1,4 +1,90 @@ -#ifndef BOUNDED_DISTANCE_PLACEMENT_H -#define BOUNDED_DISTANCE_PLACEMENT_H +// Copyright (c) 2017 GeometryFactory (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$ +// SPDX-License-Identifier: GPL-3.0+ +// +// Author(s) : Andreas Fabri +// +#ifndef CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_BOUNDED_DISTANCE_PLACEMENT_H +#define CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_BOUNDED_DISTANCE_PLACEMENT_H + +#include +#include +#include + +namespace CGAL { + +namespace Surface_mesh_simplification +{ + +template +class Bounded_distance_placement +{ +public: + + typedef typename Placement::TM TM ; + +public: + + Bounded_distance_placement(const double sq_dist, + const Placement& placement = Placement() ) + : mPlacement(placement), threshold_sq_dist(sq_dist) + { + } + + template + boost::optional + operator()( Profile const& aProfile) const + { + boost::optional op = mPlacement(aProfile); + typedef typename Profile::Point Point; + typedef typename CGAL::Kernel_traits< Point >::Kernel Kernel; + if(op){ + const Point* p = boost::get(&op); + const typename Profile::Triangle_vector& triangles = aProfile.triangles(); + typename Profile::Triangle_vector::const_iterator it = triangles.begin(); + typename Profile::VertexPointMap ppmap = aProfile.vertex_point_map(); + + bool does_intersect = false; + CGAL::Sphere_3 s(*p, threshold_sq_dist); + while(it!= triangles.end()){ + typename Kernel::Triangle_3 t(get(ppmap, it->v0), get(ppmap, it->v1), get(ppmap, it->v2)); + if(CGAL::do_intersect(t, s)){ + does_intersect = true; + break; + } + ++it; + } + if(!does_intersect) + { + return boost::none; + } + } + return op; + } + + +private: + + Placement mPlacement ; + double threshold_sq_dist; + +}; +} +} + +#endif // CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_BOUNDED_DISTANCE_PLACEMENT_H + -#endif // BOUNDED_DISTANCE_PLACEMENT_H diff --git a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp index 22726ae3afe..1dab340de47 100644 --- a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp +++ b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp @@ -19,82 +19,12 @@ //Timer #include //filter{ -#include - -typedef CGAL::Simple_cartesian Kernel; -typedef CGAL::Surface_mesh Surface; - -typedef CGAL::AABB_face_graph_triangle_primitive Primitive; -typedef CGAL::AABB_traits Traits; -typedef CGAL::AABB_tree Tree; - -namespace SMS = CGAL::Surface_mesh_simplification ; - -namespace CGAL { - -namespace Surface_mesh_simplification -{ - -template -class Bounded_distance_placement -{ -public: - - typedef typename Placement::TM TM ; - -public: - - Bounded_distance_placement(const double sq_dist, - const Placement& placement = Placement() ) - : mPlacement(placement), threshold_sq_dist(sq_dist) - { - } - - template - boost::optional - operator()( Profile const& aProfile) const - { - boost::optional op = mPlacement(aProfile); - typedef typename Profile::Point Point; - if(op){ - const Point* p = boost::get(&op); - const typename Profile::Triangle_vector& triangles = aProfile.triangles(); - typename Profile::Triangle_vector::const_iterator it = triangles.begin(); - bool does_intersect = false; - CGAL::Sphere_3 s(*p, threshold_sq_dist); - if(aProfile.left_face_exists()){ - ++it; - } - if(aProfile.right_face_exists()){ - ++it; - } - while(it!= triangles.end()){ - typename Profile::Triangle t = *it; - if(CGAL::do_intersect(t, s)){ - does_intersect = true; - break; - } - } - if(!does_intersect) - { - return boost::none; - } - } - return op; - } - - -private: - - Placement mPlacement ; - double threshold_sq_dist; - -}; -} -} +#include //} end filter - +namespace SMS = CGAL::Surface_mesh_simplification ; +typedef CGAL::Simple_cartesian Kernel; +typedef CGAL::Surface_mesh Surface; int main( int argc, char** argv ) { @@ -141,7 +71,7 @@ int main( int argc, char** argv ) placement1_time=timer.time(); surface_mesh.collect_garbage(); copy_mesh.collect_garbage(); - std::cout<<"Filtered placement total time = "< Date: Mon, 30 Sep 2019 14:18:45 +0200 Subject: [PATCH 149/185] Update --- .../Bounded_distance_placement.h | 34 +++---- .../test_edge_collapse_bounded_distance.cpp | 99 ++++++++++--------- 2 files changed, 65 insertions(+), 68 deletions(-) diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h index dddd601bf65..c2b7ab08750 100644 --- a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017 GeometryFactory (France). All rights reserved. +// Copyright (c) 2019 GeometryFactory (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 @@ -15,7 +15,7 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0+ // -// Author(s) : Andreas Fabri +// Author(s) : Maxime Gimeno // #ifndef CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_BOUNDED_DISTANCE_PLACEMENT_H #define CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_BOUNDED_DISTANCE_PLACEMENT_H @@ -29,7 +29,7 @@ namespace CGAL { namespace Surface_mesh_simplification { -template +template class Bounded_distance_placement { public: @@ -38,9 +38,10 @@ public: public: - Bounded_distance_placement(const double sq_dist, + Bounded_distance_placement(const double dist, + const Tree& tree, const Placement& placement = Placement() ) - : mPlacement(placement), threshold_sq_dist(sq_dist) + : mPlacement(placement), tree(tree), threshold_dist(dist) { } @@ -53,24 +54,12 @@ public: typedef typename CGAL::Kernel_traits< Point >::Kernel Kernel; if(op){ const Point* p = boost::get(&op); - const typename Profile::Triangle_vector& triangles = aProfile.triangles(); - typename Profile::Triangle_vector::const_iterator it = triangles.begin(); - typename Profile::VertexPointMap ppmap = aProfile.vertex_point_map(); - bool does_intersect = false; - CGAL::Sphere_3 s(*p, threshold_sq_dist); - while(it!= triangles.end()){ - typename Kernel::Triangle_3 t(get(ppmap, it->v0), get(ppmap, it->v1), get(ppmap, it->v2)); - if(CGAL::do_intersect(t, s)){ - does_intersect = true; - break; - } - ++it; - } - if(!does_intersect) - { - return boost::none; + + if(tree.do_intersect(CGAL::Sphere_3(*p, threshold_dist*threshold_dist))){ + return op; } + return boost::none; } return op; } @@ -79,7 +68,8 @@ public: private: Placement mPlacement ; - double threshold_sq_dist; + const Tree& tree; + double threshold_dist; }; } diff --git a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp index 1dab340de47..3dc39895ec1 100644 --- a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp +++ b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp @@ -15,72 +15,79 @@ #include #include +//bbox +#include + //Timer -#include -//filter{ +//#include #include -//} end filter namespace SMS = CGAL::Surface_mesh_simplification ; typedef CGAL::Simple_cartesian Kernel; typedef CGAL::Surface_mesh Surface; + +typedef CGAL::AABB_face_graph_triangle_primitive Primitive; +typedef CGAL::AABB_traits Traits; +typedef CGAL::AABB_tree Tree; + + int main( int argc, char** argv ) { - Surface surface_mesh; - std::ifstream is(argc > 1 ? argv[1] : "input.off"); - is >> surface_mesh; - // This is a stop predicate (defines when the algorithm terminates). - // In this example, the simplification stops when the number of undirected edges - // left in the surface mesh drops below the specified number (1000) - SMS::Count_stop_predicate stop(num_halfedges(surface_mesh)/10); + Surface ref_mesh; + std::ifstream is(argc > 1 ? argv[1] : "data/helmet.off"); + is >> ref_mesh; - typedef SMS::Bounded_distance_placement > Filtered_placement; + SMS::Count_stop_predicate stop(num_halfedges(ref_mesh)/10); + + typedef SMS::Bounded_distance_placement, Tree> Filtered_placement; typedef SMS::LindstromTurk_placement Placement; - double placement1_time, placement2_time; + //double placement1_time, placement2_time, tree_time; - std::cout<<"input has "< bbox(CGAL::Polygon_mesh_processing::bbox(ref_mesh)); - SMS::edge_collapse( surface_mesh, + + Kernel::Point_3 cmin = (bbox.min)(); + Kernel::Point_3 cmax = (bbox.max)(); + double diag = std::sqrt(CGAL::squared_distance(cmin,cmax)); + + Surface small_mesh = ref_mesh; + Surface big_mesh = ref_mesh; + Tree tree( faces(ref_mesh).first, faces(ref_mesh).second, ref_mesh); + + Placement placement_ref; + Filtered_placement placement_small(0.00005*diag, tree, placement_ref); + Filtered_placement placement_big(50*diag, tree, placement_ref); + + SMS::edge_collapse( small_mesh, stop, CGAL::parameters::get_cost (SMS::LindstromTurk_cost()) - .get_placement(placement2) + .get_placement(placement_small) ); - timer.stop(); - placement2_time=timer.time(); - timer.reset(); - timer.start(); - SMS::edge_collapse( copy_mesh, + + SMS::edge_collapse( big_mesh, stop, CGAL::parameters::get_cost (SMS::LindstromTurk_cost()) - .get_placement(placement1) + .get_placement(placement_big) ); - timer.stop(); - placement1_time=timer.time(); - surface_mesh.collect_garbage(); - copy_mesh.collect_garbage(); - std::cout<<"Filtered placement time = "<()) + .get_placement(placement_ref) + ); + + ref_mesh.collect_garbage(); + small_mesh.collect_garbage(); + big_mesh.collect_garbage(); + //std::cout<<"Filtered placement time = "< Date: Mon, 30 Sep 2019 18:18:06 +0200 Subject: [PATCH 150/185] do an initial try with the closest point since do_intersect is with a sphere and not a ball --- .../Edge_collapse/Bounded_distance_placement.h | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h index c2b7ab08750..35d1dec66db 100644 --- a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h @@ -53,10 +53,24 @@ public: typedef typename Profile::Point Point; typedef typename CGAL::Kernel_traits< Point >::Kernel Kernel; if(op){ + + CGAL_assertion(!tree.empty()); + const Point* p = boost::get(&op); + tree.accelerate_distance_queries(); + Point cp = tree.best_hint(*p).first; // requires accelerate distance query to be called. + // We could do better by having access to the internal kd-tree + // and call search_any_point with a fuzzy_sphere. - if(tree.do_intersect(CGAL::Sphere_3(*p, threshold_dist*threshold_dist))){ + const double sqtd = threshold_dist*threshold_dist; + + // if no input vertex is closer than the threshold, then + // any face closer than the threshold is intersected by + // the sphere (avoid the inclusion of the mesh into the threshold sphere) + if( CGAL::compare_squared_distance(*p,cp, sqtd)!=LARGER || + tree.do_intersect(CGAL::Sphere_3(*p, sqtd))) + { return op; } return boost::none; From 32e78834eb6d6a41abbda1d4da5753b73ab80bea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 2 Jan 2020 15:21:52 +0100 Subject: [PATCH 151/185] Clean header --- .../Bounded_distance_placement.h | 77 ++++++++----------- 1 file changed, 31 insertions(+), 46 deletions(-) diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h index 35d1dec66db..f71f4aaa10e 100644 --- a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h @@ -1,19 +1,10 @@ // Copyright (c) 2019 GeometryFactory (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$ -// SPDX-License-Identifier: GPL-3.0+ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // Author(s) : Maxime Gimeno // @@ -21,74 +12,68 @@ #define CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_BOUNDED_DISTANCE_PLACEMENT_H #include + +#include + #include -#include namespace CGAL { - -namespace Surface_mesh_simplification -{ +namespace Surface_mesh_simplification { template class Bounded_distance_placement { public: - - typedef typename Placement::TM TM ; + typedef typename Placement::TM TM; public: - Bounded_distance_placement(const double dist, - const Tree& tree, - const Placement& placement = Placement() ) - : mPlacement(placement), tree(tree), threshold_dist(dist) - { - } + const Tree& tree, + const Placement& placement = Placement()) + : m_get_placement(placement), m_tree(tree), m_(dist) + { } template boost::optional - operator()( Profile const& aProfile) const + operator()(const Profile& profile) const { - boost::optional op = mPlacement(aProfile); - typedef typename Profile::Point Point; + typedef typename Profile::Point Point; typedef typename CGAL::Kernel_traits< Point >::Kernel Kernel; - if(op){ + boost::optional op = m_get_placement(profile); + if(op) + { CGAL_assertion(!tree.empty()); - const Point* p = boost::get(&op); + const Point& p = *op; tree.accelerate_distance_queries(); - Point cp = tree.best_hint(*p).first; // requires accelerate distance query to be called. - // We could do better by having access to the internal kd-tree - // and call search_any_point with a fuzzy_sphere. + const Point& cp = tree.best_hint(*p).first; // requires accelerate distance query to be called. - const double sqtd = threshold_dist*threshold_dist; + // We could do better by having access to the internal kd-tree + // and call search_any_point with a fuzzy_sphere. + const double sqtd = CGAL::square(m_threshold_dist); // if no input vertex is closer than the threshold, then // any face closer than the threshold is intersected by // the sphere (avoid the inclusion of the mesh into the threshold sphere) - if( CGAL::compare_squared_distance(*p,cp, sqtd)!=LARGER || - tree.do_intersect(CGAL::Sphere_3(*p, sqtd))) - { + if(CGAL::compare_squared_distance(p, cp, sqtd) != LARGER || + tree.do_intersect(CGAL::Sphere_3(p, sqtd))) return op; - } - return boost::none; + + return boost::optional(); } + return op; } - private: - - Placement mPlacement ; - const Tree& tree; - double threshold_dist; - + const Placement m_get_placement; + const Tree& m_tree; + const double m_threshold_dist; }; -} -} + +} // namespace Surface_mesh_simplification +} // namespace CGAL #endif // CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_BOUNDED_DISTANCE_PLACEMENT_H - - From 8c26549b65c04d8f6e04741e350cf6007228c228 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 2 Jan 2020 15:22:00 +0100 Subject: [PATCH 152/185] Clean test --- .../test_edge_collapse_bounded_distance.cpp | 76 +++++++------------ 1 file changed, 26 insertions(+), 50 deletions(-) diff --git a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp index 3dc39895ec1..17700dd0156 100644 --- a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp +++ b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp @@ -1,11 +1,9 @@ -#include -#include - #include #include // Simplification function #include +#include #include #include #include @@ -18,22 +16,24 @@ //bbox #include +#include +#include -//Timer -//#include -#include +namespace SMS = CGAL::Surface_mesh_simplification; -namespace SMS = CGAL::Surface_mesh_simplification ; -typedef CGAL::Simple_cartesian Kernel; -typedef CGAL::Surface_mesh Surface; +typedef CGAL::Simple_cartesian Kernel; +typedef Kernel::Point_3 Point_3; +typedef CGAL::Surface_mesh Surface; +typedef CGAL::AABB_face_graph_triangle_primitive Primitive; +typedef CGAL::AABB_traits Traits; +typedef CGAL::AABB_tree Tree; -typedef CGAL::AABB_face_graph_triangle_primitive Primitive; -typedef CGAL::AABB_traits Traits; -typedef CGAL::AABB_tree Tree; +typedef SMS::LindstromTurk_cost Cost; +typedef SMS::LindstromTurk_placement Placement; +typedef SMS::Bounded_distance_placement Filtered_placement; - -int main( int argc, char** argv ) +int main(int argc, char** argv) { Surface ref_mesh; std::ifstream is(argc > 1 ? argv[1] : "data/helmet.off"); @@ -41,54 +41,30 @@ int main( int argc, char** argv ) SMS::Count_stop_predicate stop(num_halfedges(ref_mesh)/10); - typedef SMS::Bounded_distance_placement, Tree> Filtered_placement; - typedef SMS::LindstromTurk_placement Placement; - //double placement1_time, placement2_time, tree_time; - - //std::cout<<"input has "< bbox(CGAL::Polygon_mesh_processing::bbox(ref_mesh)); - - Kernel::Point_3 cmin = (bbox.min)(); - Kernel::Point_3 cmax = (bbox.max)(); - double diag = std::sqrt(CGAL::squared_distance(cmin,cmax)); + Point_3 cmin = (bbox.min)(); + Point_3 cmax = (bbox.max)(); + const double diag = std::sqrt(CGAL::squared_distance(cmin, cmax)); Surface small_mesh = ref_mesh; Surface big_mesh = ref_mesh; - Tree tree( faces(ref_mesh).first, faces(ref_mesh).second, ref_mesh); + Tree tree(faces(ref_mesh).first, faces(ref_mesh).second, ref_mesh); Placement placement_ref; Filtered_placement placement_small(0.00005*diag, tree, placement_ref); Filtered_placement placement_big(50*diag, tree, placement_ref); - SMS::edge_collapse( small_mesh, - stop, - CGAL::parameters::get_cost (SMS::LindstromTurk_cost()) - .get_placement(placement_small) - ); + SMS::edge_collapse(small_mesh, stop, CGAL::parameters::get_cost(Cost()).get_placement(placement_small)); + SMS::edge_collapse(big_mesh, stop, CGAL::parameters::get_cost(Cost()).get_placement(placement_big)); + SMS::edge_collapse(ref_mesh, stop, CGAL::parameters::get_cost(Cost()).get_placement(placement_ref)); - SMS::edge_collapse( big_mesh, - stop, - CGAL::parameters::get_cost (SMS::LindstromTurk_cost()) - .get_placement(placement_big) - ); + std::cout << "There are " << num_vertices(surface_mesh) << " vertices left when filtered" + << " and " << num_vertices(copy_mesh) << " when not filtered." << std::endl; - SMS::edge_collapse( ref_mesh, - stop, - CGAL::parameters::get_cost (SMS::LindstromTurk_cost()) - .get_placement(placement_ref) - ); - - ref_mesh.collect_garbage(); - small_mesh.collect_garbage(); - big_mesh.collect_garbage(); - //std::cout<<"Filtered placement time = "< Date: Thu, 2 Jan 2020 15:26:19 +0100 Subject: [PATCH 153/185] Fix compilation / test --- .../Edge_collapse/Bounded_distance_placement.h | 10 +++++----- .../test_edge_collapse_bounded_distance.cpp | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h index f71f4aaa10e..d022a007790 100644 --- a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h @@ -30,7 +30,7 @@ public: Bounded_distance_placement(const double dist, const Tree& tree, const Placement& placement = Placement()) - : m_get_placement(placement), m_tree(tree), m_(dist) + : m_get_placement(placement), m_tree(tree), m_threshold_dist(dist) { } template @@ -43,12 +43,12 @@ public: boost::optional op = m_get_placement(profile); if(op) { - CGAL_assertion(!tree.empty()); + CGAL_assertion(!m_tree.empty()); const Point& p = *op; - tree.accelerate_distance_queries(); - const Point& cp = tree.best_hint(*p).first; // requires accelerate distance query to be called. + m_tree.accelerate_distance_queries(); + const Point& cp = m_tree.best_hint(p).first; // requires accelerate distance query to be called. // We could do better by having access to the internal kd-tree // and call search_any_point with a fuzzy_sphere. @@ -58,7 +58,7 @@ public: // any face closer than the threshold is intersected by // the sphere (avoid the inclusion of the mesh into the threshold sphere) if(CGAL::compare_squared_distance(p, cp, sqtd) != LARGER || - tree.do_intersect(CGAL::Sphere_3(p, sqtd))) + m_tree.do_intersect(CGAL::Sphere_3(p, sqtd))) return op; return boost::optional(); diff --git a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp index 17700dd0156..e946d6b8a1b 100644 --- a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp +++ b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp @@ -57,14 +57,14 @@ int main(int argc, char** argv) Filtered_placement placement_big(50*diag, tree, placement_ref); SMS::edge_collapse(small_mesh, stop, CGAL::parameters::get_cost(Cost()).get_placement(placement_small)); - SMS::edge_collapse(big_mesh, stop, CGAL::parameters::get_cost(Cost()).get_placement(placement_big)); SMS::edge_collapse(ref_mesh, stop, CGAL::parameters::get_cost(Cost()).get_placement(placement_ref)); + SMS::edge_collapse(big_mesh, stop, CGAL::parameters::get_cost(Cost()).get_placement(placement_big)); - std::cout << "There are " << num_vertices(surface_mesh) << " vertices left when filtered" - << " and " << num_vertices(copy_mesh) << " when not filtered." << std::endl; + std::cout << "There are " << vertices(small_mesh).size() << " vertices left when filtered" + << " and " << num_vertices(big_mesh) << " when not filtered." << std::endl; - assert(vertices(big_mesh).size() == vertices(ref_mesh).size()); assert(vertices(small_mesh).size() != vertices(ref_mesh).size()); + assert(vertices(big_mesh).size() == vertices(ref_mesh).size()); return EXIT_SUCCESS; } From 5ab92fef26f3ff1a112e7590bacb45a98398427e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 2 Jan 2020 15:46:11 +0100 Subject: [PATCH 154/185] Keep the squared value in memory instead of recomputing it on every call --- .../Policies/Edge_collapse/Bounded_distance_placement.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h index d022a007790..130c66edc31 100644 --- a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h @@ -30,7 +30,7 @@ public: Bounded_distance_placement(const double dist, const Tree& tree, const Placement& placement = Placement()) - : m_get_placement(placement), m_tree(tree), m_threshold_dist(dist) + : m_get_placement(placement), m_tree(tree), m_sq_threshold_dist(CGAL::square(dist)) { } template @@ -52,13 +52,12 @@ public: // We could do better by having access to the internal kd-tree // and call search_any_point with a fuzzy_sphere. - const double sqtd = CGAL::square(m_threshold_dist); // if no input vertex is closer than the threshold, then // any face closer than the threshold is intersected by // the sphere (avoid the inclusion of the mesh into the threshold sphere) - if(CGAL::compare_squared_distance(p, cp, sqtd) != LARGER || - m_tree.do_intersect(CGAL::Sphere_3(p, sqtd))) + if(CGAL::compare_squared_distance(p, cp, m_sq_threshold_dist) != LARGER || + m_tree.do_intersect(CGAL::Sphere_3(p, m_sq_threshold_dist))) return op; return boost::optional(); @@ -70,7 +69,7 @@ public: private: const Placement m_get_placement; const Tree& m_tree; - const double m_threshold_dist; + const double m_sq_threshold_dist; }; } // namespace Surface_mesh_simplification From 1ee8e7b83847160c6ef78acdb8f137d9dc2a918b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 2 Jan 2020 15:46:29 +0100 Subject: [PATCH 155/185] Better output in the test --- .../test_edge_collapse_bounded_distance.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp index e946d6b8a1b..77fbd23589c 100644 --- a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp +++ b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp @@ -60,8 +60,9 @@ int main(int argc, char** argv) SMS::edge_collapse(ref_mesh, stop, CGAL::parameters::get_cost(Cost()).get_placement(placement_ref)); SMS::edge_collapse(big_mesh, stop, CGAL::parameters::get_cost(Cost()).get_placement(placement_big)); - std::cout << "There are " << vertices(small_mesh).size() << " vertices left when filtered" - << " and " << num_vertices(big_mesh) << " when not filtered." << std::endl; + std::cout << "no filtering: " << vertices(ref_mesh).size() << " vertices left" << std::endl; + std::cout << "large filtering distance: " << vertices(big_mesh).size() << " vertices left" << std::endl; + std::cout << "small filtering distance: " << vertices(small_mesh).size() << " vertices left" << std::endl; assert(vertices(small_mesh).size() != vertices(ref_mesh).size()); assert(vertices(big_mesh).size() == vertices(ref_mesh).size()); From 46e7a8f930f34b79bbb086a72183ffcb54434d78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 7 Jan 2020 13:54:45 +0100 Subject: [PATCH 156/185] Make it optional to pass the AABB tree --- .../Bounded_distance_placement.h | 140 ++++++++++++++++-- 1 file changed, 124 insertions(+), 16 deletions(-) diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h index 130c66edc31..904492f56ff 100644 --- a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h @@ -6,49 +6,105 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s) : Maxime Gimeno +// Author(s) : Maxime Gimeno, +// Mael Rouxel-Labbé // #ifndef CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_BOUNDED_DISTANCE_PLACEMENT_H #define CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_BOUNDED_DISTANCE_PLACEMENT_H #include +#include +#include +#include +#include +#include #include +#include #include namespace CGAL { namespace Surface_mesh_simplification { -template +// An AABB tree can also be passed to the placement instead, see undocumented specialization below +template class Bounded_distance_placement { -public: - typedef typename Placement::TM TM; + typedef typename GeomTraits::Triangle_3 Triangle; + typedef std::vector Triangle_container; + typedef typename Triangle_container::iterator TC_iterator; + typedef CGAL::AABB_triangle_primitive Primitive; + typedef CGAL::AABB_traits Traits; + typedef CGAL::AABB_tree AABB_tree; + +private: + template + void initialize_tree(const Profile& profile) const + { + typedef typename Profile::Geom_traits Geom_traits; + typedef typename Geom_traits::Triangle_3 Triangle; + + typedef typename Profile::Triangle_mesh Triangle_mesh; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + CGAL_precondition(m_tree_ptr == nullptr); + + const Triangle_mesh& tm = profile.surface_mesh(); + const Geom_traits& gt = profile.geom_traits(); + std::vector input_triangles; + + for(face_descriptor f : faces(profile.surface_mesh())) + { + halfedge_descriptor h = halfedge(f, tm); + CGAL_assertion(!is_border(h, tm)); + + input_triangles.push_back(gt.construct_triangle_3_object()( + get(profile.vertex_point_map(), source(h, tm)), + get(profile.vertex_point_map(), target(h, tm)), + get(profile.vertex_point_map(), target(next(h, tm), tm)))); + } + + m_tree_ptr = new AABB_tree(input_triangles.begin(), input_triangles.end()); + const_cast(m_tree_ptr)->build(); + } public: Bounded_distance_placement(const double dist, - const Tree& tree, - const Placement& placement = Placement()) - : m_get_placement(placement), m_tree(tree), m_sq_threshold_dist(CGAL::square(dist)) + const BasePlacement& placement = BasePlacement()) + : + m_sq_threshold_dist(CGAL::square(dist)), + m_tree_ptr(nullptr), + m_base_placement(placement) { } + ~Bounded_distance_placement() + { + if(m_tree_ptr != nullptr) + delete m_tree_ptr; + } + template boost::optional operator()(const Profile& profile) const { - typedef typename Profile::Point Point; - typedef typename CGAL::Kernel_traits< Point >::Kernel Kernel; + typedef typename Profile::Geom_traits Geom_traits; + typedef typename Profile::Point Point; - boost::optional op = m_get_placement(profile); + boost::optional op = m_base_placement(profile); if(op) { - CGAL_assertion(!m_tree.empty()); + if(m_tree_ptr == nullptr) + initialize_tree(profile); + + CGAL_assertion(m_tree_ptr != nullptr); + CGAL_assertion(!m_tree_ptr->empty()); const Point& p = *op; - m_tree.accelerate_distance_queries(); - const Point& cp = m_tree.best_hint(p).first; // requires accelerate distance query to be called. + m_tree_ptr->accelerate_distance_queries(); + const Point& cp = m_tree_ptr->best_hint(p).first; // requires accelerate distance query to be called. // We could do better by having access to the internal kd-tree // and call search_any_point with a fuzzy_sphere. @@ -57,7 +113,7 @@ public: // any face closer than the threshold is intersected by // the sphere (avoid the inclusion of the mesh into the threshold sphere) if(CGAL::compare_squared_distance(p, cp, m_sq_threshold_dist) != LARGER || - m_tree.do_intersect(CGAL::Sphere_3(p, m_sq_threshold_dist))) + m_tree_ptr->do_intersect(CGAL::Sphere_3(p, m_sq_threshold_dist))) return op; return boost::optional(); @@ -67,9 +123,61 @@ public: } private: - const Placement m_get_placement; - const Tree& m_tree; const double m_sq_threshold_dist; + mutable const AABB_tree* m_tree_ptr; + + const BasePlacement m_base_placement; +}; + +// Undocumented specizalization where an _already built_ AABB tree is passed +template +class Bounded_distance_placement > +{ + typedef CGAL::AABB_tree AABB_tree; + +public: + Bounded_distance_placement(const double dist, + const AABB_tree& tree, + const BasePlacement& placement = BasePlacement()) + : + m_sq_threshold_dist(CGAL::square(dist)), + m_tree_ptr(&tree), + m_base_placement(placement) + { } + + template + boost::optional + operator()(const Profile& profile) const + { + typedef typename Profile::Geom_traits Geom_traits; + typedef typename Profile::Point Point; + + boost::optional op = m_base_placement(profile); + if(op) + { + CGAL_assertion(m_tree_ptr != nullptr); + CGAL_assertion(!m_tree_ptr->empty()); + + const Point& p = *op; + + m_tree_ptr->accelerate_distance_queries(); + const Point& cp = m_tree_ptr->best_hint(p).first; // requires accelerate distance query to be called. + + if(CGAL::compare_squared_distance(p, cp, m_sq_threshold_dist) != LARGER || + m_tree_ptr->do_intersect(CGAL::Sphere_3(p, m_sq_threshold_dist))) + return op; + + return boost::optional(); + } + + return op; + } + +private: + const double m_sq_threshold_dist; + mutable const AABB_tree* m_tree_ptr; + + const BasePlacement m_base_placement; }; } // namespace Surface_mesh_simplification From 66b32fa3d13ed63546f72290826dc329200fc48d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 7 Jan 2020 13:55:43 +0100 Subject: [PATCH 157/185] Update test --- .../test_edge_collapse_bounded_distance.cpp | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp index 77fbd23589c..c93208d36bf 100644 --- a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp +++ b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp @@ -25,13 +25,15 @@ typedef CGAL::Simple_cartesian Kernel; typedef Kernel::Point_3 Point_3; typedef CGAL::Surface_mesh Surface; +typedef SMS::LindstromTurk_cost Cost; +typedef SMS::LindstromTurk_placement Placement; + typedef CGAL::AABB_face_graph_triangle_primitive Primitive; typedef CGAL::AABB_traits Traits; typedef CGAL::AABB_tree Tree; -typedef SMS::LindstromTurk_cost Cost; -typedef SMS::LindstromTurk_placement Placement; -typedef SMS::Bounded_distance_placement Filtered_placement; +typedef SMS::Bounded_distance_placement Filtered_placement; +typedef SMS::Bounded_distance_placement Filtered_placement_with_tree; int main(int argc, char** argv) { @@ -48,16 +50,18 @@ int main(int argc, char** argv) Point_3 cmax = (bbox.max)(); const double diag = std::sqrt(CGAL::squared_distance(cmin, cmax)); + Surface mesh_cpy = ref_mesh; // need a copy to keep the AABB tree valid Surface small_mesh = ref_mesh; Surface big_mesh = ref_mesh; - Tree tree(faces(ref_mesh).first, faces(ref_mesh).second, ref_mesh); + Tree tree(faces(mesh_cpy).first, faces(mesh_cpy).second, mesh_cpy); Placement placement_ref; - Filtered_placement placement_small(0.00005*diag, tree, placement_ref); - Filtered_placement placement_big(50*diag, tree, placement_ref); - - SMS::edge_collapse(small_mesh, stop, CGAL::parameters::get_cost(Cost()).get_placement(placement_small)); SMS::edge_collapse(ref_mesh, stop, CGAL::parameters::get_cost(Cost()).get_placement(placement_ref)); + + Filtered_placement_with_tree placement_small(0.00005*diag, tree, placement_ref); + SMS::edge_collapse(small_mesh, stop, CGAL::parameters::get_cost(Cost()).get_placement(placement_small)); + + Filtered_placement placement_big(50*diag, placement_ref); // lazily builds the AABB tree SMS::edge_collapse(big_mesh, stop, CGAL::parameters::get_cost(Cost()).get_placement(placement_big)); std::cout << "no filtering: " << vertices(ref_mesh).size() << " vertices left" << std::endl; From 38b780cdb66737e55f901b9bc3a20bb3fad72e9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 7 Jan 2020 14:31:50 +0100 Subject: [PATCH 158/185] Tiny improvement to GH doc --- .../Policies/Edge_collapse/GarlandHeckbert_policies.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Surface_mesh_simplification/doc/Surface_mesh_simplification/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/GarlandHeckbert_policies.h b/Surface_mesh_simplification/doc/Surface_mesh_simplification/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/GarlandHeckbert_policies.h index 07fc7ed0a93..5b4de9dcaf5 100644 --- a/Surface_mesh_simplification/doc/Surface_mesh_simplification/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/GarlandHeckbert_policies.h +++ b/Surface_mesh_simplification/doc/Surface_mesh_simplification/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/GarlandHeckbert_policies.h @@ -12,13 +12,13 @@ associating quadrics to vertices. Note however, that they may still be wrapped with slight behavior modifying classes such as `Constrained_placement` or `Bounded_normal_change_placement`. -Note that these policies depend on the third party \ref thirdpartyEigen library. - \tparam TriangleMesh is the type of surface mesh being simplified, and must be a model of the `MutableFaceGraph` and `HalfedgeListGraph` concepts. \tparam GeomTraits must be a model of `Kernel`. If you have passed a traits class in the optional named parameters in the call to `edge_collapse()`, the types must be identical. +These policies depend on the third party \ref thirdpartyEigen library. + */ template class GarlandHeckbert_policies From fa83880b5e30c4ac9f0300e99fb21973ca9fd10a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 7 Jan 2020 14:32:23 +0100 Subject: [PATCH 159/185] Document Bounded_distance_placement --- .../Bounded_distance_placement.h | 55 +++++++++++++++++++ .../Concepts/GetPlacement.h | 1 + .../PackageDescription.txt | 1 + 3 files changed, 57 insertions(+) create mode 100644 Surface_mesh_simplification/doc/Surface_mesh_simplification/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h diff --git a/Surface_mesh_simplification/doc/Surface_mesh_simplification/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h b/Surface_mesh_simplification/doc/Surface_mesh_simplification/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h new file mode 100644 index 00000000000..0a227beabcc --- /dev/null +++ b/Surface_mesh_simplification/doc/Surface_mesh_simplification/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h @@ -0,0 +1,55 @@ + +namespace CGAL { +namespace Surface_mesh_simplification { + +/*! +\ingroup PkgSurfaceMeshSimplificationRef + +The class `Bounded_distance_placement` is a model for the concept `GetPlacement`. + +This placement class is a wrapper around another (so-called base) placement class. +The position of a vertex resulting from the contraction of an edge is obtained by first querying +the base placement class, and checking whether this tentative position is not too far +(according to a user-provided distance bound) from the input mesh. +If it is too far, the position is rejected and no position is returned; otherwise, +the position is returned. + +\tparam BasePlacement must be a model of `GetPlacement`. +\tparam GeomTraits must be a model of `Kernel` and be identical to the traits specified + in the named parameters of the function `edge_collapse()` (if specified). + +The distance check is performed using an AABB tree and this class thus depends on the package \ref PkgAABBTree. + +\cgalModels `GetPlacement` + +*/ +template +class Bounded_distance_placement + : public BasePlacement +{ +public: + /// + typedef typename GeomTraits::FT FT; + + /// \name Creation + /// + /// @{ + + /// The distance bound `d` is used to control that during simplification, + /// no vertex has a distance to the input that would be greater than `d`. + Bounded_distance_placement(const FT d, const BasePlacement& base_placement = BasePlacement()); + + /// @} + + /// \name Operations + /// @{ + + /// Returns the placement computed by `base_placement`, provided the distance between the input + /// and this placement is smaller than `d`. Otherwise, nothing is returned. + boost::optional operator()(const Edge_profile& profile) const; + + /// @} +}; + +} // namespace Surface_Mesh_Simplification +} // namespace CGAL diff --git a/Surface_mesh_simplification/doc/Surface_mesh_simplification/Concepts/GetPlacement.h b/Surface_mesh_simplification/doc/Surface_mesh_simplification/Concepts/GetPlacement.h index f7f0b927f6d..3ca167ecf05 100644 --- a/Surface_mesh_simplification/doc/Surface_mesh_simplification/Concepts/GetPlacement.h +++ b/Surface_mesh_simplification/doc/Surface_mesh_simplification/Concepts/GetPlacement.h @@ -18,6 +18,7 @@ or can be intentionally returned to prevent the edge from being collapsed. \cgalHasModel `CGAL::Surface_mesh_simplification::Midpoint_placement` \cgalHasModel `CGAL::Surface_mesh_simplification::LindstromTurk_placement` \cgalHasModel `CGAL::Surface_mesh_simplification::GarlandHeckbert_policies` +\cgalHasModel `CGAL::Surface_mesh_simplification::Bounded_distance_placement` \cgalHasModel `CGAL::Surface_mesh_simplification::Bounded_normal_change_placement` \cgalHasModel `CGAL::Surface_mesh_simplification::Constrained_placement` diff --git a/Surface_mesh_simplification/doc/Surface_mesh_simplification/PackageDescription.txt b/Surface_mesh_simplification/doc/Surface_mesh_simplification/PackageDescription.txt index 9cec933f869..6ff97276f7e 100644 --- a/Surface_mesh_simplification/doc/Surface_mesh_simplification/PackageDescription.txt +++ b/Surface_mesh_simplification/doc/Surface_mesh_simplification/PackageDescription.txt @@ -43,6 +43,7 @@ - `CGAL::Surface_mesh_simplification::LindstromTurk_cost` - `CGAL::Surface_mesh_simplification::LindstromTurk_placement` - `CGAL::Surface_mesh_simplification::GarlandHeckbert_policies` +- `CGAL::Surface_mesh_simplification::Bounded_distance_placement` - `CGAL::Surface_mesh_simplification::Bounded_normal_change_placement` - `CGAL::Surface_mesh_simplification::Constrained_placement` */ From 80f1583fa8aca77d3947bb44af4312c89538044b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 7 Jan 2020 14:47:52 +0100 Subject: [PATCH 160/185] Minor doc improvements --- .../Bounded_distance_placement.h | 22 ++++++++++++------- .../test_edge_collapse_bounded_distance.cpp | 3 ++- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h index 904492f56ff..dad4317af92 100644 --- a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h @@ -24,6 +24,9 @@ #include +#include +#include + namespace CGAL { namespace Surface_mesh_simplification { @@ -31,9 +34,13 @@ namespace Surface_mesh_simplification { template class Bounded_distance_placement { + typedef GeomTraits Geom_traits; + typedef typename Geom_traits::FT FT; + typedef typename GeomTraits::Triangle_3 Triangle; typedef std::vector Triangle_container; typedef typename Triangle_container::iterator TC_iterator; + typedef CGAL::AABB_triangle_primitive Primitive; typedef CGAL::AABB_traits Traits; typedef CGAL::AABB_tree AABB_tree; @@ -42,8 +49,7 @@ private: template void initialize_tree(const Profile& profile) const { - typedef typename Profile::Geom_traits Geom_traits; - typedef typename Geom_traits::Triangle_3 Triangle; + CGAL_static_assertion((std::is_same::value)); typedef typename Profile::Triangle_mesh Triangle_mesh; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; @@ -71,7 +77,7 @@ private: } public: - Bounded_distance_placement(const double dist, + Bounded_distance_placement(const FT dist, const BasePlacement& placement = BasePlacement()) : m_sq_threshold_dist(CGAL::square(dist)), @@ -89,7 +95,6 @@ public: boost::optional operator()(const Profile& profile) const { - typedef typename Profile::Geom_traits Geom_traits; typedef typename Profile::Point Point; boost::optional op = m_base_placement(profile); @@ -123,7 +128,7 @@ public: } private: - const double m_sq_threshold_dist; + const FT m_sq_threshold_dist; mutable const AABB_tree* m_tree_ptr; const BasePlacement m_base_placement; @@ -133,10 +138,11 @@ private: template class Bounded_distance_placement > { - typedef CGAL::AABB_tree AABB_tree; + typedef CGAL::AABB_tree AABB_tree; + typedef typename AABB_tree::AABB_traits::FT FT; public: - Bounded_distance_placement(const double dist, + Bounded_distance_placement(const FT dist, const AABB_tree& tree, const BasePlacement& placement = BasePlacement()) : @@ -174,7 +180,7 @@ public: } private: - const double m_sq_threshold_dist; + const FT m_sq_threshold_dist; mutable const AABB_tree* m_tree_ptr; const BasePlacement m_base_placement; diff --git a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp index c93208d36bf..8aaa51a4651 100644 --- a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp +++ b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp @@ -22,6 +22,7 @@ namespace SMS = CGAL::Surface_mesh_simplification; typedef CGAL::Simple_cartesian Kernel; + typedef Kernel::Point_3 Point_3; typedef CGAL::Surface_mesh Surface; @@ -48,7 +49,7 @@ int main(int argc, char** argv) Point_3 cmin = (bbox.min)(); Point_3 cmax = (bbox.max)(); - const double diag = std::sqrt(CGAL::squared_distance(cmin, cmax)); + const double diag = CGAL::approximate_sqrt(CGAL::squared_distance(cmin, cmax)); Surface mesh_cpy = ref_mesh; // need a copy to keep the AABB tree valid Surface small_mesh = ref_mesh; From 3df376ed83c5ee62aee0eafcec5d4ff8968d3962 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 10 Jan 2020 19:56:30 +0100 Subject: [PATCH 161/185] Update dependencies enter the commit message for your changes. Lines starting --- .../package_info/Surface_mesh_simplification/dependencies | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Surface_mesh_simplification/package_info/Surface_mesh_simplification/dependencies b/Surface_mesh_simplification/package_info/Surface_mesh_simplification/dependencies index f8f2b1e180e..27dd31f34e6 100644 --- a/Surface_mesh_simplification/package_info/Surface_mesh_simplification/dependencies +++ b/Surface_mesh_simplification/package_info/Surface_mesh_simplification/dependencies @@ -1,9 +1,13 @@ +AABB_tree Algebraic_foundations BGL +Cartesian_kernel Circulator Distance_2 Distance_3 Installation +Intersections_2 +Intersections_3 Interval_support Kernel_23 Modular_arithmetic @@ -12,5 +16,6 @@ Profiling_tools Property_map Random_numbers STL_Extension +Spatial_searching Stream_support Surface_mesh_simplification From 0de28e84fffb8cb748389e387f901b1a3d753e36 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 28 Jan 2020 12:42:06 +0100 Subject: [PATCH 162/185] Undocument --- .../Bounded_distance_placement.h | 26 +++++------ .../Concepts/GetPlacement.h | 46 +++++++++---------- .../PackageDescription.txt | 1 - 3 files changed, 36 insertions(+), 37 deletions(-) diff --git a/Surface_mesh_simplification/doc/Surface_mesh_simplification/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h b/Surface_mesh_simplification/doc/Surface_mesh_simplification/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h index 0a227beabcc..5fa7e3c3395 100644 --- a/Surface_mesh_simplification/doc/Surface_mesh_simplification/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h +++ b/Surface_mesh_simplification/doc/Surface_mesh_simplification/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h @@ -2,7 +2,7 @@ namespace CGAL { namespace Surface_mesh_simplification { -/*! +/* \ingroup PkgSurfaceMeshSimplificationRef The class `Bounded_distance_placement` is a model for the concept `GetPlacement`. @@ -28,27 +28,27 @@ class Bounded_distance_placement : public BasePlacement { public: - /// + // typedef typename GeomTraits::FT FT; - /// \name Creation - /// - /// @{ + // \name Creation + // + // @{ - /// The distance bound `d` is used to control that during simplification, - /// no vertex has a distance to the input that would be greater than `d`. + // The distance bound `d` is used to control that during simplification, + // no vertex has a distance to the input that would be greater than `d`. Bounded_distance_placement(const FT d, const BasePlacement& base_placement = BasePlacement()); - /// @} + // @} - /// \name Operations - /// @{ + // \name Operations + // @{ - /// Returns the placement computed by `base_placement`, provided the distance between the input - /// and this placement is smaller than `d`. Otherwise, nothing is returned. + // Returns the placement computed by `base_placement`, provided the distance between the input + // and this placement is smaller than `d`. Otherwise, nothing is returned. boost::optional operator()(const Edge_profile& profile) const; - /// @} + // @} }; } // namespace Surface_Mesh_Simplification diff --git a/Surface_mesh_simplification/doc/Surface_mesh_simplification/Concepts/GetPlacement.h b/Surface_mesh_simplification/doc/Surface_mesh_simplification/Concepts/GetPlacement.h index 3ca167ecf05..f9fdbf0d981 100644 --- a/Surface_mesh_simplification/doc/Surface_mesh_simplification/Concepts/GetPlacement.h +++ b/Surface_mesh_simplification/doc/Surface_mesh_simplification/Concepts/GetPlacement.h @@ -1,28 +1,28 @@ -/*! -\ingroup PkgSurfaceMeshSimplificationConcepts -\cgalConcept +//! +//!\ingroup PkgSurfaceMeshSimplificationConcepts +//!\cgalConcept +//! +//!The concept `GetPlacement` describes the requirements for the policy +//!function object which gets the collapse placement of an edge, +//!that is, the new position of the vertex that remains after a +//!halfedge-collapse operation. +//! +//!The placement returned is a `boost::optional` value (i.e., it can +//!be absent). An absent result indicates that the edge should not be collapsed. +//!This could be the result of a computational limitation (such as an overflow), +//!or can be intentionally returned to prevent the edge from being collapsed. +//! +//!\cgalRefines `DefaultConstructible` +//!\cgalRefines `CopyConstructible` +//! +//!\cgalHasModel `CGAL::Surface_mesh_simplification::Midpoint_placement` +//!\cgalHasModel `CGAL::Surface_mesh_simplification::LindstromTurk_placement` +//!\cgalHasModel `CGAL::Surface_mesh_simplification::GarlandHeckbert_policies` +//\cgalHasModel `CGAL::Surface_mesh_simplification::Bounded_distance_placement` +//!\cgalHasModel `CGAL::Surface_mesh_simplification::Bounded_normal_change_placement` +//!\cgalHasModel `CGAL::Surface_mesh_simplification::Constrained_placement` -The concept `GetPlacement` describes the requirements for the policy -function object which gets the collapse placement of an edge, -that is, the new position of the vertex that remains after a -halfedge-collapse operation. -The placement returned is a `boost::optional` value (i.e., it can -be absent). An absent result indicates that the edge should not be collapsed. -This could be the result of a computational limitation (such as an overflow), -or can be intentionally returned to prevent the edge from being collapsed. - -\cgalRefines `DefaultConstructible` -\cgalRefines `CopyConstructible` - -\cgalHasModel `CGAL::Surface_mesh_simplification::Midpoint_placement` -\cgalHasModel `CGAL::Surface_mesh_simplification::LindstromTurk_placement` -\cgalHasModel `CGAL::Surface_mesh_simplification::GarlandHeckbert_policies` -\cgalHasModel `CGAL::Surface_mesh_simplification::Bounded_distance_placement` -\cgalHasModel `CGAL::Surface_mesh_simplification::Bounded_normal_change_placement` -\cgalHasModel `CGAL::Surface_mesh_simplification::Constrained_placement` - -*/ class GetPlacement { public: diff --git a/Surface_mesh_simplification/doc/Surface_mesh_simplification/PackageDescription.txt b/Surface_mesh_simplification/doc/Surface_mesh_simplification/PackageDescription.txt index 6ff97276f7e..9cec933f869 100644 --- a/Surface_mesh_simplification/doc/Surface_mesh_simplification/PackageDescription.txt +++ b/Surface_mesh_simplification/doc/Surface_mesh_simplification/PackageDescription.txt @@ -43,7 +43,6 @@ - `CGAL::Surface_mesh_simplification::LindstromTurk_cost` - `CGAL::Surface_mesh_simplification::LindstromTurk_placement` - `CGAL::Surface_mesh_simplification::GarlandHeckbert_policies` -- `CGAL::Surface_mesh_simplification::Bounded_distance_placement` - `CGAL::Surface_mesh_simplification::Bounded_normal_change_placement` - `CGAL::Surface_mesh_simplification::Constrained_placement` */ From a8820c69a98a34fab1d453bf8f253238426eef01 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 28 Jan 2020 13:45:27 +0100 Subject: [PATCH 163/185] Doc. --- .../Concepts/GetPlacement.h | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/Surface_mesh_simplification/doc/Surface_mesh_simplification/Concepts/GetPlacement.h b/Surface_mesh_simplification/doc/Surface_mesh_simplification/Concepts/GetPlacement.h index f9fdbf0d981..da415685d46 100644 --- a/Surface_mesh_simplification/doc/Surface_mesh_simplification/Concepts/GetPlacement.h +++ b/Surface_mesh_simplification/doc/Surface_mesh_simplification/Concepts/GetPlacement.h @@ -1,26 +1,26 @@ -//! -//!\ingroup PkgSurfaceMeshSimplificationConcepts -//!\cgalConcept -//! -//!The concept `GetPlacement` describes the requirements for the policy -//!function object which gets the collapse placement of an edge, -//!that is, the new position of the vertex that remains after a -//!halfedge-collapse operation. -//! -//!The placement returned is a `boost::optional` value (i.e., it can -//!be absent). An absent result indicates that the edge should not be collapsed. -//!This could be the result of a computational limitation (such as an overflow), -//!or can be intentionally returned to prevent the edge from being collapsed. -//! -//!\cgalRefines `DefaultConstructible` -//!\cgalRefines `CopyConstructible` -//! -//!\cgalHasModel `CGAL::Surface_mesh_simplification::Midpoint_placement` -//!\cgalHasModel `CGAL::Surface_mesh_simplification::LindstromTurk_placement` -//!\cgalHasModel `CGAL::Surface_mesh_simplification::GarlandHeckbert_policies` -//\cgalHasModel `CGAL::Surface_mesh_simplification::Bounded_distance_placement` -//!\cgalHasModel `CGAL::Surface_mesh_simplification::Bounded_normal_change_placement` -//!\cgalHasModel `CGAL::Surface_mesh_simplification::Constrained_placement` +/*! +\ingroup PkgSurfaceMeshSimplificationConcepts +\cgalConcept + +The concept `GetPlacement` describes the requirements for the policy +function object which gets the collapse placement of an edge, +that is, the new position of the vertex that remains after a +halfedge-collapse operation. + +The placement returned is a `boost::optional` value (i.e., it can +be absent). An absent result indicates that the edge should not be collapsed. +This could be the result of a computational limitation (such as an overflow), +or can be intentionally returned to prevent the edge from being collapsed. + +\cgalRefines `DefaultConstructible` +\cgalRefines `CopyConstructible` + +\cgalHasModel `CGAL::Surface_mesh_simplification::Midpoint_placement` +\cgalHasModel `CGAL::Surface_mesh_simplification::LindstromTurk_placement` +\cgalHasModel `CGAL::Surface_mesh_simplification::GarlandHeckbert_policies` +\cgalHasModel `CGAL::Surface_mesh_simplification::Bounded_normal_change_placement` +\cgalHasModel `CGAL::Surface_mesh_simplification::Constrained_placement` +*/ class GetPlacement From 6cd0be27072ec1e693528521e4f61d7f86a331fb Mon Sep 17 00:00:00 2001 From: Mael Date: Wed, 29 Jan 2020 16:49:52 +0100 Subject: [PATCH 164/185] Update changes.md --- Installation/CHANGES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 736a64839c6..c13c8649420 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -75,6 +75,10 @@ Release date: June 2020 - The concept "EdgeProfile" has been removed. This concept was not actually in use as the CGAL-provided model `CGAL::Edge_profile` was imposed to the user. Other concepts have been clarified to reflect the fact that the API uses this particular class. +### STL Extensions for CGAL + - Added a new concurrency tag: `CGAL::Parallel_if_available_tag`. This tag is a convenience typedef to `CGAL::Parallel_tag` + if the third party library TBB has been found and linked with, and to `CGAL::Sequential_tag` otherwise. + [Release 5.0](https://github.com/CGAL/cgal/releases/tag/releases%2FCGAL-5.0) ----------- From bb35aacb4d399ba65d5b4bb0a5f9c43180fd86e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 31 Jan 2020 11:03:42 +0100 Subject: [PATCH 165/185] Fix some const correctness in SMSP --- .../shortest_paths_no_id.cpp | 12 +++---- .../Surface_mesh_shortest_path.h | 33 ++++++++++++------- .../Surface_mesh_shortest_path_test_1.cpp | 10 +++--- .../Surface_mesh_shortest_path_test_2.cpp | 6 ++-- .../Surface_mesh_shortest_path_test_3.cpp | 4 +-- .../Surface_mesh_shortest_path_test_4.cpp | 8 ++--- .../Surface_mesh_shortest_path_test_5.cpp | 6 ++-- .../Surface_mesh_shortest_path/TestMesh.cpp | 10 +++--- .../include/CGAL/test_util.h | 6 ++-- 9 files changed, 52 insertions(+), 43 deletions(-) diff --git a/Surface_mesh_shortest_path/examples/Surface_mesh_shortest_path/shortest_paths_no_id.cpp b/Surface_mesh_shortest_path/examples/Surface_mesh_shortest_path/shortest_paths_no_id.cpp index ec93ca54a56..fe9489bfb9d 100644 --- a/Surface_mesh_shortest_path/examples/Surface_mesh_shortest_path/shortest_paths_no_id.cpp +++ b/Surface_mesh_shortest_path/examples/Surface_mesh_shortest_path/shortest_paths_no_id.cpp @@ -11,16 +11,16 @@ #include -typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; -typedef CGAL::Polyhedron_3 Triangle_mesh; -typedef CGAL::Surface_mesh_shortest_path_traits Traits; +typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; +typedef CGAL::Polyhedron_3 Triangle_mesh; +typedef CGAL::Surface_mesh_shortest_path_traits Traits; // default property maps typedef boost::property_map::type Vertex_index_map; + boost::vertex_external_index_t>::const_type Vertex_index_map; typedef boost::property_map::type Halfedge_index_map; + CGAL::halfedge_external_index_t>::const_type Halfedge_index_map; typedef boost::property_map::type Face_index_map; + CGAL::face_external_index_t>::const_type Face_index_map; typedef CGAL::Surface_mesh_shortest_path::%type`. + The default is `boost::property_map::%const_type`. \tparam HIM a model of `ReadablePropertyMap` with `halfedge_descriptor` as key and `unsigned int` as value type. - The default is `boost::property_map::%type`. + The default is `boost::property_map::%const_type`. \tparam FIM a model of `ReadablePropertyMap` with `face_descriptor` as key and `unsigned int` as value type. - The default is `boost::property_map::%type`. + The default is `boost::property_map::%const_type`. \tparam VPM a model of `ReadablePropertyMap` with `vertex_descriptor` as key and `Traits::Point_3` as value type. - The default is `boost::property_map::%type`. + The default is `boost::property_map::%const_type`. + +If no property map is provided through the constructor of the class, the internal property maps must +be available and initialized. + +\sa \link PkgBGLHelper `CGAL::set_halfedgeds_items_id()`\endlink */ template::type + typename boost::property_map::const_type >::type Vertex_index_map; typedef typename Default::Get< HIM, - typename boost::property_map::type + typename boost::property_map::const_type >::type Halfedge_index_map; typedef typename Default::Get< FIM, - typename boost::property_map::type + typename boost::property_map::const_type >::type Face_index_map; typedef typename Default::Get< VPM, - typename boost::property_map::type + typename boost::property_map::const_type >::type Vertex_point_map; #else @@ -336,7 +341,7 @@ private: private: const Traits& m_traits; - Triangle_mesh& m_graph; + const Triangle_mesh& m_graph; Vertex_index_map m_vertexIndexMap; Halfedge_index_map m_halfedgeIndexMap; @@ -2196,11 +2201,15 @@ public: Equivalent to `Surface_mesh_shortest_path(tm, get(boost::vertex_index, tm), get(boost::halfedge_index, tm), get(boost::face_index, tm), get(CGAL::vertex_point, tm), traits)`. + + Internal property maps must be available and initialized. + + \sa \link PkgBGLHelper `CGAL::set_halfedgeds_items_id()`\endlink */ - Surface_mesh_shortest_path(Triangle_mesh& tm, + Surface_mesh_shortest_path(const Triangle_mesh& tm, const Traits& traits = Traits()) : m_traits(traits) - , m_graph(const_cast(tm)) + , m_graph(tm) , m_vertexIndexMap(get(boost::vertex_index, tm)) , m_halfedgeIndexMap(get(boost::halfedge_index, tm)) , m_faceIndexMap(get(boost::face_index, tm)) @@ -2234,7 +2243,7 @@ public: Vertex_point_map vertexPointMap, const Traits& traits = Traits()) : m_traits(traits) - , m_graph(const_cast(tm)) + , m_graph(tm) , m_vertexIndexMap(vertexIndexMap) , m_halfedgeIndexMap(halfedgeIndexMap) , m_faceIndexMap(faceIndexMap) diff --git a/Surface_mesh_shortest_path/test/Surface_mesh_shortest_path/Surface_mesh_shortest_path_test_1.cpp b/Surface_mesh_shortest_path/test/Surface_mesh_shortest_path/Surface_mesh_shortest_path_test_1.cpp index d952707649d..f420e43c1a3 100644 --- a/Surface_mesh_shortest_path/test/Surface_mesh_shortest_path/Surface_mesh_shortest_path_test_1.cpp +++ b/Surface_mesh_shortest_path/test/Surface_mesh_shortest_path/Surface_mesh_shortest_path_test_1.cpp @@ -98,7 +98,7 @@ void test_simple_saddle_vertex_mesh() typedef Graph_traits::halfedge_descriptor halfedge_descriptor; typedef Graph_traits::face_descriptor face_descriptor; typedef CGAL::Surface_mesh_shortest_path Surface_mesh_shortest_path; - typedef boost::property_map::type VPM; + typedef boost::property_map::const_type VPM; Traits traits; @@ -197,7 +197,7 @@ void test_simple_saddle_vertex_mesh() collector.m_sequence.clear(); - typedef boost::property_map::type HalfedgeIndexMap; + typedef boost::property_map::const_type HalfedgeIndexMap; HalfedgeIndexMap halfedgeIndexMap(CGAL::get(CGAL::halfedge_external_index, P)); @@ -329,7 +329,7 @@ void test_boundary_mesh() typedef Graph_traits::face_descriptor face_descriptor; typedef Graph_traits::face_iterator face_iterator; typedef CGAL::Surface_mesh_shortest_path Surface_mesh_shortest_path; - typedef boost::property_map::type VPM; + typedef boost::property_map::const_type VPM; Traits traits; @@ -398,7 +398,7 @@ void test_boundary_mesh() Barycentric_coordinates startLocation = construct_barycentric_coordinates(FT(0.1), FT(0.8), FT(0.1)); - typedef boost::property_map::type FaceIndexMap; + typedef boost::property_map::const_type FaceIndexMap; FaceIndexMap faceIndexMap(CGAL::get(CGAL::face_external_index, P)); @@ -462,6 +462,6 @@ int main() shortest_path_regular_tetrahedron(); test_simple_saddle_vertex_mesh(); test_boundary_mesh(); - + return 0; } diff --git a/Surface_mesh_shortest_path/test/Surface_mesh_shortest_path/Surface_mesh_shortest_path_test_2.cpp b/Surface_mesh_shortest_path/test/Surface_mesh_shortest_path/Surface_mesh_shortest_path_test_2.cpp index 5a895e77fc4..06be126c91a 100644 --- a/Surface_mesh_shortest_path/test/Surface_mesh_shortest_path/Surface_mesh_shortest_path_test_2.cpp +++ b/Surface_mesh_shortest_path/test/Surface_mesh_shortest_path/Surface_mesh_shortest_path_test_2.cpp @@ -37,9 +37,9 @@ int main(int argc, char* argv[]) typedef Graph_traits::face_descriptor face_descriptor; typedef Graph_traits::face_iterator face_iterator; typedef CGAL::Surface_mesh_shortest_path Surface_mesh_shortest_path; - typedef boost::property_map::type VIM; - typedef boost::property_map::type HIM; - typedef boost::property_map::type FIM; + typedef boost::property_map::const_type VIM; + typedef boost::property_map::const_type HIM; + typedef boost::property_map::const_type FIM; diff --git a/Surface_mesh_shortest_path/test/Surface_mesh_shortest_path/Surface_mesh_shortest_path_test_3.cpp b/Surface_mesh_shortest_path/test/Surface_mesh_shortest_path/Surface_mesh_shortest_path_test_3.cpp index 31f5198322a..d9884ccb384 100644 --- a/Surface_mesh_shortest_path/test/Surface_mesh_shortest_path/Surface_mesh_shortest_path_test_3.cpp +++ b/Surface_mesh_shortest_path/test/Surface_mesh_shortest_path/Surface_mesh_shortest_path_test_3.cpp @@ -35,8 +35,8 @@ int main(int argc, char* argv[]) typedef Graph_traits::face_descriptor face_descriptor; typedef Graph_traits::face_iterator face_iterator; typedef CGAL::Surface_mesh_shortest_path Surface_mesh_shortest_path; - typedef boost::property_map::type VPM; - typedef boost::property_map::type FIM; + typedef boost::property_map::const_type VPM; + typedef boost::property_map::const_type FIM; typedef CGAL::AABB_face_graph_triangle_primitive AABB_face_graph_primitive; typedef CGAL::AABB_traits AABB_face_graph_traits; diff --git a/Surface_mesh_shortest_path/test/Surface_mesh_shortest_path/Surface_mesh_shortest_path_test_4.cpp b/Surface_mesh_shortest_path/test/Surface_mesh_shortest_path/Surface_mesh_shortest_path_test_4.cpp index 3c57487983c..9593de4bc43 100644 --- a/Surface_mesh_shortest_path/test/Surface_mesh_shortest_path/Surface_mesh_shortest_path_test_4.cpp +++ b/Surface_mesh_shortest_path/test/Surface_mesh_shortest_path/Surface_mesh_shortest_path_test_4.cpp @@ -38,8 +38,8 @@ int main(int argc, char* argv[]) typedef Graph_traits::face_descriptor face_descriptor; typedef Graph_traits::face_iterator face_iterator; typedef CGAL::Surface_mesh_shortest_path Surface_mesh_shortest_path; - typedef boost::property_map::type VPM; - typedef boost::property_map::type FIM; + typedef boost::property_map::const_type VPM; + typedef boost::property_map::const_type FIM; typedef CGAL::AABB_face_graph_triangle_primitive AABB_face_graph_primitive; typedef CGAL::AABB_traits AABB_face_graph_traits; @@ -83,8 +83,8 @@ int main(int argc, char* argv[]) size_t numTrials = 30; - typedef boost::property_map::type VPM ; - typedef boost::property_map::type FIM; + typedef boost::property_map::const_type VPM ; + typedef boost::property_map::const_type FIM; FIM faceIndexMap(get(boost::face_index, polyhedron)); VPM vertexPointMap(get(CGAL::vertex_point, polyhedron)); diff --git a/Surface_mesh_shortest_path/test/Surface_mesh_shortest_path/Surface_mesh_shortest_path_test_5.cpp b/Surface_mesh_shortest_path/test/Surface_mesh_shortest_path/Surface_mesh_shortest_path_test_5.cpp index fac75436061..ee5d2f15c81 100644 --- a/Surface_mesh_shortest_path/test/Surface_mesh_shortest_path/Surface_mesh_shortest_path_test_5.cpp +++ b/Surface_mesh_shortest_path/test/Surface_mesh_shortest_path/Surface_mesh_shortest_path_test_5.cpp @@ -35,9 +35,9 @@ int main(int argc, char* argv[]) typedef Graph_traits::face_iterator face_iterator; typedef CGAL::Surface_mesh_shortest_path Surface_mesh_shortest_path; typedef Surface_mesh_shortest_path::Face_location Face_location; - typedef boost::property_map::type VIM; - typedef boost::property_map::type HIM; - typedef boost::property_map::type FIM; + typedef boost::property_map::const_type VIM; + typedef boost::property_map::const_type HIM; + typedef boost::property_map::const_type FIM; Traits traits; diff --git a/Surface_mesh_shortest_path/test/Surface_mesh_shortest_path/TestMesh.cpp b/Surface_mesh_shortest_path/test/Surface_mesh_shortest_path/TestMesh.cpp index 89f57b80826..674cf9f7562 100644 --- a/Surface_mesh_shortest_path/test/Surface_mesh_shortest_path/TestMesh.cpp +++ b/Surface_mesh_shortest_path/test/Surface_mesh_shortest_path/TestMesh.cpp @@ -61,11 +61,11 @@ struct TestMeshProgramInstance typedef typename Graph_traits::face_iterator face_iterator; typedef CGAL::Surface_mesh_shortest_path Surface_mesh_shortest_path; typedef typename Surface_mesh_shortest_path::Face_location Face_location; - typedef typename boost::property_map::type VPM; - typedef typename boost::property_map::type VIM; - typedef typename boost::property_map::type EIM; - typedef typename boost::property_map::type HIM; - typedef typename boost::property_map::type FIM; + typedef typename boost::property_map::const_type VPM; + typedef typename boost::property_map::const_type VIM; + typedef typename boost::property_map::const_type EIM; + typedef typename boost::property_map::const_type HIM; + typedef typename boost::property_map::const_type FIM; TestMeshProgramInstance() { diff --git a/Surface_mesh_shortest_path/test/Surface_mesh_shortest_path/include/CGAL/test_util.h b/Surface_mesh_shortest_path/test/Surface_mesh_shortest_path/include/CGAL/test_util.h index 6255de9e733..55d9234e4a4 100644 --- a/Surface_mesh_shortest_path/test/Surface_mesh_shortest_path/include/CGAL/test_util.h +++ b/Surface_mesh_shortest_path/test/Surface_mesh_shortest_path/include/CGAL/test_util.h @@ -41,9 +41,9 @@ struct Sequence_item }; template ::type, - class HIM = typename boost::property_map::type, - class FIM = typename boost::property_map::type> + class VIM = typename boost::property_map::const_type, + class HIM = typename boost::property_map::const_type, + class FIM = typename boost::property_map::const_type> struct Edge_sequence_collector { typedef typename Traits::Triangle_mesh Triangle_mesh; From eebaf7fb4d39f91fab0cfccde8db2a1b1d8f030e Mon Sep 17 00:00:00 2001 From: Mael Date: Fri, 31 Jan 2020 11:16:50 +0100 Subject: [PATCH 166/185] Tiny rephrasing --- .../Surface_mesh_shortest_path/Surface_mesh_shortest_path.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Surface_mesh_shortest_path/include/CGAL/Surface_mesh_shortest_path/Surface_mesh_shortest_path.h b/Surface_mesh_shortest_path/include/CGAL/Surface_mesh_shortest_path/Surface_mesh_shortest_path.h index ecf3db7ab5d..4b7f8cb5d3d 100644 --- a/Surface_mesh_shortest_path/include/CGAL/Surface_mesh_shortest_path/Surface_mesh_shortest_path.h +++ b/Surface_mesh_shortest_path/include/CGAL/Surface_mesh_shortest_path/Surface_mesh_shortest_path.h @@ -73,7 +73,7 @@ Refer to those respective papers for the details of the implementation. \tparam VPM a model of `ReadablePropertyMap` with `vertex_descriptor` as key and `Traits::Point_3` as value type. The default is `boost::property_map::%const_type`. -If no property map is provided through the constructor of the class, the internal property maps must +If index property maps are not provided through the constructor of the class, internal property maps must be available and initialized. \sa \link PkgBGLHelper `CGAL::set_halfedgeds_items_id()`\endlink From 42a03ae1683231cd24b97f2ab82e9ea176e75c23 Mon Sep 17 00:00:00 2001 From: Mael Date: Mon, 3 Feb 2020 10:29:35 +0100 Subject: [PATCH 167/185] Add missing header --- .../Polygon_mesh_processing/hole_filling_example_SM.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/hole_filling_example_SM.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/hole_filling_example_SM.cpp index 960fc7d9c51..6eb8bd06195 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/hole_filling_example_SM.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/hole_filling_example_SM.cpp @@ -4,6 +4,8 @@ #include #include +#include + #include #include #include From 071fe09661be34c69b2b22f11f198dd7a402cc12 Mon Sep 17 00:00:00 2001 From: Mael Date: Mon, 3 Feb 2020 10:30:17 +0100 Subject: [PATCH 168/185] Add missing example name --- Polygon_mesh_processing/doc/Polygon_mesh_processing/examples.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/examples.txt b/Polygon_mesh_processing/doc/Polygon_mesh_processing/examples.txt index a9350578648..194199ba808 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/examples.txt +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/examples.txt @@ -2,6 +2,7 @@ \example Polygon_mesh_processing/self_intersections_example.cpp \example Polygon_mesh_processing/hole_filling_example.cpp +\example Polygon_mesh_processing/hole_filling_example_SM.cpp \example Polygon_mesh_processing/stitch_borders_example.cpp \example Polygon_mesh_processing/compute_normals_example.cpp \example Polygon_mesh_processing/point_inside_example.cpp From 7020ec88937b5c3a9ed9899d3928960fdde1da19 Mon Sep 17 00:00:00 2001 From: Mael Date: Mon, 3 Feb 2020 11:15:08 +0100 Subject: [PATCH 169/185] Fix lack of capital M in 'CMakeLists.txt' Co-Authored-By: Sebastien Loriot --- INSTALL.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 8b12e288e91..c2c9526c05e 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -20,7 +20,7 @@ Building a Program Using CGAL ============================= If you wish to build a program that is not provided with CGAL and does not already have a `CMakeLists.txt`, -you can trigger the creation of a basic `CmakeLists.txt` by calling the script [`cgal_create_cmake_script`](Scripts/scripts/cgal_create_cmake_script) +you can trigger the creation of a basic `CMakeLists.txt` by calling the script [`cgal_create_cmake_script`](Scripts/scripts/cgal_create_cmake_script) found in `/path/to/cgal.git/Scripts/scripts/` at the root of your program directory. ``` {.bash} @@ -33,12 +33,12 @@ found in `/path/to/cgal.git/Scripts/scripts/` at the root of your program direct make your_program ``` -Since the basic `CmakeLists.txt` created by the script `cgal_create_cmake_script` cannot +Since the basic `CMakeLists.txt` created by the script `cgal_create_cmake_script` cannot guess which part(s) of CGAL you are using, it does not link with any optional third party dependency of CGAL. You should look at the documentation of the package(s) that you -are using to learn which dependencies you must add. The `CmakeLists.txt` +are using to learn which dependencies you must add. The `CMakeLists.txt` of the examples and demos provided with the package(s) that you are using can be used -to complete your basic `CmakeLists.txt`. +to complete your basic `CMakeLists.txt`. Repository Structure From 2632f960027095fa2638fe2ebf90d34e393fe37c Mon Sep 17 00:00:00 2001 From: Mael Date: Mon, 3 Feb 2020 12:11:41 +0100 Subject: [PATCH 170/185] Fix value type --- .../CGAL/Polygon_mesh_processing/connected_components.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/connected_components.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/connected_components.h index fa332c05e10..4935db60735 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/connected_components.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/connected_components.h @@ -217,9 +217,9 @@ connected_components(const PolygonMesh& pmesh, = choose_parameter(get_parameter(np, internal_np::edge_is_constrained), internal::No_constraint()); - typename GetFaceIndexMap::const_type - fimap = choose_parameter(get_parameter(np, internal_np::face_index), - get_const_property_map(boost::face_index, pmesh)); + typedef typename GetFaceIndexMap::const_type FaceIndexMap; + FaceIndexMap fimap = choose_parameter(get_parameter(np, internal_np::face_index), + get_const_property_map(boost::face_index, pmesh)); typename boost::property_traits::value_type i=0; std::vector handled(num_faces(pmesh), false); @@ -232,7 +232,7 @@ connected_components(const PolygonMesh& pmesh, { face_descriptor fq = queue.back(); queue.pop_back(); - typename boost::property_traits::value_type fq_id = get(fimap,fq); + typename boost::property_traits::value_type fq_id = get(fimap,fq); if ( handled[fq_id]) continue; handled[fq_id]=true; put(fcm, fq, i); From f5197b3df7f542760d487dc118871dd2788f0ef2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 4 Feb 2020 14:16:32 +0100 Subject: [PATCH 171/185] use real size --- .../demo/Polyhedron/Plugins/PMP/Repair_polyhedron_plugin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Repair_polyhedron_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Repair_polyhedron_plugin.cpp index 1e8fb6578ef..92da2e43934 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Repair_polyhedron_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Repair_polyhedron_plugin.cpp @@ -182,10 +182,10 @@ void Polyhedron_demo_repair_polyhedron_plugin::on_actionRemoveDegenerateFaces_tr qobject_cast(scene->item(index)); if (poly_item) { - std::size_t nbv = num_faces(*poly_item->polyhedron()); + std::size_t nbv = faces(*poly_item->polyhedron()).size(); CGAL::Polygon_mesh_processing::remove_degenerate_faces( *poly_item->polyhedron()); - nbv -= num_faces(*poly_item->polyhedron()); + nbv -= faces(*poly_item->polyhedron()).size(); poly_item->invalidateOpenGLBuffers(); Q_EMIT poly_item->itemChanged(); CGAL::Three::Three::information(tr(" %1 degenerate faces have been removed.") From eec9b0b2270ec5a48816ad3b5b7eb2b9c752c02b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 3 Feb 2020 18:24:08 +0100 Subject: [PATCH 172/185] Fix corner case in sin weight normal computations --- .../include/CGAL/Polygon_mesh_processing/compute_normal.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/compute_normal.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/compute_normal.h index a4ba7099f7b..a149ef1155f 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/compute_normal.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/compute_normal.h @@ -535,10 +535,14 @@ compute_vertex_normal_as_sum_of_weighted_normals(typename boost::graph_traits Date: Mon, 3 Feb 2020 18:10:41 +0100 Subject: [PATCH 173/185] Fix some corner cases with the new compute normals and degenerate faces --- .../Polygon_mesh_processing/compute_normal.h | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/compute_normal.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/compute_normal.h index a149ef1155f..0c254332e78 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/compute_normal.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/compute_normal.h @@ -311,18 +311,18 @@ typename GT::Vector_3 compute_normals_bisector(const typename GT::Vector_3& ni, Vector_3 nb = cv_3(CGAL::NULL_VECTOR); - if(almost_equal(ni, nj, traits)) + if(almost_equal(ni, nj, traits) || nk == CGAL::NULL_VECTOR) { if(almost_equal(nj, nk, traits)) nb = ni; else // ni == nj, but nij != nk nb = compute_normals_bisector(nj, nk, traits); } - else if(almost_equal(ni, nk, traits)) // ni != nj + else if(almost_equal(ni, nk, traits) || nj == CGAL::NULL_VECTOR) // ni != nj { nb = compute_normals_bisector(nj, nk, traits); } - else if(almost_equal(nj, nk, traits)) // ni != nj, ni != nk + else if(almost_equal(nj, nk, traits) || ni == CGAL::NULL_VECTOR) // ni != nj, ni != nk { nb = compute_normals_bisector(ni, nk, traits); } @@ -345,7 +345,7 @@ typename GT::Vector_3 compute_normals_bisector(const typename GT::Vector_3& ni, return csv_3(csv_3(cslv_3(ni, third), cslv_3(nj, third)), cslv_3(nk, third)); } - nb = cv_3(CGAL::ORIGIN, c); // note that this isn't normalized + nb = cv_3(CGAL::ORIGIN, c); // not normalized } return nb; @@ -432,6 +432,10 @@ compute_most_visible_normal_3_points(const std::vector 2); + // The vertex has only two incident faces with opposite normals (fold)... + // @todo devise something based on the directions of the 2/3/4 incident edges? + if(incident_faces.size() == 2 && res == CGAL::NULL_VECTOR) + return res; + + CGAL_assertion(incident_faces.size() >= 2); return compute_most_visible_normal_3_points(incident_faces, face_normals, traits); } From 55afaf713f08d6030e3b5a835889016a4fe30744 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 4 Feb 2020 15:58:00 +0100 Subject: [PATCH 174/185] Add some tests of meshes with degeneracies --- .../pmp_compute_normals_test.cpp | 71 +++++++++++++++++-- 1 file changed, 66 insertions(+), 5 deletions(-) diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/pmp_compute_normals_test.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/pmp_compute_normals_test.cpp index ef4e8a08f8a..a243df48db2 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/pmp_compute_normals_test.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/pmp_compute_normals_test.cpp @@ -1,4 +1,4 @@ -// #define CGAL_PMP_COMPUTE_NORMAL_DEBUG +// #define CGAL_PMP_COMPUTE_NORMAL_DEBUG_PP #include #include @@ -6,7 +6,10 @@ #include #include +#include #include +#include +#include #include #include @@ -27,6 +30,7 @@ void test(const Mesh& mesh, typedef typename K::Vector_3 Vector; typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; typedef typename CGAL::GetVertexPointMap::const_type VPMap; @@ -63,12 +67,58 @@ void test(const Mesh& mesh, PMP::compute_normals(mesh, vnormals, fnormals, CGAL::parameters::vertex_point_map(vpmap) .geom_traits(K())); - for(vertex_descriptor v : vertices(mesh)) { - assert(get(vnormals, v) != CGAL::NULL_VECTOR); +#if 1//def CGAL_PMP_COMPUTE_NORMAL_DEBUG_PP + std::ofstream vn_out("vertex_normals.cgal.polylines.txt"); + std::ofstream fn_out("face_normals.cgal.polylines.txt"); + + const CGAL::Bbox_3 bb = PMP::bbox(mesh); + const auto bbox_diagonal = CGAL::sqrt(CGAL::square(bb.xmax() - bb.xmin()) + + CGAL::square(bb.ymax() - bb.ymin()) + + CGAL::square(bb.zmax() - bb.zmin())); + + for(vertex_descriptor v : vertices(mesh)) + vn_out << "2 " << get(vpmap, v) << " " << get(vpmap, v) + 0.1 * bbox_diagonal * get(vnormals, v) << "\n"; + vn_out.close(); + + for(face_descriptor f : faces(mesh)) + { + std::list vertices; + for(halfedge_descriptor h : CGAL::halfedges_around_face(halfedge(f, mesh), mesh)) + vertices.push_back(get(vpmap, target(h, mesh))); + + const typename K::Point_3& c = CGAL::centroid(vertices.begin(), vertices.end()); + fn_out << "2 " << c << " " << c + 0.1 * bbox_diagonal * get(fnormals, f) << "\n"; + } + fn_out.close(); +#endif + + // Check sanity of output + for(const face_descriptor f : faces(mesh)) + { + // tests on non triangular meshes are @todo + if(CGAL::is_triangle(halfedge(f, mesh), mesh)) + { + if(PMP::is_degenerate_triangle_face(f, mesh)) + assert(get(fnormals, f) == CGAL::NULL_VECTOR); + else + assert(get(fnormals, f) != CGAL::NULL_VECTOR); + } } - for(face_descriptor f : faces(mesh)) { - assert(get(fnormals, f) != CGAL::NULL_VECTOR); + for(const vertex_descriptor v : vertices(mesh)) + { + if(get(vnormals, v) == CGAL::NULL_VECTOR) + { + for(halfedge_descriptor h : CGAL::halfedges_around_face(halfedge(v, mesh), mesh)) + { + if(!is_border(h, mesh)) + { + // There are other cases where a vertex normal can be null without the face normals being null, + // (only two incident faces with opposite normals, for example), but they are not tested for now. + assert(get(fnormals, face(h, mesh)) == CGAL::NULL_VECTOR); + } + } + } } } @@ -161,6 +211,17 @@ int main() test("data/mannequin-devil.off"); test("data/U.off"); + test("data_degeneracies/deg_on_border.off"); + test("data_degeneracies/degtri_edge.off"); + test("data_degeneracies/degtri_three.off"); + test("data_degeneracies/degtri_four.off"); + test("data_degeneracies/degtri_nullface.off"); + test("data_degeneracies/degtri_single.off"); + test("data_degeneracies/existing_flip.off"); + test("data_degeneracies/fused_vertices.off"); + test("data_degeneracies/small_ccs.off"); + test("data_degeneracies/trihole.off"); + std::cerr << "All done." << std::endl; return EXIT_SUCCESS; } From 0c05fc6e80ce6e59686e15628f8cac02e6ba73d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 4 Feb 2020 15:56:55 +0100 Subject: [PATCH 175/185] More fixes for normal computations of meshes with degenerate faces --- .../include/CGAL/Polygon_mesh_processing/compute_normal.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/compute_normal.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/compute_normal.h index 0c254332e78..3600992a7e0 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/compute_normal.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/compute_normal.h @@ -265,6 +265,8 @@ bool does_enclose_other_normals(const std::size_t i, const std::size_t j, const continue; const Vector_ref nl = get(face_normals, incident_faces[l]); + if(nl == CGAL::NULL_VECTOR) + continue; // this is a bound on how much the scalar product between (v1,v2) and (v1, v3) can change // when the angle changes theta_bound := 0.01° @@ -432,9 +434,8 @@ compute_most_visible_normal_3_points(const std::vector Date: Tue, 4 Feb 2020 18:15:04 +0100 Subject: [PATCH 176/185] Use new tag in PMP tests --- .../self_intersection_surface_mesh_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/self_intersection_surface_mesh_test.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/self_intersection_surface_mesh_test.cpp index 6d468a267d1..32ddf4b2b6b 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/self_intersection_surface_mesh_test.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/self_intersection_surface_mesh_test.cpp @@ -35,7 +35,7 @@ test_self_intersections(const char* filename, const bool expected) timer.start(); std::vector > intersected_tris; - CGAL::Polygon_mesh_processing::self_intersections( + CGAL::Polygon_mesh_processing::self_intersections( m, std::back_inserter(intersected_tris), CGAL::parameters::vertex_index_map(get(CGAL::vertex_point, m))); @@ -45,7 +45,7 @@ test_self_intersections(const char* filename, const bool expected) std::cout << intersected_tris.size() << " pairs of triangles are intersecting." << std::endl; timer.reset(); - bool intersecting_2 = CGAL::Polygon_mesh_processing::does_self_intersect(m, + bool intersecting_2 = CGAL::Polygon_mesh_processing::does_self_intersect(m, CGAL::Polygon_mesh_processing::parameters::vertex_index_map(get(CGAL::vertex_point, m))); std::cout << "does_self_intersect test took " << timer.time() << " sec." << std::endl; From c2f99dc723a7ed63c500e07be0798bbdfe7966b1 Mon Sep 17 00:00:00 2001 From: Mael Date: Tue, 4 Feb 2020 18:18:45 +0100 Subject: [PATCH 177/185] Actually use TBB in test... --- .../test/Polygon_mesh_processing/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt index 40a606b3124..31851957f1a 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt @@ -98,6 +98,7 @@ endif() if( TBB_FOUND ) CGAL_target_use_TBB(test_pmp_distance) + CGAL_target_use_TBB(self_intersection_surface_mesh_test) else() message( STATUS "NOTICE: Intel TBB was not found. test_pmp_distance will use sequential code." ) endif() From f118be1cbf9b3c0f9c0b5aaa1dc15deb1bf7e57b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 5 Feb 2020 09:35:41 +0100 Subject: [PATCH 178/185] Add missing data files --- .../data_degeneracies/deg_on_border.off | 10 ++++++++++ .../data_degeneracies/existing_flip.off | 19 +++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 Polygon_mesh_processing/test/Polygon_mesh_processing/data_degeneracies/deg_on_border.off create mode 100644 Polygon_mesh_processing/test/Polygon_mesh_processing/data_degeneracies/existing_flip.off diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data_degeneracies/deg_on_border.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data_degeneracies/deg_on_border.off new file mode 100644 index 00000000000..d8518b7cdfb --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data_degeneracies/deg_on_border.off @@ -0,0 +1,10 @@ +OFF +5 3 0 +0 0 0 +1 0 0 +2 -1 0 +3 -1 0 +4 0 0 +3 0 1 4 +3 1 2 3 +3 1 3 4 diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data_degeneracies/existing_flip.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data_degeneracies/existing_flip.off new file mode 100644 index 00000000000..cca5987fabe --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data_degeneracies/existing_flip.off @@ -0,0 +1,19 @@ +OFF +7 10 0 +0.314482809221655 -0.012877345839067217 -0.24601469358849659 +-0.081905665816609866 0.11959178909305103 0.59582950965713732 +1 1 0 +0.5 0.5 1 +0.75 0.75 0.5 +0.67302179212919955 0.77012616600142381 -0.44072953863256931 +0.14300722468117555 0.12954038296069673 0.88891433254868446 +3 0 5 2 +3 0 3 6 +3 5 0 4 +3 2 4 3 +3 4 0 1 +3 4 1 6 +3 4 2 5 +3 3 0 2 +3 6 3 4 +3 6 1 0 From 8773cee832570e6d54e1b156e5be3be316696eb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 5 Feb 2020 10:54:11 +0100 Subject: [PATCH 179/185] Minor code improvements --- .../include/CGAL/box_intersection_d.h | 2 + .../self_intersections.h | 40 ++++++++++--------- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/Box_intersection_d/include/CGAL/box_intersection_d.h b/Box_intersection_d/include/CGAL/box_intersection_d.h index fb70c7ad6c2..94752c41462 100644 --- a/Box_intersection_d/include/CGAL/box_intersection_d.h +++ b/Box_intersection_d/include/CGAL/box_intersection_d.h @@ -186,6 +186,8 @@ void box_intersection_segment_tree_d( It r1_end = (r1_endi == -1) ? range_1_copies.end() : range_1_iterators[r1_endi][r1_endj]; It r2_start = range_2_iterators[i][(j+i)%n]; It r2_end = (r2_endi == -1) ? range_2_copies.end() : range_2_iterators[r2_endi][r2_endj]; + CGAL_assertion(range_1_copies.begin() <= r1_start && r1_start <= r1_end && r1_end <= range_1_copies.end()); + CGAL_assertion(range_2_copies.begin() <= r2_start && r2_start <= r2_end && r2_end <= range_2_copies.end()); // Specify "copy by value" otherwise the values of iterators for next (i,j) iterations // become shared with different lambdas being run in parallel, and things go wrong diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h index 55563d8b1da..c3a06220c53 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/self_intersections.h @@ -74,6 +74,9 @@ bool do_faces_intersect(typename boost::graph_traits::halfedge_descriptor h, typedef typename GT::Segment_3 Segment; typedef typename GT::Triangle_3 Triangle; + CGAL_assertion(!is_border(h, tmesh)); + CGAL_assertion(!is_border(g, tmesh)); + vertex_descriptor hv[3], gv[3]; hv[0] = target(h, tmesh); hv[1] = target(next(h, tmesh), tmesh); @@ -83,12 +86,10 @@ bool do_faces_intersect(typename boost::graph_traits::halfedge_descriptor h, gv[1] = target(next(g, tmesh), tmesh); gv[2] = source(g, tmesh); - halfedge_descriptor opp_h; - // check for shared edge for(unsigned int i=0; i<3; ++i) { - opp_h = opposite(h, tmesh); + halfedge_descriptor opp_h = opposite(h, tmesh); if(face(opp_h, tmesh) == face(g, tmesh)) { // there is an intersection if the four points are coplanar and the triangles overlap @@ -138,11 +139,11 @@ bool do_faces_intersect(typename boost::graph_traits::halfedge_descriptor h, CGAL_assertion(hv[i] == gv[j]); // geometric check if the opposite segments intersect the triangles - Triangle t1 = construct_triangle(get(vpmap, hv[0]), get(vpmap, hv[1]), get(vpmap, hv[2])); - Triangle t2 = construct_triangle(get(vpmap, gv[0]), get(vpmap, gv[1]), get(vpmap, gv[2])); + const Triangle t1 = construct_triangle(get(vpmap, hv[0]), get(vpmap, hv[1]), get(vpmap, hv[2])); + const Triangle t2 = construct_triangle(get(vpmap, gv[0]), get(vpmap, gv[1]), get(vpmap, gv[2])); - Segment s1 = construct_segment(get(vpmap, hv[(i+1)%3]), get(vpmap, hv[(i+2)%3]) ); - Segment s2 = construct_segment(get(vpmap, gv[(j+1)%3]), get(vpmap, gv[(j+2)%3])); + const Segment s1 = construct_segment(get(vpmap, hv[(i+1)%3]), get(vpmap, hv[(i+2)%3])); + const Segment s2 = construct_segment(get(vpmap, gv[(j+1)%3]), get(vpmap, gv[(j+2)%3])); if(do_intersect(t1, s2)) return true; @@ -153,9 +154,9 @@ bool do_faces_intersect(typename boost::graph_traits::halfedge_descriptor h, } // check for geometric intersection - Triangle t1 = construct_triangle(get(vpmap, hv[0]), get(vpmap, hv[1]), get(vpmap, hv[2])); - Triangle t2 = construct_triangle(get(vpmap, gv[0]), get(vpmap, gv[1]), get(vpmap, gv[2])); - if(do_intersect(t1, t2)) + const Triangle th = construct_triangle(get(vpmap, hv[0]), get(vpmap, hv[1]), get(vpmap, hv[2])); + const Triangle tg = construct_triangle(get(vpmap, gv[0]), get(vpmap, gv[1]), get(vpmap, gv[2])); + if(do_intersect(th, tg)) return true; return false; @@ -163,7 +164,7 @@ bool do_faces_intersect(typename boost::graph_traits::halfedge_descriptor h, template -struct Strict_intersect_faces // meaning, not just a shared subface +struct Strict_intersect_faces // "strict" as in "not sharing a subface" { typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; @@ -186,8 +187,8 @@ struct Strict_intersect_faces // meaning, not just a shared subface void operator()(const Box* b, const Box* c) const { - halfedge_descriptor h = halfedge(b->info(), m_tmesh); - halfedge_descriptor g = halfedge(c->info(), m_tmesh); + const halfedge_descriptor h = halfedge(b->info(), m_tmesh); + const halfedge_descriptor g = halfedge(c->info(), m_tmesh); if(do_faces_intersect(h, g, m_tmesh, m_vpmap, m_construct_segment, m_construct_triangle, m_do_intersect)) *m_iterator++ = std::make_pair(b->info(), c->info()); @@ -212,6 +213,7 @@ self_intersections_impl(const FaceRange& face_range, using CGAL::parameters::get_parameter; typedef TriangleMesh TM; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; typedef CGAL::Box_intersection_d::ID_FROM_BOX_ADDRESS Box_policy; @@ -236,10 +238,11 @@ self_intersections_impl(const FaceRange& face_range, // This loop is very cheap, so there is hardly anything to gain from parallelizing it for(face_descriptor f : face_range) { + halfedge_descriptor h = halfedge(f, tmesh); typename boost::property_traits::reference - p = get(vpmap, target(halfedge(f,tmesh),tmesh)), - q = get(vpmap, target(next(halfedge(f, tmesh), tmesh), tmesh)), - r = get(vpmap, target(next(next(halfedge(f, tmesh), tmesh), tmesh), tmesh)); + p = get(vpmap, target(h,tmesh)), + q = get(vpmap, target(next(h, tmesh), tmesh)), + r = get(vpmap, target(prev(h, tmesh), tmesh)); // tiny fixme: if f is degenerate, we might still have a real intersection between f // and another face f', but right now we are not creating a box for f and thus not returning those @@ -302,15 +305,16 @@ self_intersections_impl(const FaceRange& face_range, return out; } #endif + // Sequential version of the code // Compute self-intersections filtered out by boxes typedef internal::Strict_intersect_faces Intersecting_faces_filter; Intersecting_faces_filter intersect_faces(tmesh, vpmap, gt, out); if(throw_on_SI) - CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(), throwing_filter, cutoff); + CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(), throwing_filter, cutoff); else - CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(), intersect_faces, cutoff); + CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(), intersect_faces, cutoff); return intersect_faces.m_iterator; } From 4bc3d850218ed14f469be2914e20ae2d950286a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 5 Feb 2020 10:54:26 +0100 Subject: [PATCH 180/185] Don't test parallel features with EPECK, since it's not threadsafe --- .../self_intersection_surface_mesh_test.cpp | 73 ++++++++++++------- 1 file changed, 47 insertions(+), 26 deletions(-) diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/self_intersection_surface_mesh_test.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/self_intersection_surface_mesh_test.cpp index 32ddf4b2b6b..11cb16b40a7 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/self_intersection_surface_mesh_test.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/self_intersection_surface_mesh_test.cpp @@ -11,12 +11,15 @@ #include #include -typedef CGAL::Exact_predicates_inexact_constructions_kernel Epic; -typedef CGAL::Exact_predicates_exact_constructions_kernel Epec; +typedef CGAL::Exact_predicates_inexact_constructions_kernel EPICK; +typedef CGAL::Exact_predicates_exact_constructions_kernel EPECK; + +namespace PMP = ::CGAL::Polygon_mesh_processing; +namespace CP = ::CGAL::parameters; template -int -test_self_intersections(const char* filename, const bool expected) +int test_self_intersections(const char* filename, + const bool expected) { typedef CGAL::Surface_mesh Mesh; typedef typename boost::graph_traits::face_descriptor face_descriptor; @@ -35,18 +38,36 @@ test_self_intersections(const char* filename, const bool expected) timer.start(); std::vector > intersected_tris; - CGAL::Polygon_mesh_processing::self_intersections( - m, - std::back_inserter(intersected_tris), - CGAL::parameters::vertex_index_map(get(CGAL::vertex_point, m))); + + if(std::is_same::value) // EPECK isn't threadsafe + { + PMP::self_intersections( + m, std::back_inserter(intersected_tris), CP::vertex_index_map(get(CGAL::vertex_point, m))); + } + else + { + PMP::self_intersections( + m, std::back_inserter(intersected_tris), CP::vertex_index_map(get(CGAL::vertex_point, m))); + } bool intersecting_1 = !intersected_tris.empty(); std::cout << "self_intersections test took " << timer.time() << " sec." << std::endl; std::cout << intersected_tris.size() << " pairs of triangles are intersecting." << std::endl; timer.reset(); - bool intersecting_2 = CGAL::Polygon_mesh_processing::does_self_intersect(m, - CGAL::Polygon_mesh_processing::parameters::vertex_index_map(get(CGAL::vertex_point, m))); + + bool intersecting_2; + + if(std::is_same::value) // EPECK isn't threadsafe + { + intersecting_2 = PMP::does_self_intersect( + m, CP::vertex_index_map(get(CGAL::vertex_point, m))); + } + else + { + intersecting_2 = PMP::does_self_intersect( + m, CP::vertex_index_map(get(CGAL::vertex_point, m))); + } std::cout << "does_self_intersect test took " << timer.time() << " sec." << std::endl; std::cout << (intersecting_2 ? "There is a self-intersection." : @@ -77,11 +98,11 @@ int main(int argc, char** argv) assert(!ss.fail()); // make sure that argv[2] is either 'true' or 'false' } - std::cout << "First test (Epic):" << std::endl; - int r = test_self_intersections(filename, expected); + std::cout << "First test (EPICK):" << std::endl; + int r = test_self_intersections(filename, expected); - std::cout << "First test (Epec):" << std::endl; - r += test_self_intersections(filename, expected); + std::cout << "First test (EPECK):" << std::endl; + r += test_self_intersections(filename, expected); // Second test --------------------------------------------------------------- expected = true; @@ -93,11 +114,11 @@ int main(int argc, char** argv) assert(!ss.fail()); } - std::cout << "Second test (Epic):" << std::endl; - r += test_self_intersections(filename, expected); + std::cout << "Second test (EPICK):" << std::endl; + r += test_self_intersections(filename, expected); - std::cout << "Second test (Epec):" << std::endl; - r += test_self_intersections(filename, expected); + std::cout << "Second test (EPECK):" << std::endl; + r += test_self_intersections(filename, expected); // Third test ---------------------------------------------------------------- expected = true; @@ -109,11 +130,11 @@ int main(int argc, char** argv) assert(!ss.fail()); } - std::cout << "Third test (Epic):" << std::endl; - r += test_self_intersections(filename, expected); + std::cout << "Third test (EPICK):" << std::endl; + r += test_self_intersections(filename, expected); - std::cout << "Third test (Epec):" << std::endl; - r += test_self_intersections(filename, expected); + std::cout << "Third test (EPECK):" << std::endl; + r += test_self_intersections(filename, expected); // Fourth test ---------------------------------------------------------------- expected = true; @@ -125,11 +146,11 @@ int main(int argc, char** argv) assert(!ss.fail()); } - std::cout << "Fourth test (Epic):" << std::endl; - r += test_self_intersections(filename, expected); + std::cout << "Fourth test (EPICK):" << std::endl; + r += test_self_intersections(filename, expected); - std::cout << "Fourth test (Epec):" << std::endl; - r += test_self_intersections(filename, expected); + std::cout << "Fourth test (EPECK):" << std::endl; + r += test_self_intersections(filename, expected); return r; } From dca752395e7ba189bd7202442421be01e7fd3ce8 Mon Sep 17 00:00:00 2001 From: Mael Date: Wed, 5 Feb 2020 18:28:08 +0100 Subject: [PATCH 181/185] Remove assertion --- .../include/CGAL/Polygon_mesh_processing/compute_normal.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/compute_normal.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/compute_normal.h index 3600992a7e0..7c8925c2797 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/compute_normal.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/compute_normal.h @@ -388,8 +388,6 @@ compute_most_visible_normal_2_points(std::vector= - std::numeric_limits::epsilon()); - sp_bi = (std::max)(FT(0), sp_bi); if(sp_bi <= min_sp) continue; From 4eeb7f1a800aabde557cb940123a465cd7991be3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 6 Feb 2020 11:57:04 +0100 Subject: [PATCH 182/185] Copy comparer by const& --- Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h | 4 +++- Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h b/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h index 3d389481e97..23e87f7ac7b 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h @@ -139,7 +139,9 @@ public: RandomAccessIterator begin, end; const Comp& comp; - Hilbert_split(RandomAccessIterator& res, RandomAccessIterator begin, RandomAccessIterator end, const Comp comp) + Hilbert_split(RandomAccessIterator& res, + RandomAccessIterator begin, RandomAccessIterator end, + const Comp& comp) : res(res), begin(begin), end(end), comp(comp) {} diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h b/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h index 0536ef8be94..0ea51bb24bc 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h @@ -156,7 +156,9 @@ public: RandomAccessIterator begin, end; const Comp& comp; - Hilbert_split(RandomAccessIterator& res, RandomAccessIterator begin, RandomAccessIterator end, const Comp comp) + Hilbert_split(RandomAccessIterator& res, + RandomAccessIterator begin, RandomAccessIterator end, + const Comp& comp) : res(res), begin(begin), end(end), comp(comp) {} From 8ac61eae0dc48417fa2f985779ee8e234b424820 Mon Sep 17 00:00:00 2001 From: Mael Date: Fri, 7 Feb 2020 10:58:47 +0100 Subject: [PATCH 183/185] Update CHANGES.md --- Installation/CHANGES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 736a64839c6..4ccf1ab216c 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -65,6 +65,10 @@ Release date: June 2020 k-NN search to interrupt some distance computations before its end, saving precious milliseconds, in particular in medium-to-high dimension. +### Spatial Sorting + - Added parallel versions of `hilbert_sort()` and `spatial_sort()` in 2D and 3D when the median policy is used. + The parallel versions use up to four threads in 2D, and up to eight threads in 3D. + ### dD Geometry Kernel - Epick\_d and Epeck\_d gain 2 new functors: `Power_side_of_bounded_power_sphere_d` and `Compute_squared_radius_smallest_orthogonal_sphere_d`. Those are From 5c9eb2fdfe0282a276ccd4db89f9a4beb6cf0af8 Mon Sep 17 00:00:00 2001 From: Mael Date: Fri, 7 Feb 2020 11:10:15 +0100 Subject: [PATCH 184/185] Update CHANGES.md --- Installation/CHANGES.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 736a64839c6..646ca085b5f 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -18,6 +18,9 @@ Release date: June 2020 - **Breaking change**: the internal search tree is now lazily constructed. To disable it, one must call the new function `do_not_accelerate_distance_queries()` before the first distance query. +### Intersecting Sequences of dD Iso-oriented Boxes + - Added parallel versions of the functions `CGAL::box_intersection_d()` and `CGAL::box_self_intersection_d()`. + ### Polygon Mesh Processing - Introduced a new function, `CGAL::Polygon_mesh_processing::remove_connected_components_of_negligible_size()`, @@ -28,6 +31,8 @@ Release date: June 2020 components that would be removed with the specified threshold, but without actually removing them. - The function `CGAL::Polygon_mesh_processing::stitch_borders()` now returns the number of halfedge pairs that were stitched. + - Added parallel versions of the functions `CGAL::Polygon_mesh_processing::does_self_intersect()` + and `CGAL::Polygon_mesh_processing::self_intersections()`. ### 2D Triangulations - To fix an inconsistency between code and documentation and to clarify which types of intersections From 406b6faec0ae7f39dcf0964e8ef26e4650405e5e Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 11 Feb 2020 13:59:56 +0100 Subject: [PATCH 185/185] Fix: retrieving FPU rounding mode broken on mips Fix issue #4399. --- Number_types/include/CGAL/FPU.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Number_types/include/CGAL/FPU.h b/Number_types/include/CGAL/FPU.h index 1ed1d728d34..1d290381603 100644 --- a/Number_types/include/CGAL/FPU.h +++ b/Number_types/include/CGAL/FPU.h @@ -408,7 +408,7 @@ typedef unsigned int FPU_CW_t; #elif defined __mips__ #define CGAL_IA_SETFPCW(CW) asm volatile ("ctc1 %0,$31" : :"r" (CW)) -#define CGAL_IA_GETFPCW(CW) asm volatile ("cfc1 %0,$31" : "=r" (CW)) +#define CGAL_IA_GETFPCW(CW) asm volatile ("cfc1 %0,$31" : "=r" (CW)); CW &= 3 typedef unsigned int FPU_CW_t; #define CGAL_FE_TONEAREST (0x0) #define CGAL_FE_TOWARDZERO (0x1)