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(), 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/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/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..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 @@ -242,6 +242,29 @@ 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. 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 + 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 +297,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 +315,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 +514,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 +548,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 +561,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, 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..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 @@ -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, IdPolicy> 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 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..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,7 +23,6 @@ #include #include - #include #include #include @@ -93,6 +91,8 @@ void one_way_scan( RandomAccessIter1 p_begin, RandomAccessIter1 p_end, bool in_order = true ) { typedef typename Traits::Compare Compare; + + // 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 ) ); @@ -323,7 +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 ) + std::ptrdiff_t cutoff, int dim, bool in_order) { typedef typename Predicate_traits::Spanning Spanning; typedef typename Predicate_traits::Lo_less Lo_less; diff --git a/Box_intersection_d/include/CGAL/box_intersection_d.h b/Box_intersection_d/include/CGAL/box_intersection_d.h index d7952400617..94752c41462 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 @@ -25,12 +25,191 @@ #include #include +#include +#include + +#ifdef CGAL_LINKED_WITH_TBB +#include +#endif + +#include #include +//////////////////////////////////////////////////////////////////////////////////////////////// +/// THE CALLBACK MUST BE THREADSAFE IF YOU ARE USING THE PARALLEL MODE +//////////////////////////////////////////////////////////////////////////////////////////////// + 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) + { + // Here is an illustration for n=2. + // + // 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] + // + // 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] + // + // Ranges must be duplicates since sorting is performed + + typedef typename std::iterator_traits::value_type val_t; + typedef typename std::iterator_traits::difference_type diff_size; + + typedef std::vector val_container; + typedef typename val_container::iterator It; + + static constexpr int n = 4; + + const diff_size r1s = std::distance(begin1, end1); + const diff_size r2s = std::distance(begin2, end2); + + val_container range_1_copies, range_2_copies; + range_1_copies.reserve(r1s * n); + range_2_copies.reserve(r2s * n); + + const diff_size r1_step = r1s / n; + const diff_size r2_step = r2s / n; + + for(int i=0; i, n> range_1_iterators; + std::array, n> range_2_iterators; + + for(int i=0; i void box_intersection_custom_predicates_d( RandomAccessIter1 begin1, RandomAccessIter1 end1, @@ -40,23 +219,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, @@ -67,18 +238,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, @@ -86,35 +258,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, @@ -122,53 +298,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 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, @@ -176,49 +357,52 @@ 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); + + 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 > +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, - Box_intersection_d::CLOSED); + 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, @@ -226,10 +410,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, @@ -238,28 +422,27 @@ 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_self_intersection_d(begin, end, callback, + 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, @@ -269,18 +452,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, @@ -293,20 +476,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, @@ -314,12 +497,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, @@ -328,7 +511,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); } @@ -336,7 +519,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; @@ -344,7 +527,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) { @@ -361,17 +544,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/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; } 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 ad3b83c0eef..d25cf4cfd0b 100644 --- a/Classification/include/CGAL/Classification/Local_eigen_analysis.h +++ b/Classification/include/CGAL/Classification/Local_eigen_analysis.h @@ -226,7 +226,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) @@ -242,10 +242,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> @@ -310,7 +308,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) @@ -325,10 +323,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> @@ -396,7 +392,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) @@ -409,10 +405,8 @@ public: template diff --git a/Classification/include/CGAL/Classification/Mesh_feature_generator.h b/Classification/include/CGAL/Classification/Mesh_feature_generator.h index d9baf699327..b68fce17bc8 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 28ec87f5fdb..83779d5518a 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/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); 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..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,7 +41,6 @@ #endif // CGAL_DISABLE_STATIC_FILTERS_ADDED_2011 - #ifndef CGAL_NO_EQUAL_3_STATIC_FILTERS # include # include @@ -65,6 +64,7 @@ # include #endif // NOT NOT CGAL_NO_DO_INTERSECT_STATIC_FILTERS +#include #include #include #include @@ -121,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; @@ -138,28 +139,28 @@ public: { return Collinear_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 @@ -182,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/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/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/INSTALL.md b/INSTALL.md index 8913be934e0..c2c9526c05e 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,8 +1,7 @@ -NOTICE -====== +Building an Example or a Demo of CGAL +===================================== -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: +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 @@ -13,43 +12,41 @@ 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). +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 ============================= -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: +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. ``` {.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 -``` - -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: - -``` {.bash} - cd /path/to/cgal.git/Triangulation_2/examples/Triangulation_2 + git clone https://github.com/CGAL/cgal.git /path/to/cgal.git + cd /path/to/your/program /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 ../.. - make + cmake -DCMAKE_BUILD_TYPE=Debug -DCGAL_DIR:PATH=/path/to/cgal.git ../.. + make your_program ``` -For more information head over to the [CGAL manual](https://doc.cgal.org/latest/Manual/general_intro.html). +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). diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 736a64839c6..ad9ad327281 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 @@ -65,6 +70,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 @@ -75,6 +84,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) ----------- diff --git a/Installation/CMakeLists.txt b/Installation/CMakeLists.txt index db6e3120e77..c96b2b9af03 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) @@ -621,9 +615,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,7 +634,7 @@ 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) + option(WITH_${lib} "Select external library ${lib}" ON) else() option(WITH_${lib} "Select external library ${lib}" OFF) endif() diff --git a/Installation/cmake/modules/CGAL_SetupGMP.cmake b/Installation/cmake/modules/CGAL_SetupGMP.cmake index 1a8c28a3c13..6627df01796 100644 --- a/Installation/cmake/modules/CGAL_SetupGMP.cmake +++ b/Installation/cmake/modules/CGAL_SetupGMP.cmake @@ -23,12 +23,12 @@ 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) +else() + option(CGAL_WITH_GMPXX "Use CGAL with GMPXX: use C++ classes of GNU MP instead of CGAL wrappers" ON) endif() #.rst: diff --git a/Intersections_3/test/Intersections_3/call_test.cpp b/Intersections_3/test/Intersections_3/call_test.cpp index 768c7d4ac6e..96da5418020 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; } 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) 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/Mesh_3/test/Mesh_3/CMakeLists.txt b/Mesh_3/test/Mesh_3/CMakeLists.txt index e76ea6cbb16..525573cbeb4 100644 --- a/Mesh_3/test/Mesh_3/CMakeLists.txt +++ b/Mesh_3/test/Mesh_3/CMakeLists.txt @@ -65,15 +65,15 @@ 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 + 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; 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) 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/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/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 d69d85d9bf4..a01a9eba86e 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 @@ -144,7 +145,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 @@ -350,9 +351,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/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/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 diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt index 95a539040ac..eff0d48d229 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt @@ -109,6 +109,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/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/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/examples/Polygon_mesh_processing/hole_filling_example_SM.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/hole_filling_example_SM.cpp index 47d9d9454e4..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 @@ -2,58 +2,96 @@ #include #include +#include + +#include #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, + double max_hole_diam, int max_num_hole_edges) +{ + int num_hole_edges = 0; + CGAL::Bbox_3 hole_bbox; + for (halfedge_descriptor hc : CGAL::halfedges_around_face(h, mesh)) + { + const Point& p = mesh.point(target(hc, mesh)); + + 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; + } + + 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 unsigned int nb_holes = 0; - for(halfedge_descriptor h : halfedges(mesh)) - { - if(is_border(h,mesh)) - { - 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::vector border_cycles; - 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++; - } + // 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(max_hole_diam > 0 && max_num_hole_edges > 0 && + !is_small_hole(h, mesh, 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::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; 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; 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/self_intersections_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/self_intersections_example.cpp index 93a2de84858..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 @@ -2,12 +2,15 @@ #include #include +#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 +23,25 @@ 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))); + std::cout << "Using parallel mode? " << std::is_same::value << std::endl; - std::cout - << (intersecting ? "There are self-intersections." : "There is no self-intersection.") - << std::endl; + CGAL::Real_timer timer; + timer.start(); + + 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(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; + + std::cout << "Elapsed time (self intersections): " << timer.time() << std::endl; + + return EXIT_SUCCESS; } 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/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h index 0b2e28fd8fa..ca4256c3977 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,9 +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. + * \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`. @@ -386,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. @@ -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 `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 + * \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 `is_cuboid` + * 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 `iso_cuboid`. + */ +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/include/CGAL/Polygon_mesh_processing/compute_normal.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/compute_normal.h index e3696de26ff..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 @@ -6,7 +6,7 @@ // $URL$ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// +// // // Author(s) : Jane Tournois // Mael Rouxel-Labbé @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -264,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° @@ -271,6 +274,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; @@ -308,18 +313,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); } @@ -342,7 +347,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; @@ -382,9 +387,8 @@ compute_most_visible_normal_2_points(std::vector= 0); + FT sp_bi = sp_3(nb, ni); + sp_bi = (std::max)(FT(0), sp_bi); if(sp_bi <= min_sp) continue; @@ -428,6 +432,9 @@ 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); } @@ -531,10 +543,14 @@ compute_vertex_normal_as_sum_of_weighted_normals(typename boost::graph_traits #include #include -#include -#include #include #include @@ -206,6 +204,10 @@ connected_components(const PolygonMesh& pmesh, using parameters::choose_parameter; using parameters::get_parameter; + typedef boost::graph_traits GT; + typedef typename GT::halfedge_descriptor halfedge_descriptor; + typedef typename GT::face_descriptor face_descriptor; + typedef typename internal_np::Lookup_named_param_def < internal_np::edge_is_constrained_t, NamedParameters, @@ -215,22 +217,40 @@ connected_components(const PolygonMesh& pmesh, = choose_parameter(get_parameter(np, internal_np::edge_is_constrained), internal::No_constraint()); - typedef Dual Dual; - typedef boost::filtered_graph > FiniteDual; - Dual dual(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)); - FiniteDual finite_dual(dual, - internal::No_border(pmesh, ecmap)); - - typename GetFaceIndexMap::const_type - fimap = choose_parameter(get_parameter(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 (halfedge_descriptor 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 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 5bc232135b8..7cffba4f20a 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/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 e7778e76441..ab52338fcab 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; @@ -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 c1ee33318a1..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 @@ -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; @@ -141,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 0d036f3522f..f46e8ccd821 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,27 @@ #include -#include -#include -#include -#include -#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 { @@ -401,8 +408,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); @@ -414,12 +423,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; @@ -433,6 +438,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)); @@ -449,7 +455,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()); @@ -459,10 +464,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(), @@ -541,21 +543,16 @@ 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 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; 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) { @@ -571,7 +568,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]), @@ -587,12 +583,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(), @@ -672,34 +663,32 @@ 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) )); - 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; 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) { @@ -730,12 +719,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(), @@ -773,18 +757,15 @@ 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; 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) { @@ -813,10 +794,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(), @@ -856,7 +834,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; @@ -871,6 +851,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) { @@ -878,9 +859,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) { @@ -915,15 +897,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(), @@ -1595,7 +1573,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())); @@ -1604,21 +1584,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; } @@ -1634,7 +1611,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()); } @@ -1827,9 +1804,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/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..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 @@ -21,215 +21,378 @@ #include -#include -#include -#include - -#include - -#include -#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 +#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 -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; +// 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; + + 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); + hv[2] = source(h, tmesh); + + gv[0] = target(g, tmesh); + gv[1] = target(next(g, tmesh), tmesh); + gv[2] = source(g, tmesh); + + // check for shared edge + for(unsigned int i=0; i<3; ++i) + { + 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 + 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; + } } - OutputIterator* m_iterator; - bool* m_intersected; - }; -// typedefs - typedef typename Kernel::Segment_3 Segment; - typedef typename Kernel::Triangle_3 Triangle; + 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 + 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])); + + 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; + else if(do_intersect(t2, s1)) + return true; + + return false; + } + + // check for geometric intersection + 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; +}; + +template +struct Strict_intersect_faces // "strict" as in "not sharing a subface" +{ typedef typename boost::graph_traits::halfedge_descriptor halfedge_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; - mutable bool m_intersected; - mutable boost::function_output_iterator m_iterator_wrapper; + 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) + Strict_intersect_faces(const TM& tmesh, VPM vpmap, const GT& gt, OutputIterator it) : - 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()) - { } + 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 { - halfedge_descriptor h = halfedge(b->info(), m_tmesh); - halfedge_descriptor opp_h; + const halfedge_descriptor h = halfedge(b->info(), m_tmesh); + const halfedge_descriptor g = halfedge(c->info(), m_tmesh); - // 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 - 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)), - 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)), - 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 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); - } - } - - if(v != halfedge_descriptor()){ - // 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))); - - 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))); - - 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, 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))); - if(do_intersect_3_functor(t1, t2)){ - *m_iterator_wrapper++ = std::make_pair(b->info(), c->info()); - } - } // end operator () -}; // end struct Intersect_facets - -struct Throw_at_output { - class Throw_at_output_exception: public std::exception - { }; - - template - void operator()(const T& /* t */) const { - throw Throw_at_output_exception(); + 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()); } }; -}// namespace internal +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)); -namespace Polygon_mesh_processing { + using CGAL::parameters::choose_parameter; + using CGAL::parameters::get_parameter; -#ifndef DOXYGEN_RUNNING -template -OutputIterator -self_intersections( const FaceRange& face_range, - const TriangleMesh& tmesh, - OutputIterator out, - const NamedParameters& np); + 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; + typedef CGAL::Box_intersection_d::Box_with_info_d Box; + + typedef typename GetGeomTraits::type GT; + GT gt = choose_parameter(get_parameter(np, internal_np::geom_traits), GT()); + + typedef typename GetVertexPointMap::const_type VPM; + VPM vpmap = choose_parameter(get_parameter(np, internal_np::vertex_point), + 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; + + // make one box per face + 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) + { + halfedge_descriptor h = halfedge(f, tmesh); + typename boost::property_traits::reference + 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 + if(collinear(p, q, r)) + { + if(throw_on_SI) + throw CGAL::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 + std::vector box_ptr; + box_ptr.reserve(boxes.size()); + + for(Box& b : boxes) + box_ptr.push_back(&b); + + // In case we are throwing, like in `does_self_intersect()`, we keep the geometric test to throw ASAP. + // This is obviously not optimal if there are no or few self-intersections: it would be a greater speed-up + // 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::Strict_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), + "Parallel_tag is enabled but TBB is unavailable."); +#else + if(std::is_convertible::value) + { + // 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; + 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(), callback, cutoff); + + // Sequentially write into the output iterator + for(std::size_t i=0; i 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); + else + CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(), intersect_faces, cutoff); + + return intersect_faces.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 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" + * + * @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 +FacePairOutputIterator +self_intersections(const FaceRange& face_range, + const TriangleMesh& tmesh, + FacePairOutputIterator out) +{ + return self_intersections(face_range, tmesh, out, CGAL::parameters::all_default()); +} +/// \endcond + /** * \ingroup PMP_intersection_grp - * detects and records self-intersections of a triangulated surface mesh. + * 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`, `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 `OutputIterator` holding objects of type * `std::pair::%face_descriptor, boost::graph_traits::%face_descriptor>` * @tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" * @@ -249,181 +412,35 @@ self_intersections( const FaceRange& face_range, * * @return `out` */ -template -OutputIterator -self_intersections(const TriangleMesh& tmesh - , OutputIterator out -#ifdef DOXYGEN_RUNNING - , const NamedParameters& np) -#else - , const Named_function_parameters& np) -#endif +template +FacePairOutputIterator +self_intersections(const TriangleMesh& tmesh, + FacePairOutputIterator 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 -template -OutputIterator -self_intersections(const TriangleMesh& tmesh, OutputIterator out) +template +FacePairOutputIterator +self_intersections(const TriangleMesh& tmesh, FacePairOutputIterator out) { - return self_intersections(tmesh, out, - CGAL::Polygon_mesh_processing::parameters::all_default()); + return self_intersections(faces(tmesh), tmesh, out, parameters::all_default()); } /// \endcond -/*! - * \ingroup PMP_intersection_grp - * Same as above but the self-intersections reported - * are only limited to the faces in `face_range`. - * - * @pre `CGAL::is_triangle_mesh(tmesh)` - * - * @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 -OutputIterator -self_intersections( const FaceRange& face_range, - const TriangleMesh& tmesh, - OutputIterator out, - const NamedParameters& np) -{ - 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; -} - -/// \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()); -} -/// \endcond - -/** - * \ingroup PMP_intersection_grp - * tests if a triangulated surface mesh self-intersects. - * This function depends on the package \ref PkgBoxIntersectionD - * @pre `CGAL::is_triangle_mesh(tmesh)` - * - * @tparam TriangleMesh a model of `FaceListGraph` - * @tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" - * - * @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 `PMPSelfIntersectionTraits` \cgalParamEnd - * \cgalNamedParamsEnd - * - * @return true if `tmesh` self-intersects - */ -template -bool does_self_intersect(const TriangleMesh& tmesh - , const CGAL_PMP_NP_CLASS& np) -{ - CGAL_precondition(CGAL::is_triangle_mesh(tmesh)); - - try - { - typedef boost::function_output_iterator OutputIterator; - self_intersections(tmesh, OutputIterator(), np); - } - catch( CGAL::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" @@ -439,12 +456,12 @@ bool does_self_intersect(const TriangleMesh& tmesh * \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 + * @return `true` if the faces in `face_range` self-intersect */ -template + class NamedParameters> bool does_self_intersect(const FaceRange& face_range, const TriangleMesh& tmesh, const NamedParameters& np) @@ -453,35 +470,65 @@ bool does_self_intersect(const FaceRange& face_range, try { - typedef boost::function_output_iterator OutputIterator; - self_intersections(face_range, tmesh, OutputIterator(), np); + CGAL::Emptyset_iterator unused_out; + internal::self_intersections_impl(face_range, tmesh, unused_out, true /*throw*/, np); + } + catch(CGAL::internal::Throw_at_output_exception&) + { + return true; } - catch( CGAL::internal::Throw_at_output::Throw_at_output_exception& ) - { return true; } return false; } -/// \cond SKIP_IN_MANUAL -template -bool does_self_intersect(const TriangleMesh& tmesh) +/** + * \ingroup PMP_intersection_grp + * tests if 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 TriangleMesh a model of `FaceListGraph` + * @tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" + * + * @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 `PMPSelfIntersectionTraits` \cgalParamEnd + * \cgalNamedParamsEnd + * + * @return `true` if `tmesh` self-intersects + */ +template +bool does_self_intersect(const TriangleMesh& tmesh, + const CGAL_PMP_NP_CLASS& np) { - return does_self_intersect(tmesh, - CGAL::Polygon_mesh_processing::parameters::all_default()); + return does_self_intersect(faces(tmesh), tmesh, np); } -template +/// \cond SKIP_IN_MANUAL +template +bool does_self_intersect(const TriangleMesh& tmesh) +{ + return does_self_intersect(faces(tmesh), 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 - +}// namespace Polygon_mesh_processing }// namespace CGAL #include diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt index 2bf92f35e85..b708ac434a8 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt @@ -101,6 +101,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() 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 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; } 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..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 @@ -1,22 +1,25 @@ -#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; +#include +#include +#include +#include + +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::Polygon_mesh_processing::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; } 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; 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/CMakeLists.txt b/Polyhedron/demo/Polyhedron/CMakeLists.txt index 6427dc55d7d..1b1cd817152 100644 --- a/Polyhedron/demo/Polyhedron/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/CMakeLists.txt @@ -251,7 +251,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 ) @@ -262,6 +265,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/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/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/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.") 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 ff215dfa0e3..d9cb4ee90d5 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 c027c4275da..6bd189a6b2c 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 c3740307ffa..b7d64382b03 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 a6987e4f759..4979471b987 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/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 7b6febf0ff9..65ecb788392 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 @@ -1581,7 +1582,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; } @@ -1659,7 +1660,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_)) 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/Polyhedron/examples/Polyhedron/polyhedron_prog_cut_cube.cpp b/Polyhedron/examples/Polyhedron/polyhedron_prog_cut_cube.cpp index c244c1c1c74..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 << P; + std::cout << std::setprecision(17)<< P; return 0; } diff --git a/Polyhedron/examples/Polyhedron/polyhedron_prog_subdiv.cpp b/Polyhedron/examples/Polyhedron/polyhedron_prog_subdiv.cpp index b7d997bcfc1..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 << P; + std::cout << std::setprecision(17) << P; return 0; } diff --git a/Polyhedron/examples/Polyhedron/polyhedron_prog_subdiv_with_boundary.cpp b/Polyhedron/examples/Polyhedron/polyhedron_prog_subdiv_with_boundary.cpp index cd544262c2d..dd0af786576 100644 --- a/Polyhedron/examples/Polyhedron/polyhedron_prog_subdiv_with_boundary.cpp +++ b/Polyhedron/examples/Polyhedron/polyhedron_prog_subdiv_with_boundary.cpp @@ -196,6 +196,6 @@ int main( int argc, char* argv[]) { if ( i & 1) subdiv_border( P); } - cout << P; + cout << std::setprecision(17) << P; return 0; } 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/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 b5d4b0141d1..8ac695b7c6c 100644 --- a/STL_Extension/doc/STL_Extension/PackageDescription.txt +++ b/STL_Extension/doc/STL_Extension/PackageDescription.txt @@ -106,6 +106,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` 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 diff --git a/STL_Extension/include/CGAL/tags.h b/STL_Extension/include/CGAL/tags.h index 4b033abaf32..8feef206784 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,12 @@ 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 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/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/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 afd639b5040..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,14 +5,21 @@ 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`. -\tparam Traits must be a model for `SpatialSortingTraits`. +\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 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 > + template< typename Traits, typename PolicyTag, typename ConcurrencyTag = Sequential_tag > class Hilbert_sort_2 { public: @@ -31,9 +38,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 194c33e6206..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,12 +5,21 @@ 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 for `SpatialSortingTraits_3`. +\tparam Traits must be a model of the concept `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. + +\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 > +template< typename Traits, typename PolicyTag, typename ConcurrencyTag = Sequential_tag > class Hilbert_sort_3 { public: @@ -29,9 +38,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..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 { @@ -29,9 +33,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..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 { @@ -37,9 +41,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/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; /// @} diff --git a/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h b/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h index c724e3be723..56611e6687d 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/hilbert_sort.h @@ -8,19 +8,24 @@ along a Hilbert curve. 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()`. +\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. -\cgalHeading{Requirements} - -
      -
    1. `std::iterator_traits::%value_type` is 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`. -
    2. `Traits` is a model for concept `SpatialSortingTraits_2`, + +\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 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} @@ -31,12 +36,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); +hilbert_sort( InputPointIterator begin, + InputPointIterator 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..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 @@ -9,28 +9,22 @@ If input points are not close to the input sphere, this function still works, bu It sorts the range `[begin, end)` in place. +\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. -The default policy is `Hilbert_sort_median_policy()` and the -other option is `Hilbert_sort_middle_policy()`. +`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. 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} - -
      -
    1. `sqr_radius` greater than 0. -
    +\pre `sqr_radius` greater than 0. \cgalHeading{Implementation} @@ -38,14 +32,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 bec60e92aa8..38e37c16894 100644 --- a/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h +++ b/Spatial_sorting/doc/Spatial_sorting/CGAL/spatial_sort.h @@ -10,23 +10,27 @@ of being close in the order. 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 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. -The default policy is `Hilbert_sort_median_policy()` and the -other option is `Hilbert_sort_middle_policy()`. +\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 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. -\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} Creates an instance of `Multiscale_sort` @@ -44,15 +48,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..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} @@ -54,17 +47,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 */ diff --git a/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt b/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt index e726f56299d..cd4815c648f 100644 --- a/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt +++ b/Spatial_sorting/doc/Spatial_sorting/Spatial_sorting.txt @@ -208,12 +208,29 @@ 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 Parallel Spatial Sorting + +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. + +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_3.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, -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 */ diff --git a/Spatial_sorting/doc/Spatial_sorting/examples.txt b/Spatial_sorting/doc/Spatial_sorting/examples.txt index b0d1275d633..8417048ad59 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_spatial_sort_3.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/CMakeLists.txt b/Spatial_sorting/examples/Spatial_sorting/CMakeLists.txt index df5f623e1ba..0cd2ea143b2 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. @@ -16,6 +15,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_spatial_sort_3 ) + endif() else() message(STATUS "This program requires the CGAL library, and will not be compiled.") diff --git a/Spatial_sorting/examples/Spatial_sorting/parallel_spatial_sort_3.cpp b/Spatial_sorting/examples/Spatial_sorting/parallel_spatial_sort_3.cpp new file mode 100644 index 00000000000..b71cfa6887e --- /dev/null +++ b/Spatial_sorting/examples/Spatial_sorting/parallel_spatial_sort_3.cpp @@ -0,0 +1,33 @@ +#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() +{ + std::size_t pt_nb = 10000; + std::vector points; + points.reserve(pt_nb); + + CGAL::Random_points_in_cube_3 gen(1.0); + + for(std::size_t i=0; i(points.begin(), points.end()); + + return 0; +} diff --git a/Spatial_sorting/include/CGAL/Hilbert_sort_2.h b/Spatial_sorting/include/CGAL/Hilbert_sort_2.h index f75631089eb..1a4b7b249cd 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_2.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_2.h @@ -18,27 +18,27 @@ namespace CGAL { -template - class Hilbert_sort_2; +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) - {} +public: + Hilbert_sort_2 (const K &k=K(), std::ptrdiff_t limit=1 ) + : Hilbert_sort_median_2 (k,limit) + {} }; -template - class Hilbert_sort_2 +template +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 cd48af285cb..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 - 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) - {} +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 e33f2499eaf..d4d62d0b49a 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_base.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_base.h @@ -15,30 +15,33 @@ #include #include #include +#include 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 6d89cfc8eec..23e87f7ac7b 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_median_2.h @@ -12,101 +12,188 @@ #ifndef CGAL_HILBERT_SORT_MEDIAN_2_H #define CGAL_HILBERT_SORT_MEDIAN_2_H +#include #include +#include +#include + +#include + +#ifdef CGAL_LINKED_WITH_TBB +#include +#endif + #include #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 K Kernel; - typedef typename Kernel::Point_2 Point; - -private: - Kernel _k; - std::ptrdiff_t _limit; + typedef Hilbert_sort_median_2 Self; + 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) + 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); + } + + 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) {} - template - void sort (RandomAccessIterator begin, RandomAccessIterator end) const + void operator()() 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)); - - sort (m0, m1); - sort (m1, m2); - sort (m2, m3); - sort (m3, m4); + hs.recursive_sort(begin,end); } + }; - template - void operator() (RandomAccessIterator begin, RandomAccessIterator end) const + 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 { - sort <0, false, false> (begin, end); + 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 + const int y = (x + 1) % 2; + if (std::distance(begin,end) <= _limit) + return; + + RandomAccessIterator m0 = begin, m4 = end; + + 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)); + + 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); + } +#endif + } + + 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 1ccdea9adf6..0ea51bb24bc 100644 --- a/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h +++ b/Spatial_sorting/include/CGAL/Hilbert_sort_median_3.h @@ -13,122 +13,211 @@ #define CGAL_HILBERT_SORT_MEDIAN_3_H #include +#include #include #include #include +#include + +#ifdef CGAL_LINKED_WITH_TBB +#include +#endif + 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 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_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 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_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); + } +}; + +} // namespace internal + +template class Hilbert_sort_median_3 { public: - typedef K Kernel; - typedef typename Kernel::Point_3 Point; + typedef Hilbert_sort_median_3 Self; + 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) + 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); + } + + 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) {} - template - void sort (RandomAccessIterator begin, RandomAccessIterator end) const + void operator()() 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)); - - sort (m0, m1); - sort (m1, m2); - sort (m2, m3); - sort (m3, m4); - sort (m4, m5); - sort (m5, m6); - sort (m6, m7); - sort (m7, m8); + hs.recursive_sort(begin,end); } + }; - template - void operator() (RandomAccessIterator begin, RandomAccessIterator end) const + 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 { - sort <0, false, false, false> (begin, end); + 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 + const int y = (x + 1) % 3, z = (x + 2) % 3; + if ((end - begin) <= _limit) return; + + RandomAccessIterator m0 = begin, m8 = end; + 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)), + 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()); + } }; } // 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/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/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 13db962df86..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_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_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 +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); +} + +} // 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 +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 891889e4b50..90dd07bd966 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); - - 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); - } - -} - - -template +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_2 *, + 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_2 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 (nullptr), - threshold_hilbert,threshold_multiscale,ratio); + 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, - 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; - - 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) -{ - 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); -} - - -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) + Policy /*policy*/, + typename Kernel::Point_3 *, + std::ptrdiff_t threshold_hilbert, + std::ptrdiff_t threshold_multiscale, + double ratio) { - spatial_sort (begin, end, k, - Hilbert_sort_median_policy(), - threshold_hilbert,threshold_multiscale,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 +template void spatial_sort (RandomAccessIterator begin, RandomAccessIterator end, - std::ptrdiff_t threshold_hilbert=0, - std::ptrdiff_t threshold_multiscale=0, - double ratio=0.0) + const Kernel &k, + Policy /*policy*/, + typename Kernel::Point_d *, + std::ptrdiff_t threshold_hilbert, + std::ptrdiff_t threshold_multiscale, + double ratio) { - spatial_sort (begin, end, - Hilbert_sort_median_policy(), - threshold_hilbert,threshold_multiscale,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 (nullptr), + 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) +{ + 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); +} + +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) +{ + 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); +} + + +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, + Hilbert_sort_median_policy(), + threshold_hilbert,threshold_multiscale,ratio); +} + +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, + 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 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 ac1e5d47ef9..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,643 +31,658 @@ 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 = 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; + 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(); + timer.reset();timer.start(); + CGAL::hilbert_sort (v.begin(), v.end()); + timer.stop(); - std::cout << "done in "<(v2.begin(), v2.end()); + timer.stop(); - std::cout << "no points lost." << std::endl; + std::cout << "done in " << timer.time() << "seconds." << std::endl; + + std::cout << " Checking... " << std::flush; + assert(v == v2); + + 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 (median policy): Generating "< 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; + + timer.reset();timer.start(); + CGAL::hilbert_sort (v.begin(), v.end()); + timer.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; + + timer.reset();timer.start(); + CGAL::hilbert_sort(v.begin(),v.end(), CGAL::Hilbert_sort_middle_policy()); + timer.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; + + timer.reset();timer.start(); + CGAL::hilbert_sort(v.begin(),v.end(), CGAL::Hilbert_sort_middle_policy()); + timer.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 (median policy): 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; - } - { - std::cout << "Testing 2D (middle policy): Generating " - < v; - v.reserve (nb_points_2); + std::cout << "done in "< gen (1.0, random); + std::cout << " Sorting points (parallel)... " << std::flush; - for (int i = 0; i < nb_points_2 - 1; ++i) - v.push_back (*gen++); - v.push_back(v[0]); //insert twice the same point + timer.reset();timer.start(); + CGAL::hilbert_sort(v2.begin(), v2.end()); + timer.stop(); - std::cout << "done." << std::endl; + std::cout << "done in " << timer.time() << "seconds." << std::endl; - std::vector v2 (v); + std::cout << " Checking... " << std::flush; + assert(v == v2); - std::cout << " Sorting points... " << std::flush; + 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 - cost.reset();cost.start(); - CGAL::hilbert_sort(v.begin(),v.end(), CGAL::Hilbert_sort_middle_policy()); - cost.stop(); + std::cout << "Testing 3D (median policy): Generating "< v; + v.reserve(size); - std::cout << " Checking... " << std::flush; + CGAL::points_on_cube_grid_3 (box_size, (std::size_t)size, + std::back_inserter(v), Creator_3() ); - 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 << "done." << std::endl; - std::cout << "no points lost." << std::endl; - } - { - int size=256; // 2^(xd) - double box_size = 15.0; // 2^x -1 with x=4 d=2 - std::cout << "Testing 2D (middle policy): Generating " - < v; - v.reserve(size); + std::cout << " Sorting points... " << std::flush; - CGAL::points_on_square_grid_2 (box_size, (std::size_t)size, - std::back_inserter(v), Creator_2() ); + timer.reset();timer.start(); + CGAL::hilbert_sort (v.begin(), v.end()); + timer.stop(); - std::cout << "done." << std::endl; + 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; + + timer.reset();timer.start(); + CGAL::hilbert_sort(v.begin(),v.end(),CGAL::Hilbert_sort_middle_policy()); + timer.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; + + timer.reset();timer.start(); + CGAL::hilbert_sort(v.begin(),v.end(),CGAL::Hilbert_sort_middle_policy()); + timer.stop(); + + std::cout << "done in "< 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_on_sphere_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 + 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()); - cost.stop(); + timer.reset();timer.start(); + CGAL::hilbert_sort(v.begin(),v.end()); + timer.stop(); - std::cout << "done in "<(v2.begin(), v2.end()); + timer.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 " << timer.time() << "seconds." << std::endl; - std::cout << "Testing 3D: Generating "< 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()); - 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 ); + timer.reset();timer.start(); + CGAL::hilbert_sort_on_sphere(v.begin(),v.end(), 4, CGAL::ORIGIN + Vector_3(3,5,5)); + timer.stop(); - std::cout << "OK." << std::endl; - } + std::cout << "done in "< v; - v.reserve (nb_points_3); + 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::Random_points_in_cube_3 gen (1.0, random); + std::cout << "no points lost." << std::endl; + } + { + std::cout << "Testing Spherical (middle policy): Generating "< v; + v.reserve (nb_points_3); - std::cout << "done." << std::endl; + CGAL::Random_points_on_sphere_3 gen (1.0, random); - std::vector v2 (v); + 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 << " Sorting points... " << std::flush; + std::cout << "done." << std::endl; - cost.reset();cost.start(); - CGAL::hilbert_sort(v.begin(),v.end(),CGAL::Hilbert_sort_middle_policy()); - cost.stop(); + std::vector v2 (v); - std::cout << "done in "< v; - v.reserve(size); + std::cout << "no points lost." << std::endl; + } + { + std::cout << "Testing Spherical (middle 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; - } - { - std::cout << "Testing Spherical (median policy): Generating "< v; - v.reserve (nb_points_3); + std::cout << "done in "< gen (1.0, random); + std::cout << " Checking... " << 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 + 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 << "done." << std::endl; + std::cout << "no points lost." << std::endl; + } + { + int dim =5; + 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(), K().less_xyz_3_object()); - std::sort (v2.begin(), v2.end(), K().less_xyz_3_object()); - assert(v == v2); + std::cout << " Sorting points... " << std::flush; - 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 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 + 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; + } + { + int dim = 1000; + 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_on_sphere(v.begin(),v.end(), 4, CGAL::ORIGIN + Vector_3(3,5,5)); - 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(), K().less_xyz_3_object()); - std::sort (v2.begin(), v2.end(), K().less_xyz_3_object()); - assert(v == v2); + std::cout << " Sorting points... " << std::flush; - std::cout << "no points lost." << std::endl; - } - { - std::cout << "Testing Spherical (middle policy): Generating "< v; - v.reserve (nb_points_3); + std::cout << "done in "< gen (1.0, random); + std::cout << " Checking... " << 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 + 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; + } + { + int dim = 10; + 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_on_sphere(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); - 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 << " Sorting points ... " << std::flush; - std::cout << "no points lost." << std::endl; - } - { - std::cout << "Testing Spherical (middle policy) + given sphere: Generating "< 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 + 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; + } + { + int dim=5; + 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_on_sphere(v.begin(),v.end(),CGAL::Hilbert_sort_middle_policy(), 4, CGAL::ORIGIN + Vector_3(3,5,5)); - 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(), K().less_xyz_3_object()); - std::sort (v2.begin(), v2.end(), K().less_xyz_3_object()); - assert(v == v2); + std::cout << " Sorting points... " << std::flush; - std::cout << "no points lost." << std::endl; - } - { - int dim =5; - 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; + } + { + 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; + } + { + int dim=3; + int size=32768; // 2^(x.dim) with x=5 + double box_size = 31.0; // 2^x -1 - std::cout << "done." << std::endl; + std::cout << "Testing "< v2 (v); + std::vector v(size); - std::cout << " Sorting points... " << std::flush; + CGAL::points_on_cube_grid_d (dim, box_size, (std::size_t)size, + v.begin(), Creator_d(dim) ); - cost.reset();cost.start(); - CGAL::hilbert_sort (v.begin(), v.end()); - cost.stop(); + std::cout << "done." << std::endl; - std::cout << "done in "< v; - v.reserve (nb_points_d); + for (int i = 0; i < size-1; ++i) + assert(CGAL::squared_distance( v[i], v[i+1]) - 4.0 < 0.1 ); - CGAL::Random_points_in_cube_d gen (dim, 1.0, random); + std::cout << "OK." << std::endl; + } - for (int i = 0; i < nb_points_d - 1; ++i) - v.push_back (*gen++); - v.push_back(v[0]); //insert twice the same point + { + int dim=5; + int size=32768; // 2^(x.dim) with x=3 + double box_size = 7.0; // 2^x -1 - std::cout << "done." << std::endl; + std::cout << "Testing "< v2 (v); + std::vector v(size); - std::cout << " Sorting points ... " << std::flush; + CGAL::points_on_cube_grid_d (dim, box_size, (std::size_t)size, + v.begin(), Creator_d(dim) ); - 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 "< v; - v.reserve (nb_points_d); + for (int i = 0; i < size-1; ++i) + assert(CGAL::squared_distance( v[i], v[i+1]) - 4.0 < 0.1 ); - CGAL::Random_points_in_cube_d gen (dim, 1.0, random); + std::cout << "OK." << std::endl; + } - for (int i = 0; i < nb_points_d - 1; ++i) - v.push_back (*gen++); - v.push_back(v[0]); //insert twice the same point + { + int dim = 50; + 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()); - 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(), Kd().less_lexicographically_d_object()); - std::sort (v2.begin(), v2.end(),Kd().less_lexicographically_d_object()); - assert(v == v2); + timer.reset();timer.start(); + CGAL::hilbert_sort (v.begin(), v.end()); + timer.stop(); - 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 << "done in "< v(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_d (dim, box_size, (std::size_t)size, - v.begin(), Creator_d(dim) ); + std::cout << "no points lost." << std::endl; + } - 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; } 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..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.141592 + atan ; - double deg = rad * 180.0 / 3.141592 ; + double rad = atan >= 0.0 ? atan : 2.0 * CGAL_PI + atan ; + double deg = rad * 180.0 / CGAL_PI; return deg ; } diff --git a/Surface_mesh/examples/Surface_mesh/sm_join.cpp b/Surface_mesh/examples/Surface_mesh/sm_join.cpp index 1b1519f85c4..9d77f4b86b6 100644 --- a/Surface_mesh/examples/Surface_mesh/sm_join.cpp +++ b/Surface_mesh/examples/Surface_mesh/sm_join.cpp @@ -34,5 +34,5 @@ int main(int argc, char* argv[]) } - std::cout << sm1 << std::endl; + std::cout << std::setprecision(17)<< sm1 << std::endl; } 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..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 @@ -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; @@ -283,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); } 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 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 */ 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 @@ -327,7 +332,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; @@ -2191,11 +2196,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)) @@ -2229,7 +2238,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 38a1f3b33be..d1c2ea19d77 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; 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..5fa7e3c3395 --- /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/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 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..da415685d46 100644 --- a/Surface_mesh_simplification/doc/Surface_mesh_simplification/Concepts/GetPlacement.h +++ b/Surface_mesh_simplification/doc/Surface_mesh_simplification/Concepts/GetPlacement.h @@ -20,8 +20,9 @@ or can be intentionally returned to prevent the edge from being collapsed. \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 { public: 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..dad4317af92 --- /dev/null +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h @@ -0,0 +1,192 @@ +// Copyright (c) 2019 GeometryFactory (France). All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// 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 + +#include +#include + +namespace CGAL { +namespace Surface_mesh_simplification { + +// An AABB tree can also be passed to the placement instead, see undocumented specialization below +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; + +private: + template + void initialize_tree(const Profile& profile) const + { + CGAL_static_assertion((std::is_same::value)); + + 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 FT 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; + + boost::optional op = m_base_placement(profile); + if(op) + { + 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_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. + + // 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, 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 FT 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; + typedef typename AABB_tree::AABB_traits::FT FT; + +public: + Bounded_distance_placement(const FT 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 FT m_sq_threshold_dist; + mutable const AABB_tree* m_tree_ptr; + + const BasePlacement m_base_placement; +}; + +} // namespace Surface_mesh_simplification +} // namespace CGAL + +#endif // CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_BOUNDED_DISTANCE_PLACEMENT_H 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 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..8aaa51a4651 --- /dev/null +++ b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp @@ -0,0 +1,76 @@ +#include +#include + +// Simplification function +#include +#include +#include +#include +#include + +//AABB_tree +#include +#include +#include + +//bbox +#include + +#include +#include + +namespace SMS = CGAL::Surface_mesh_simplification; + +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::Bounded_distance_placement Filtered_placement; +typedef SMS::Bounded_distance_placement Filtered_placement_with_tree; + +int main(int argc, char** argv) +{ + Surface ref_mesh; + std::ifstream is(argc > 1 ? argv[1] : "data/helmet.off"); + is >> ref_mesh; + + SMS::Count_stop_predicate stop(num_halfedges(ref_mesh)/10); + + std::cout << "input has " << num_vertices(ref_mesh) << " vertices." << std::endl; + CGAL::Iso_cuboid_3 bbox(CGAL::Polygon_mesh_processing::bbox(ref_mesh)); + + Point_3 cmin = (bbox.min)(); + Point_3 cmax = (bbox.max)(); + 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; + Surface big_mesh = ref_mesh; + Tree tree(faces(mesh_cpy).first, faces(mesh_cpy).second, mesh_cpy); + + Placement placement_ref; + 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; + 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()); + + return EXIT_SUCCESS; +} 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/CGAL/Triangulation_ds_face_base_2.h b/TDS_2/doc/TDS_2/CGAL/Triangulation_ds_face_base_2.h index e4154ace5f7..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 f93dd03270a..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,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 should not be specified (see Section \ref TDS_2TheRebindMechanism and examples) + \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 = void > class Triangulation_ds_vertex_base_2 { public: diff --git a/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h b/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h index 4d17e03cf52..8ef6ea99deb 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,15 @@ 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: /// \name Types @@ -76,6 +71,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; @@ -103,26 +99,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); /// @} @@ -134,89 +130,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 diff --git a/TDS_2/doc/TDS_2/Concepts/TriangulationDSVertexBase_2.h b/TDS_2/doc/TDS_2/Concepts/TriangulationDSVertexBase_2.h index 35245d1a609..e7915a48888 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,15 @@ 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: /// \name Types @@ -72,6 +66,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; diff --git a/TDS_2/doc/TDS_2/Concepts/TriangulationDataStructure_2.h b/TDS_2/doc/TDS_2/Concepts/TriangulationDataStructure_2.h index 4b025c1b7e4..bcd40c0b975 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 @@ -743,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 { @@ -863,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 49bcbed73b4..22fc2c4d296 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,10 +19,9 @@ 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` +`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()`, and `delete_cell()`. @@ -33,23 +32,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 +72,10 @@ typedef Compact_container Cell_range; /// @} /// \name Operations +/// +/// In addition to the interface documented in the concept, +/// the class offers the following functions. +/// /// @{ /*! 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..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,9 +10,10 @@ 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` -\sa `CGAL::Triangulation_cell_base_with_info_3` */ template< typename TDS = void > 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..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,9 +20,10 @@ 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` -\sa `CGAL::Triangulation_vertex_base_with_info_3` */ template< typename TDS = void > diff --git a/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h b/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h index 01c6ac9cc95..2856e1d70bd 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,15 @@ 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: /// \name Types @@ -42,13 +49,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; /*! @@ -66,11 +74,6 @@ typedef TriangulationDataStructure_3::Vertex_handle Vertex_handle; */ typedef TriangulationDataStructure_3::Cell_handle Cell_handle; -/*! - -*/ -typedef TriangulationDataStructure_3::Cell_data TDS_data; - /// @} /// \name Creation @@ -79,113 +82,23 @@ typedef TriangulationDataStructure_3::Cell_data TDS_data; /*! 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); /// @} @@ -227,26 +140,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/TriangulationDSVertexBase_3.h b/TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h index 47d209d9c9f..e1d35cb88fc 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,31 +28,29 @@ 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: /// \name Types /// @{ /*! -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; /*! @@ -74,32 +76,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); /// @} diff --git a/TDS_3/doc/TDS_3/Concepts/TriangulationDataStructure_3.h b/TDS_3/doc/TDS_3/Concepts/TriangulationDataStructure_3.h index 175a64c4e20..b7ee722b903 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` @@ -90,6 +88,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) */ @@ -111,7 +114,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`. */ @@ -1161,6 +1164,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 +1189,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 +1281,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 +1315,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..233f7bd329a 100644 --- a/TDS_3/doc/TDS_3/PackageDescription.txt +++ b/TDS_3/doc/TDS_3/PackageDescription.txt @@ -50,13 +50,14 @@ Section \ref TDS3secintro.) - `TriangulationDataStructure_3` - `TriangulationDataStructure_3::Cell` +- `TriangulationDataStructure_3::Cell_data` - `TriangulationDataStructure_3::Vertex` - `TriangulationDSCellBase_3` - `TriangulationDSVertexBase_3` \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: 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); diff --git a/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h b/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h index 4f1de418ff2..2f8aa5fbc76 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())