From fe4b69aec84b3e765105a55427ab52f2557b37f0 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 27 Feb 2020 15:08:44 +0100 Subject: [PATCH 01/26] Factorize KD-tree calls in PSP + replace TBB functors by lambdas + some cleaning --- .../internal/Neighbor_query.h | 190 ++++++++++ .../internal/neighbor_query.h | 104 ------ .../include/CGAL/bilateral_smooth_point_set.h | 342 +++++------------- .../include/CGAL/compute_average_spacing.h | 77 ++-- .../include/CGAL/jet_estimate_normals.h | 144 +++----- .../include/CGAL/jet_smooth_point_set.h | 138 +++---- .../include/CGAL/mst_orient_normals.h | 51 +-- .../include/CGAL/pca_estimate_normals.h | 139 +++---- .../include/CGAL/remove_outliers.h | 44 +-- 9 files changed, 494 insertions(+), 735 deletions(-) create mode 100644 Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Neighbor_query.h delete mode 100644 Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/neighbor_query.h diff --git a/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Neighbor_query.h b/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Neighbor_query.h new file mode 100644 index 00000000000..74ed1e17b5b --- /dev/null +++ b/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Neighbor_query.h @@ -0,0 +1,190 @@ +// Copyright (c) 2019 GeometryFactory Sarl (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) : Simon Giraudot + +#ifndef CGAL_PSP_INTERNAL_NEIGHBOR_QUERY_H +#define CGAL_PSP_INTERNAL_NEIGHBOR_QUERY_H + +#include + +#include +#include +#include +#include + +#include + +namespace CGAL { +namespace Point_set_processing_3 { +namespace internal { + +struct Maximum_points_reached_exception : public std::exception { }; + +template +class Neighbor_query +{ +public: + + typedef Kernel_ Kernel; + typedef PointRange Point_range; + typedef PointMap Point_map; + + typedef typename Kernel::FT FT; + typedef typename Kernel::Point_3 Point_3; + + typedef typename PointRange::iterator input_iterator; + typedef typename input_iterator::value_type value_type; + + typedef CGAL::Prevent_deref iterator; + + struct Deref_point_map + { + typedef iterator key_type; + typedef typename boost::property_traits::reference reference; + typedef typename boost::property_traits::value_type value_type; + typedef typename boost::property_traits::category category; + + PointMap point_map; + + Deref_point_map () { } + Deref_point_map (PointMap point_map) : point_map(point_map) { } + + friend reference get (const Deref_point_map& map, key_type it) + { + return get(map.point_map, **it); + } + }; + + typedef CGAL::Search_traits_3 Tree_traits_base; + typedef CGAL::Search_traits_adapter Tree_traits; + typedef CGAL::Sliding_midpoint Splitter; + typedef CGAL::Distance_adapter > Distance; + typedef CGAL::Kd_tree Tree; + typedef CGAL::Fuzzy_sphere Sphere; + + typedef CGAL::Orthogonal_k_neighbor_search Neighbor_search; + typedef typename Neighbor_search::iterator Search_iterator; + +private: + + PointRange& m_points; + PointMap m_point_map; + Deref_point_map m_deref_map; + Tree_traits m_traits; + Tree m_tree; + Distance m_distance; + + // Forbid copy + Neighbor_query (const Neighbor_query&) { } + +public: + + Neighbor_query (PointRange& points, PointMap point_map) + : m_points (points) + , m_point_map (point_map) + , m_deref_map (point_map) + , m_traits (m_deref_map) + , m_tree (iterator(m_points.begin()), iterator(m_points.end()), Splitter(), m_traits) + , m_distance (m_deref_map) + { + m_tree.build(); + } + + // Hack to avoid problems with const ranges + Neighbor_query (const PointRange& points, PointMap point_map) + : m_points (const_cast(points)) + , m_point_map (point_map) + , m_deref_map (point_map) + , m_traits (m_deref_map) + , m_tree (iterator(m_points.begin()), iterator(m_points.end()), Splitter(), m_traits) + , m_distance (m_deref_map) + { + m_tree.build(); + } + + PointMap point_map() const { return m_point_map; } + + template + void get_iterators (const Point_3& query, unsigned int k, FT neighbor_radius, + OutputIterator output) const + { + if (neighbor_radius != FT(0)) + { + Sphere fs (query, neighbor_radius, 0, m_traits); + + // if k=0, no limit on the number of neighbors returned + if (k == 0) + k = (std::numeric_limits::max)(); + + unsigned int nb = 0; + + try + { + std::function output_iterator_with_limit + = [&](const iterator& it) + { + *(output ++) = *it; + if (++ nb == k) + throw Maximum_points_reached_exception(); + }; + + auto function_output_iterator + = boost::make_function_output_iterator (output_iterator_with_limit); + + m_tree.search (function_output_iterator, fs); + } + catch (const Maximum_points_reached_exception&) + { } + + // Fallback, if less than 3 points are return, search for the 3 + // first points + if (nb < 3) + k = 3; + // Else, no need to search for K nearest neighbors + else + k = 0; + } + + if (k != 0) + { + // Gather set of (k+1) neighboring points. + // Perform k+1 queries (as in point set, the query point is + // output first). Search may be aborted if k is greater + // than number of input points. + + Neighbor_search search (m_tree, query, k+1, 0, true, m_distance); + Search_iterator search_iterator = search.begin(); + unsigned int i; + for (i = 0; i < (k+1); ++ i) + { + if(search_iterator == search.end()) + break; // premature ending + *(output ++) = *(search_iterator->first); + search_iterator++; + } + } + } + + template + void get_points (const Point_3& query, unsigned int k, FT neighbor_radius, + OutputIterator output) const + { + return get_iterators(query, k, neighbor_radius, + boost::make_function_output_iterator + ([&](const input_iterator& it) + { + *(output ++) = get (m_point_map, *it); + })); + } +}; + +} } } // namespace CGAL::Point_set_processing_3::internal + +#endif // CGAL_PSP_INTERNAL_NEIGHBOR_QUERY_H diff --git a/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/neighbor_query.h b/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/neighbor_query.h deleted file mode 100644 index 93a82d432fb..00000000000 --- a/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/neighbor_query.h +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) 2019 GeometryFactory Sarl (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) : Simon Giraudot - -#ifndef CGAL_PSP_INTERNAL_NEIGHBOR_QUERY_H -#define CGAL_PSP_INTERNAL_NEIGHBOR_QUERY_H - -#include - -#include -#include -#include -#include - -#include - -namespace CGAL { -namespace Point_set_processing_3 { -namespace internal { - -struct Maximum_points_reached_exception : public std::exception { }; - -template -void neighbor_query (const Point& query, - const CGAL::Kd_tree& tree, - unsigned int k, - FT neighbor_radius, - PointContainer& points) -{ - typedef typename CGAL::Orthogonal_k_neighbor_search Neighbor_search; - typedef typename Neighbor_search::iterator Search_iterator; - typedef CGAL::Fuzzy_sphere Sphere; - - if (neighbor_radius != FT(0)) - { - Sphere fs (query, neighbor_radius, 0, tree.traits()); - - // if k=0, no limit on the number of neighbors returned - if (k == 0) - k = (std::numeric_limits::max)(); - - try - { - std::function back_insert_with_limit - = [&](const Point& point) -> void - { - points.push_back (point); - if (points.size() == k) - throw Maximum_points_reached_exception(); - }; - - auto function_output_iterator - = boost::make_function_output_iterator (back_insert_with_limit); - - tree.search (function_output_iterator, fs); - } - catch (const Maximum_points_reached_exception&) - { } - - // Fallback, if less than 3 points are return, search for the 3 - // first points - if (points.size() < 3) - k = 3; - // Else, no need to search for K nearest neighbors - else - k = 0; - } - - if (k != 0) - { - // Gather set of (k+1) neighboring points. - // Perform k+1 queries (as in point set, the query point is - // output first). Search may be aborted if k is greater - // than number of input points. - points.reserve(k+1); - Neighbor_search search(tree,query,k+1); - Search_iterator search_iterator = search.begin(); - unsigned int i; - for(i=0;i<(k+1);i++) - { - if(search_iterator == search.end()) - break; // premature ending - points.push_back(search_iterator->first); - search_iterator++; - } - CGAL_point_set_processing_precondition(points.size() >= 1); - } -} - -} } } // namespace CGAL::Point_set_processing_3::internal - -#endif // CGAL_PSP_INTERNAL_NEIGHBOR_QUERY_H 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 a01a9eba86e..ca871cca2cb 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 @@ -17,12 +17,9 @@ #include #include -#include -#include -#include +#include #include #include -#include #include #include @@ -66,47 +63,6 @@ namespace CGAL { namespace bilateral_smooth_point_set_internal{ -// Item in the Kd-tree: position (Point_3) + index -template -class Kd_tree_element : public Point_with_normal_3 -{ -public: - unsigned int index; - - // basic geometric types - typedef typename CGAL::Origin Origin; - typedef CGAL::Point_with_normal_3 Base; - - Kd_tree_element(const Origin& o = ORIGIN, unsigned int id=0) - : Base(o), index(id) - {} - Kd_tree_element(const Base& p, unsigned int id=0) - : Base(p), index(id) - {} - Kd_tree_element(const Kd_tree_element& other) - : Base(other), index(other.index) - {} - - Kd_tree_element& operator=(const Kd_tree_element&)=default; -}; - - -// Helper class for the Kd-tree -template -class Kd_tree_gt : public Kernel -{ -public: - typedef Kd_tree_element Point_3; -}; - -template -class Kd_tree_traits : public CGAL::Search_traits_3 > -{ -public: - typedef typename Kernel::Point_3 PointType; -}; - - /// Compute bilateral projection for each point /// according to their KNN neighborhood points /// @@ -117,12 +73,14 @@ public: /// /// @return -template -CGAL::Point_with_normal_3 +template +std::pair compute_denoise_projection( - const CGAL::Point_with_normal_3& query, ///< 3D point to project - const std::vector, - CGAL_PSP3_DEFAULT_ALLOCATOR > >& neighbor_pwns, // + const typename PointRange::iterator::value_type& vt, + PointMap point_map, + VectorMap normal_map, + const std::vector& neighbor_pwns, typename Kernel::FT radius, ///< accept neighborhood radius typename Kernel::FT sharpness_angle ///< control sharpness(0-90) ) @@ -133,7 +91,6 @@ compute_denoise_projection( // basic geometric types typedef typename Kernel::FT FT; - typedef CGAL::Point_with_normal_3 Pwn; typedef typename Kernel::Vector_3 Vector; typedef typename Kernel::Point_3 Point; @@ -148,23 +105,21 @@ compute_denoise_projection( 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 - pwn_iter = neighbor_pwns.begin(); - for (; pwn_iter != neighbor_pwns.end(); ++pwn_iter) + for (typename PointRange::iterator it : neighbor_pwns) { - const Point& np = pwn_iter->position(); - const Vector& nn = pwn_iter->normal(); + const Point& np = get(point_map, *it); + const Vector& nn = get(normal_map, *it); - FT dist2 = CGAL::squared_distance(query.position(), np); + FT dist2 = CGAL::squared_distance(get(point_map, vt), np); if (dist2 < radius2) { FT theta = std::exp(dist2 * iradius16); - FT psi = std::exp(-std::pow(1 - query.normal() * nn, 2) + FT psi = std::exp(-std::pow(1 - get(normal_map, vt) * nn, 2) / sharpness_bandwidth); weight = theta * psi; - project_dist_sum += ((query.position() - np) * nn) * weight; + project_dist_sum += ((get(point_map, vt) - np) * nn) * weight; project_weight_sum += weight; normal_sum = normal_sum + nn * weight; } @@ -173,10 +128,10 @@ compute_denoise_projection( Vector update_normal = normal_sum / project_weight_sum; update_normal = update_normal / sqrt(update_normal.squared_length()); - Point update_point = query.position() - update_normal * + Point update_point = get(point_map, vt) - update_normal * (project_dist_sum / project_weight_sum); - return Pwn(update_point, update_normal); + return std::make_pair (update_point, update_normal); } /// Computes max-spacing of one query point from K nearest neighbors. @@ -187,41 +142,31 @@ compute_denoise_projection( /// @tparam Tree KD-tree. /// /// @return max spacing. -template < typename Kernel, - typename Tree > -typename Kernel::FT +template +typename NeighborQuery::Kernel::FT compute_max_spacing( - const CGAL::Point_with_normal_3& query, ///< 3D point - Tree& tree, ///< KD-tree + const typename NeighborQuery::value_type& vt, + typename NeighborQuery::Point_map point_map, + VectorMap normal_map, + NeighborQuery& neighbor_query, ///< KD-tree unsigned int k) ///< number of neighbors { // basic geometric types + typedef typename NeighborQuery::Kernel Kernel; typedef typename Kernel::FT FT; - typedef CGAL::Point_with_normal_3 Pwn; - - // types for K nearest neighbors search - typedef bilateral_smooth_point_set_internal::Kd_tree_traits Tree_traits; - typedef CGAL::Orthogonal_k_neighbor_search Neighbor_search; - typedef typename Neighbor_search::iterator Search_iterator; // performs k + 1 queries (if unique the query point is // output first). search may be aborted when k is greater // than number of input points - Neighbor_search search(tree,query,k+1); - Search_iterator search_iterator = search.begin(); - ++search_iterator; FT max_distance = (FT)0.0; - unsigned int i; - for(i = 0; i < (k+1) ; ++i) - { - if(search_iterator == search.end()) - break; // premature ending - - Pwn pwn = search_iterator->first; - double dist2 = CGAL::squared_distance(query.position(), pwn.position()); - max_distance = (CGAL::max)(dist2, max_distance); - ++search_iterator; - } + neighbor_query.get_iterators + (get(point_map, vt), k, (FT)(0.0), + boost::make_function_output_iterator + ([&](const typename NeighborQuery::input_iterator& it) + { + double dist2 = CGAL::squared_distance (get(point_map, vt), get(point_map, *it)); + max_distance = (CGAL::max)(dist2, max_distance); + })); // output max spacing return std::sqrt(max_distance); @@ -231,102 +176,6 @@ compute_max_spacing( /// \endcond -#ifdef CGAL_LINKED_WITH_TBB -/// \cond SKIP_IN_MANUAL -/// This is for parallelization of function: bilateral_smooth_point_set() -template -class Compute_pwns_neighbors -{ - typedef typename CGAL::Point_with_normal_3 Pwn; - typedef typename std::vector > Pwns; - typedef typename std::vector > - Pwns_neighbors; - typedef typename Kernel::FT FT; - - unsigned int m_k; - FT m_neighbor_radius; - const Tree & m_tree; - const Pwns & m_pwns; - Pwns_neighbors & m_pwns_neighbors; - cpp11::atomic& advancement; - cpp11::atomic& interrupted; - -public: - Compute_pwns_neighbors(unsigned int k, FT neighbor_radius, const Tree &tree, - const Pwns &pwns, Pwns_neighbors &neighbors, - cpp11::atomic& advancement, - cpp11::atomic& interrupted) - : m_k(k), m_neighbor_radius (neighbor_radius), m_tree(tree) - , m_pwns(pwns), m_pwns_neighbors(neighbors) - , advancement (advancement), interrupted (interrupted) {} - - void operator() ( const tbb::blocked_range& r ) const - { - for (size_t i = r.begin(); i!=r.end(); i++) - { - if (interrupted) - break; - - CGAL::Point_set_processing_3::internal::neighbor_query - (m_pwns[i], m_tree, m_k, m_neighbor_radius, m_pwns_neighbors[i]); - - ++ advancement; - } - } -}; -/// \endcond - -/// \cond SKIP_IN_MANUAL -/// This is for parallelization of function: compute_denoise_projection() -template -class Pwn_updater -{ - typedef typename CGAL::Point_with_normal_3 Pwn; - typedef typename std::vector > Pwns; - typedef typename Kernel::FT FT; - - FT sharpness_angle; - FT radius; - Pwns* pwns; - Pwns* update_pwns; - std::vector >* pwns_neighbors; - cpp11::atomic& advancement; - cpp11::atomic& interrupted; - -public: - Pwn_updater(FT sharpness, - FT r, - Pwns *in, - Pwns *out, - std::vector >* neighbors, - cpp11::atomic& advancement, - cpp11::atomic& interrupted): - sharpness_angle(sharpness), - radius(r), - pwns(in), - update_pwns(out), - pwns_neighbors(neighbors), - advancement (advancement), - interrupted (interrupted) {} - - void operator() ( const tbb::blocked_range& r ) const - { - for (size_t i = r.begin(); i != r.end(); ++i) - { - if (interrupted) - break; - (*update_pwns)[i] = bilateral_smooth_point_set_internal:: - compute_denoise_projection((*pwns)[i], - (*pwns_neighbors)[i], - radius, - sharpness_angle); - ++ advancement; - } - } -}; -/// \endcond -#endif // CGAL_LINKED_WITH_TBB - // ---------------------------------------------------------------------------- // Public section @@ -400,16 +249,18 @@ bilateral_smooth_point_set( using parameters::get_parameter; // basic geometric types + typedef typename PointRange::iterator iterator; + typedef typename iterator::value_type value_type; typedef typename Point_set_processing_3::GetPointMap::type PointMap; typedef typename Point_set_processing_3::GetNormalMap::type NormalMap; typedef typename Point_set_processing_3::GetK::Kernel Kernel; + typedef typename Kernel::Point_3 Point_3; + typedef typename Kernel::Vector_3 Vector_3; CGAL_static_assertion_msg(!(boost::is_same::NoMap>::value), "Error: no normal map"); - typedef typename CGAL::Point_with_normal_3 Pwn; - typedef typename std::vector > Pwns; typedef typename Kernel::FT FT; double sharpness_angle = choose_parameter(get_parameter(np, internal_np::sharpness_angle), 30.); @@ -420,43 +271,20 @@ bilateral_smooth_point_set( CGAL_point_set_processing_precondition(k > 1); // types for K nearest neighbors search structure - typedef bilateral_smooth_point_set_internal:: - Kd_tree_element Kd_tree_element; - typedef bilateral_smooth_point_set_internal::Kd_tree_traits Tree_traits; - typedef CGAL::Orthogonal_k_neighbor_search Neighbor_search; - typedef typename Neighbor_search::Tree Tree; + typedef Point_set_processing_3::internal::Neighbor_query Neighbor_query; PointMap point_map = choose_parameter(get_parameter(np, internal_np::point_map), PointMap()); NormalMap normal_map = choose_parameter(get_parameter(np, internal_np::normal_map), NormalMap()); FT neighbor_radius = choose_parameter(get_parameter(np, internal_np::neighbor_radius), FT(0)); - // copy points and normals - Pwns pwns; - for(typename PointRange::iterator it = points.begin(); it != points.end(); ++it) - { - typename boost::property_traits::reference p = get(point_map, *it); - typename boost::property_traits::reference n = get(normal_map, *it); - CGAL_point_set_processing_precondition(n.squared_length() > 1e-10); - - pwns.push_back(Pwn(p, n)); - } - - std::size_t nb_points = pwns.size(); + std::size_t nb_points = points.size(); #ifdef CGAL_PSP3_VERBOSE std::cout << "Initialization and compute max spacing: " << std::endl; #endif // initiate a KD-tree search for points - std::vector > treeElements; - treeElements.reserve(pwns.size()); - typename std::vector >::iterator - pwn_iter = pwns.begin(); - for (unsigned int i = 0; pwn_iter != pwns.end(); ++pwn_iter) - { - treeElements.push_back(Kd_tree_element(*pwn_iter, i)); - } - Tree tree(treeElements.begin(), treeElements.end()); + Neighbor_query neighbor_query (points, point_map); + // Guess spacing #ifdef CGAL_PSP3_VERBOSE CGAL::Real_timer task_timer; @@ -464,10 +292,10 @@ bilateral_smooth_point_set( #endif FT guess_neighbor_radius = 0.0; - for(pwn_iter = pwns.begin(); pwn_iter != pwns.end(); ++pwn_iter) + for (const value_type& vt : points) { FT max_spacing = bilateral_smooth_point_set_internal:: - compute_max_spacing(*pwn_iter, tree, k); + compute_max_spacing (vt, point_map, normal_map, neighbor_query, k); guess_neighbor_radius = (CGAL::max)(max_spacing, guess_neighbor_radius); } @@ -486,7 +314,7 @@ bilateral_smooth_point_set( task_timer.start(); #endif // compute all neighbors - std::vector > pwns_neighbors; + std::vector > pwns_neighbors; pwns_neighbors.resize(nb_points); #ifndef CGAL_LINKED_WITH_TBB @@ -498,10 +326,20 @@ bilateral_smooth_point_set( Point_set_processing_3::internal::Parallel_callback parallel_callback (callback, 2 * nb_points); - Compute_pwns_neighbors f(k, neighbor_radius, tree, pwns, pwns_neighbors, - parallel_callback.advancement(), - parallel_callback.interrupted()); - tbb::parallel_for(tbb::blocked_range(0, nb_points), f); + tbb::parallel_for(tbb::blocked_range(0, nb_points), + [&](const tbb::blocked_range& r) + { + for (size_t i = r.begin(); i!=r.end(); i++) + { + if (parallel_callback.interrupted()) + break; + + neighbor_query.get_iterators (get(point_map, *(points.begin() + i)), k, neighbor_radius, + std::back_inserter (pwns_neighbors[i])); + + ++ parallel_callback.advancement(); + } + }); bool interrupted = parallel_callback.interrupted(); @@ -516,17 +354,14 @@ bilateral_smooth_point_set( else #endif { - typename std::vector >::iterator - pwns_iter = pwns_neighbors.begin(); - std::size_t nb = 0; - for(pwn_iter = pwns.begin(); pwn_iter != pwns.end(); ++pwn_iter, ++pwns_iter, ++ nb) + for (const value_type& vt : points) { - CGAL::Point_set_processing_3::internal::neighbor_query - (*pwn_iter, tree, k, neighbor_radius, *pwns_iter); + neighbor_query.get_iterators (get (point_map, vt), k, neighbor_radius, std::back_inserter (pwns_neighbors[nb])); if (callback && !callback ((nb+1) / double(2. * nb_points))) return std::numeric_limits::quiet_NaN(); + ++ nb; } } @@ -541,7 +376,7 @@ bilateral_smooth_point_set( task_timer.start(); #endif // update points and normals - Pwns update_pwns(nb_points); + std::vector > update_pwns(nb_points); #ifdef CGAL_LINKED_WITH_TBB if(boost::is_convertible::value) @@ -549,16 +384,23 @@ bilateral_smooth_point_set( Point_set_processing_3::internal::Parallel_callback parallel_callback (callback, 2 * nb_points, nb_points); - //tbb::task_scheduler_init init(4); - tbb::blocked_range block(0, nb_points); - Pwn_updater pwn_updater(sharpness_angle, - guess_neighbor_radius, - &pwns, - &update_pwns, - &pwns_neighbors, - parallel_callback.advancement(), - parallel_callback.interrupted()); - tbb::parallel_for(block, pwn_updater); + tbb::parallel_for(tbb::blocked_range (0, nb_points), + [&](const tbb::blocked_range& r) + { + for (size_t i = r.begin(); i != r.end(); ++i) + { + if (parallel_callback.interrupted()) + break; + update_pwns[i] = bilateral_smooth_point_set_internal:: + compute_denoise_projection + (*(points.begin() + i), + point_map, normal_map, + pwns_neighbors[i], + guess_neighbor_radius, + sharpness_angle); + ++ parallel_callback.advancement(); + } + }); parallel_callback.join(); @@ -569,23 +411,18 @@ bilateral_smooth_point_set( else #endif // CGAL_LINKED_WITH_TBB { - std::size_t nb = nb_points; - - typename std::vector >::iterator - update_iter = update_pwns.begin(); - typename std::vector >::iterator - neighbor_iter = pwns_neighbors.begin(); - for(pwn_iter = pwns.begin(); pwn_iter != pwns.end(); - ++pwn_iter, ++update_iter, ++neighbor_iter, ++ nb) + std::size_t nb = 0; + for (const value_type& vt : points) { - *update_iter = bilateral_smooth_point_set_internal:: - compute_denoise_projection - (*pwn_iter, - *neighbor_iter, + update_pwns[nb] =bilateral_smooth_point_set_internal:: + compute_denoise_projection + (vt, point_map, normal_map, + pwns_neighbors[nb], guess_neighbor_radius, sharpness_angle); if (callback && !callback ((nb+1) / double(2. * nb_points))) return std::numeric_limits::quiet_NaN(); + ++ nb; } } #ifdef CGAL_PSP3_VERBOSE @@ -596,13 +433,14 @@ bilateral_smooth_point_set( #endif // save results FT sum_move_error = 0; + std::size_t nb = 0; typename PointRange::iterator it = points.begin(); - for(unsigned int i = 0 ; it != points.end(); ++it, ++i) + for (const value_type& vt : points) { - typename boost::property_traits::reference p = get(point_map, *it); - sum_move_error += CGAL::squared_distance(p, update_pwns[i].position()); - put (point_map, *it, update_pwns[i].position()); - put (normal_map, *it, update_pwns[i].normal()); + sum_move_error += CGAL::squared_distance(get(point_map, vt), update_pwns[nb].first); + put (point_map, vt, update_pwns[nb].first); + put (normal_map, vt, update_pwns[nb].second); + ++ nb; } return sum_move_error / nb_points; 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 375a8932a03..dd8242912d0 100644 --- a/Point_set_processing_3/include/CGAL/compute_average_spacing.h +++ b/Point_set_processing_3/include/CGAL/compute_average_spacing.h @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include #include @@ -60,38 +60,31 @@ namespace internal { /// @tparam Tree KD-tree. /// /// @return average spacing (scalar). -template < typename Kernel, - typename Tree > -typename Kernel::FT -compute_average_spacing(const typename Kernel::Point_3& query, ///< 3D point whose spacing we want to compute - const Tree& tree, ///< KD-tree +template +typename NeighborQuery::Kernel::FT +compute_average_spacing(const typename NeighborQuery::Kernel::Point_3& query, ///< 3D point whose spacing we want to compute + const NeighborQuery& neighbor_query, ///< KD-tree unsigned int k) ///< number of neighbors { // basic geometric types + typedef typename NeighborQuery::Kernel Kernel; typedef typename Kernel::FT FT; typedef typename Kernel::Point_3 Point; - // types for K nearest neighbors search - typedef Search_traits_3 Tree_traits; - typedef Orthogonal_k_neighbor_search Neighbor_search; - typedef typename Neighbor_search::iterator Search_iterator; // performs k + 1 queries (if unique the query point is // output first). search may be aborted when k is greater // than number of input points - Neighbor_search search(tree,query,k+1); - Search_iterator search_iterator = search.begin(); FT sum_distances = (FT)0.0; unsigned int i; - for(i=0;i<(k+1);i++) - { - if(search_iterator == search.end()) - break; // premature ending - - Point p = search_iterator->first; - sum_distances += std::sqrt(CGAL::squared_distance(query,p)); - search_iterator++; - } + neighbor_query.get_points + (query, k, 0, + boost::make_function_output_iterator + ([&](const Point& p) + { + sum_distances += std::sqrt(CGAL::squared_distance (query,p)); + ++ i; + })); // output average spacing return sum_distances / (FT)i; @@ -195,6 +188,8 @@ compute_average_spacing( using parameters::get_parameter; // basic geometric types + typedef typename PointRange::iterator iterator; + typedef typename iterator::value_type value_type; typedef typename Point_set_processing_3::GetPointMap::const_type PointMap; typedef typename Point_set_processing_3::GetK::Kernel Kernel; @@ -206,9 +201,7 @@ compute_average_spacing( // types for K nearest neighbors search structure typedef typename Kernel::FT FT; - typedef Search_traits_3 Tree_traits; - typedef Orthogonal_k_neighbor_search Neighbor_search; - typedef typename Neighbor_search::Tree Tree; + typedef Point_set_processing_3::internal::Neighbor_query Neighbor_query; // precondition: at least one element in the container. // to fix: should have at least three distinct points @@ -219,16 +212,13 @@ compute_average_spacing( CGAL_point_set_processing_precondition(k >= 2); // Instanciate a KD-tree search. - // Note: We have to convert each input iterator to Point_3. - std::vector kd_tree_points; - for(typename PointRange::const_iterator it = points.begin(); it != points.end(); it++) - kd_tree_points.push_back(get(point_map, *it)); - Tree tree(kd_tree_points.begin(), kd_tree_points.end()); + Neighbor_query neighbor_query (points, point_map); // iterate over input points, compute and output normal // vectors (already normalized) FT sum_spacings = (FT)0.0; std::size_t nb = 0; + std::size_t nb_points = points.size(); #ifndef CGAL_LINKED_WITH_TBB CGAL_static_assertion_msg (!(boost::is_convertible::value), @@ -237,14 +227,23 @@ compute_average_spacing( if (boost::is_convertible::value) { Point_set_processing_3::internal::Parallel_callback - parallel_callback (callback, kd_tree_points.size()); + parallel_callback (callback, nb_points); - std::vector spacings (kd_tree_points.size (), -1); - CGAL::internal::Compute_average_spacings - f (tree, k, kd_tree_points, spacings, - parallel_callback.advancement(), - parallel_callback.interrupted()); - tbb::parallel_for(tbb::blocked_range(0, kd_tree_points.size ()), f); + std::vector spacings (nb_points, -1); + tbb::parallel_for(tbb::blocked_range(0, nb_points), + [&](const tbb::blocked_range& r) + { + for( std::size_t i = r.begin(); i != r.end(); ++i) + { + if (parallel_callback.interrupted()) + break; + + spacings[i] = CGAL::internal::compute_average_spacing + (get(point_map, *(points.begin() + i)), neighbor_query, k); + ++ parallel_callback.advancement(); + } + + }); for (unsigned int i = 0; i < spacings.size (); ++ i) if (spacings[i] >= 0.) @@ -260,10 +259,10 @@ compute_average_spacing( { for(typename PointRange::const_iterator it = points.begin(); it != points.end(); it++, nb++) { - sum_spacings += internal::compute_average_spacing( + sum_spacings += internal::compute_average_spacing( get(point_map,*it), - tree,k); - if (callback && !callback ((nb+1) / double(kd_tree_points.size()))) + neighbor_query,k); + if (callback && !callback ((nb+1) / double(nb_points))) { ++ nb; break; 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 9b6fb4a1869..5095bfacb70 100644 --- a/Point_set_processing_3/include/CGAL/jet_estimate_normals.h +++ b/Point_set_processing_3/include/CGAL/jet_estimate_normals.h @@ -17,9 +17,7 @@ #include #include -#include -#include -#include +#include #include #include #include @@ -58,18 +56,16 @@ namespace internal { /// @tparam Tree KD-tree. /// /// @return Computed normal. Orientation is random. -template < typename Kernel, - typename SvdTraits, - typename Tree -> -typename Kernel::Vector_3 -jet_estimate_normal(const typename Kernel::Point_3& query, ///< point to compute the normal at - Tree& tree, ///< KD-tree +template +typename NeighborQuery::Kernel::Vector_3 +jet_estimate_normal(const typename NeighborQuery::Point_3& query, ///< point to compute the normal at + const NeighborQuery& neighbor_query, ///< KD-tree unsigned int k, ///< number of neighbors - typename Kernel::FT neighbor_radius, + typename NeighborQuery::FT neighbor_radius, unsigned int degree_fitting) { // basic geometric types + typedef typename NeighborQuery::Kernel Kernel; typedef typename Kernel::Point_3 Point; // types for jet fitting @@ -79,8 +75,7 @@ jet_estimate_normal(const typename Kernel::Point_3& query, ///< point to compute typedef typename Monge_jet_fitting::Monge_form Monge_form; std::vector points; - CGAL::Point_set_processing_3::internal::neighbor_query - (query, tree, k, neighbor_radius, points); + neighbor_query.get_points (query, k, neighbor_radius, std::back_inserter(points)); // performs jet fitting Monge_jet_fitting monge_fit; @@ -92,49 +87,6 @@ jet_estimate_normal(const typename Kernel::Point_3& query, ///< point to compute return monge_form.normal_direction(); } -#ifdef CGAL_LINKED_WITH_TBB - template - class Jet_estimate_normals { - typedef typename Kernel::FT FT; - typedef typename Kernel::Point_3 Point; - typedef typename Kernel::Vector_3 Vector; - const Tree& tree; - const unsigned int k; - const FT neighbor_radius; - const unsigned int degree_fitting; - const std::vector& input; - std::vector& output; - cpp11::atomic& advancement; - cpp11::atomic& interrupted; - - public: - Jet_estimate_normals(Tree& tree, unsigned int k, FT neighbor_radius, - std::vector& points, - unsigned int degree_fitting, std::vector& output, - cpp11::atomic& advancement, - cpp11::atomic& interrupted) - : tree(tree), k (k), neighbor_radius (neighbor_radius) - , degree_fitting (degree_fitting), input (points), output (output) - , advancement (advancement) - , interrupted (interrupted) - { } - - void operator()(const tbb::blocked_range& r) const - { - for( std::size_t i = r.begin(); i != r.end(); ++i) - { - if (interrupted) - break; - output[i] = CGAL::internal::jet_estimate_normal(input[i], tree, k, neighbor_radius, degree_fitting); - ++ advancement; - } - } - - }; -#endif // CGAL_LINKED_WITH_TBB - - - } /* namespace internal */ /// \endcond @@ -202,6 +154,8 @@ jet_estimate_normals( CGAL_TRACE("Calls jet_estimate_normals()\n"); // basic geometric types + typedef typename PointRange::iterator iterator; + typedef typename iterator::value_type value_type; typedef typename Point_set_processing_3::GetPointMap::type PointMap; typedef typename Point_set_processing_3::GetNormalMap::type NormalMap; typedef typename Point_set_processing_3::GetK::Kernel Kernel; @@ -229,9 +183,7 @@ jet_estimate_normals( typedef typename boost::property_traits::value_type Vector; // types for K nearest neighbors search structure - typedef typename CGAL::Search_traits_3 Tree_traits; - typedef typename CGAL::Orthogonal_k_neighbor_search Neighbor_search; - typedef typename Neighbor_search::Tree Tree; + typedef Point_set_processing_3::internal::Neighbor_query Neighbor_query; // precondition: at least one element in the container. // to fix: should have at least three distinct points @@ -244,59 +196,57 @@ jet_estimate_normals( std::size_t memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20); CGAL_TRACE(" Creates KD-tree\n"); - typename PointRange::iterator it; - - // Instanciate a KD-tree search. - // Note: We have to convert each input iterator to Point_3. - std::vector kd_tree_points; - for(it = points.begin(); it != points.end(); it++) - kd_tree_points.push_back(get(point_map, *it)); - Tree tree(kd_tree_points.begin(), kd_tree_points.end()); + Neighbor_query neighbor_query (points, point_map); memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20); CGAL_TRACE(" Computes normals\n"); + std::size_t nb_points = points.size(); + // iterate over input points, compute and output normal // vectors (already normalized) #ifndef CGAL_LINKED_WITH_TBB CGAL_static_assertion_msg (!(boost::is_convertible::value), - "Parallel_tag is enabled but TBB is unavailable."); + "Parallel_tag is enabled but TBB is unavailable."); #else - if (boost::is_convertible::value) - { - Point_set_processing_3::internal::Parallel_callback - parallel_callback (callback, kd_tree_points.size()); + if (boost::is_convertible::value) + { + Point_set_processing_3::internal::Parallel_callback + parallel_callback (callback, nb_points); - std::vector normals (kd_tree_points.size (), - CGAL::NULL_VECTOR); - CGAL::internal::Jet_estimate_normals - f (tree, k, neighbor_radius, - kd_tree_points, degree_fitting, normals, - parallel_callback.advancement(), - parallel_callback.interrupted()); - tbb::parallel_for(tbb::blocked_range(0, kd_tree_points.size ()), f); - std::size_t i = 0; - for(it = points.begin(); it != points.end(); ++ it, ++ i) - if (normals[i] != CGAL::NULL_VECTOR) - put (normal_map, *it, normals[i]); + tbb::parallel_for(tbb::blocked_range(0, points.size ()), + [&](const tbb::blocked_range& r) + { + for( std::size_t i = r.begin(); i != r.end(); ++i) + { + if (parallel_callback.interrupted()) + break; + put (normal_map, *(points.begin() + i), + CGAL::internal::jet_estimate_normal + (get(point_map, *(points.begin() + i)), neighbor_query, k, neighbor_radius, degree_fitting)); + ++ parallel_callback.advancement(); + } + }); - parallel_callback.join(); - } - else + parallel_callback.join(); + } + else #endif + { + std::size_t nb = 0; + for (const value_type& vt : points) { - std::size_t nb = 0; - for(it = points.begin(); it != points.end(); it++, ++ nb) - { - Vector normal = internal::jet_estimate_normal( - get(point_map,*it), - tree, k, neighbor_radius, degree_fitting); + put (normal_map, vt, + internal::jet_estimate_normal( + get(point_map, vt), + neighbor_query, k, neighbor_radius, degree_fitting)); - put(normal_map, *it, normal); // normal_map[it] = normal - if (callback && !callback ((nb+1) / double(kd_tree_points.size()))) - break; - } + if (callback && !callback ((nb+1) / double(nb_points))) + break; + + ++ nb; } + } memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20); 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 bde1da19f37..acf12856e4b 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 @@ -17,9 +17,7 @@ #include #include -#include -#include -#include +#include #include #include #include @@ -57,20 +55,20 @@ namespace internal { /// @tparam Tree KD-tree. /// /// @return computed point -template -typename Kernel::Point_3 +typename NeighborQuery::Kernel::Point_3 jet_smooth_point( - const typename Kernel::Point_3& query, ///< 3D point to project - Tree& tree, ///< KD-tree + const typename NeighborQuery::Kernel::Point_3& query, ///< 3D point to project + NeighborQuery& neighbor_query, ///< KD-tree const unsigned int k, ///< number of neighbors. - typename Kernel::FT neighbor_radius, + typename NeighborQuery::Kernel::FT neighbor_radius, const unsigned int degree_fitting, const unsigned int degree_monge) { // basic geometric types + typedef typename NeighborQuery::Kernel Kernel; typedef typename Kernel::Point_3 Point; // types for jet fitting @@ -79,9 +77,8 @@ jet_smooth_point( SvdTraits> Monge_jet_fitting; typedef typename Monge_jet_fitting::Monge_form Monge_form; - std::vector points; - CGAL::Point_set_processing_3::internal::neighbor_query - (query, tree, k, neighbor_radius, points); + std::vector points; + neighbor_query.get_points (query, k, neighbor_radius, std::back_inserter(points)); // performs jet fitting Monge_jet_fitting monge_fit; @@ -92,50 +89,6 @@ jet_smooth_point( return monge_form.origin(); } -#ifdef CGAL_LINKED_WITH_TBB - template - class Jet_smooth_pwns { - typedef typename Kernel::Point_3 Point; - const Tree& tree; - const unsigned int k; - const typename Kernel::FT neighbor_radius; - unsigned int degree_fitting; - unsigned int degree_monge; - const std::vector& input; - std::vector& output; - cpp11::atomic& advancement; - cpp11::atomic& interrupted; - - public: - Jet_smooth_pwns (Tree& tree, unsigned int k, typename Kernel::FT neighbor_radius, - std::vector& points, - unsigned int degree_fitting, unsigned int degree_monge, std::vector& output, - cpp11::atomic& advancement, - cpp11::atomic& interrupted) - : tree(tree), k (k), neighbor_radius(neighbor_radius) - , degree_fitting (degree_fitting) - , degree_monge (degree_monge), input (points), output (output) - , advancement (advancement) - , interrupted (interrupted) - { } - - void operator()(const tbb::blocked_range& r) const - { - for( std::size_t i = r.begin(); i != r.end(); ++i) - { - if (interrupted) - break; - output[i] = CGAL::internal::jet_smooth_point(input[i], tree, k, - neighbor_radius, - degree_fitting, - degree_monge); - ++ advancement; - } - } - - }; -#endif // CGAL_LINKED_WITH_TBB - } /* namespace internal */ @@ -204,6 +157,8 @@ jet_smooth_point_set( using parameters::get_parameter; // basic geometric types + typedef typename PointRange::iterator iterator; + typedef typename iterator::value_type value_type; typedef typename Point_set_processing_3::GetPointMap::type PointMap; typedef typename Point_set_processing_3::GetK::Kernel Kernel; typedef typename GetSvdTraits::type SvdTraits; @@ -223,9 +178,7 @@ jet_smooth_point_set( typedef typename Kernel::Point_3 Point; // types for K nearest neighbors search structure - typedef typename CGAL::Search_traits_3 Tree_traits; - typedef typename CGAL::Orthogonal_k_neighbor_search Neighbor_search; - typedef typename Neighbor_search::Tree Tree; + typedef Point_set_processing_3::internal::Neighbor_query Neighbor_query; // precondition: at least one element in the container. // to fix: should have at least three distinct points @@ -234,19 +187,15 @@ jet_smooth_point_set( // precondition: at least 2 nearest neighbors CGAL_point_set_processing_precondition(k >= 2); - - typename PointRange::iterator it; // Instanciate a KD-tree search. - // Note: We have to convert each input iterator to Point_3. - std::vector kd_tree_points; - for(it = points.begin(); it != points.end(); it++) - kd_tree_points.push_back(get(point_map, *it)); - Tree tree(kd_tree_points.begin(), kd_tree_points.end()); + Neighbor_query neighbor_query (points, point_map); // Iterates over input points and mutates them. // Implementation note: the cast to Point& allows to modify only the point's position. + std::size_t nb_points = points.size(); + #ifndef CGAL_LINKED_WITH_TBB CGAL_static_assertion_msg (!(boost::is_convertible::value), "Parallel_tag is enabled but TBB is unavailable."); @@ -254,37 +203,52 @@ jet_smooth_point_set( if (boost::is_convertible::value) { Point_set_processing_3::internal::Parallel_callback - parallel_callback (callback, kd_tree_points.size()); + parallel_callback (callback, nb_points); - std::vector mutated_points (kd_tree_points.size (), CGAL::ORIGIN); - CGAL::internal::Jet_smooth_pwns - f (tree, k, neighbor_radius, kd_tree_points, degree_fitting, degree_monge, - mutated_points, - parallel_callback.advancement(), - parallel_callback.interrupted()); - tbb::parallel_for(tbb::blocked_range(0, kd_tree_points.size ()), f); + std::vector mutated_points (nb_points, CGAL::ORIGIN); + tbb::parallel_for(tbb::blocked_range(0, nb_points), + [&](const tbb::blocked_range& r) + { + for( std::size_t i = r.begin(); i != r.end(); ++i) + { + if (parallel_callback.interrupted()) + break; + mutated_points[i] = + CGAL::internal::jet_smooth_point + (get (point_map, *(points.begin() + i)), neighbor_query, + k, + neighbor_radius, + degree_fitting, + degree_monge); + ++ parallel_callback.advancement(); + } + }); + unsigned int i = 0; - for(it = points.begin(); it != points.end(); ++ it, ++ i) + for (const value_type& vt : points) + { if (mutated_points[i] != CGAL::ORIGIN) - put(point_map, *it, mutated_points[i]); + put(point_map, vt, mutated_points[i]); + ++ i; + } parallel_callback.join(); } else #endif + { + std::size_t nb = 0; + for (const value_type& vt : points) { - std::size_t nb = 0; - for(it = points.begin(); it != points.end(); it++, ++ nb) - { - const typename boost::property_traits::reference p = get(point_map, *it); - put(point_map, *it , - internal::jet_smooth_point( - p,tree,k,neighbor_radius,degree_fitting,degree_monge) ); - if (callback && !callback ((nb+1) / double(kd_tree_points.size()))) - break; - } + put(point_map, vt, + internal::jet_smooth_point + (get (point_map, vt), neighbor_query,k,neighbor_radius,degree_fitting,degree_monge) ); + if (callback && !callback ((nb+1) / double(nb_points))) + break; + ++ nb; } + } } diff --git a/Point_set_processing_3/include/CGAL/mst_orient_normals.h b/Point_set_processing_3/include/CGAL/mst_orient_normals.h index b8c7030498b..1db0b213053 100644 --- a/Point_set_processing_3/include/CGAL/mst_orient_normals.h +++ b/Point_set_processing_3/include/CGAL/mst_orient_normals.h @@ -17,10 +17,7 @@ #include #include -#include -#include -#include -#include +#include #include #include #include @@ -296,17 +293,16 @@ mst_find_source( /// @tparam Kernel Geometric traits class. /// /// @return the Riemannian graph -template -Riemannian_graph +Riemannian_graph create_riemannian_graph( - ForwardIterator first, ///< iterator over the first input point. - ForwardIterator beyond, ///< past-the-end iterator over the input points. + PointRange& points, ///< input points PointMap point_map, ///< property map: value_type of ForwardIterator -> Point_3 NormalMap normal_map, ///< property map: value_type of ForwardIterator -> Vector_3 IndexMap index_map, ///< property map ForwardIterator -> index @@ -320,11 +316,8 @@ create_riemannian_graph( typedef typename boost::property_traits::reference Vector_ref; // Types for K nearest neighbors search structure - typedef Point_vertex_handle_3 Point_vertex_handle_3; - typedef internal::Search_traits_vertex_handle_3 Traits; - typedef Euclidean_distance_vertex_handle_3 KDistance; - typedef Orthogonal_k_neighbor_search Neighbor_search; - typedef typename Neighbor_search::Tree Tree; + typedef typename PointRange::iterator ForwardIterator; + typedef Point_set_processing_3::internal::Neighbor_query Neighbor_query; // Riemannian_graph types typedef internal::Riemannian_graph Riemannian_graph; @@ -337,26 +330,12 @@ create_riemannian_graph( CGAL_point_set_processing_precondition(k >= 2); // Number of input points - const std::size_t num_input_points = distance(first, beyond); + const std::size_t num_input_points = points.size(); std::size_t memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20); CGAL_TRACE(" Creates KD-tree\n"); - // Instanciate a KD-tree search. - // Notes: We have to wrap each input point by a Point_vertex_handle_3. - // The KD-tree is allocated dynamically to recover RAM as soon as possible. - std::vector kd_tree_points; kd_tree_points.reserve(num_input_points); - for (ForwardIterator it = first; it != beyond; it++) - { - - Point_ref point = get(point_map, *it); - Point_vertex_handle_3 point_wrapper(point.x(), point.y(), point.z(), it); - kd_tree_points.push_back(point_wrapper); - } - boost::shared_ptr tree( new Tree(kd_tree_points.begin(), kd_tree_points.end()) ); - - // Recover RAM - kd_tree_points.clear(); + Neighbor_query neighbor_query (points, point_map); memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20); CGAL_TRACE(" Creates Riemannian Graph\n"); @@ -369,7 +348,7 @@ create_riemannian_graph( Riemannian_graph riemannian_graph; // // add vertices - for (ForwardIterator it = first; it != beyond; it++) + for (ForwardIterator it = points.begin(); it != points.end(); it++) { typename Riemannian_graph::vertex_descriptor v = add_vertex(riemannian_graph); CGAL_point_set_processing_assertion(v == get(index_map,it)); @@ -383,16 +362,14 @@ create_riemannian_graph( // // add edges Riemannian_graph_weight_map riemannian_graph_weight_map = get(boost::edge_weight, riemannian_graph); - for (ForwardIterator it = first; it != beyond; it++) + for (ForwardIterator it = points.begin(); it != points.end(); it++) { std::size_t it_index = get(index_map,it); Vector_ref it_normal_vector = get(normal_map,*it); Point_ref point = get(point_map, *it); - Point_vertex_handle_3 point_wrapper(point.x(), point.y(), point.z(), it); - std::vector neighbor_points; - CGAL::Point_set_processing_3::internal::neighbor_query - (point_wrapper, *tree, k, neighbor_radius, neighbor_points); + std::vector neighbor_points; + neighbor_query.get_iterators (point, k, neighbor_radius, std::back_inserter(neighbor_points)); for (std::size_t i = 0; i < neighbor_points.size(); ++ i) { @@ -665,7 +642,7 @@ mst_orient_normals( if (boost::is_same::NoMap>::value) - riemannian_graph = create_riemannian_graph(points.begin(), points.end(), + riemannian_graph = create_riemannian_graph(points, point_map, normal_map, index_map, Default_constrained_map (mst_find_source(points.begin(), points.end(), @@ -675,7 +652,7 @@ mst_orient_normals( neighbor_radius, kernel); else - riemannian_graph = create_riemannian_graph(points.begin(), points.end(), + riemannian_graph = create_riemannian_graph(points, point_map, normal_map, index_map, constrained_map, k, 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 3a6ead3d5fd..63c9782b60c 100644 --- a/Point_set_processing_3/include/CGAL/pca_estimate_normals.h +++ b/Point_set_processing_3/include/CGAL/pca_estimate_normals.h @@ -18,9 +18,7 @@ #include #include -#include -#include -#include +#include #include #include #include @@ -58,22 +56,20 @@ namespace internal { /// @tparam Tree KD-tree. /// /// @return Computed normal. Orientation is random. -template < typename Kernel, - typename Tree -> -typename Kernel::Vector_3 -pca_estimate_normal(const typename Kernel::Point_3& query, ///< point to compute the normal at - const Tree& tree, ///< KD-tree +template +typename NeighborQuery::Kernel::Vector_3 +pca_estimate_normal(const typename NeighborQuery::Kernel::Point_3& query, ///< point to compute the normal at + const NeighborQuery& neighbor_query, ///< KD-tree unsigned int k, ///< number of neighbors - typename Kernel::FT neighbor_radius) + typename NeighborQuery::Kernel::FT neighbor_radius) { // basic geometric types + typedef typename NeighborQuery::Kernel Kernel; typedef typename Kernel::Point_3 Point; typedef typename Kernel::Plane_3 Plane; std::vector points; - CGAL::Point_set_processing_3::internal::neighbor_query - (query, tree, k, neighbor_radius, points); + neighbor_query.get_points (query, k, neighbor_radius, std::back_inserter(points)); // performs plane fitting by point-based PCA Plane plane; @@ -83,48 +79,6 @@ pca_estimate_normal(const typename Kernel::Point_3& query, ///< point to compute return plane.orthogonal_vector(); } - -#ifdef CGAL_LINKED_WITH_TBB - template - class PCA_estimate_normals { - typedef typename Kernel::FT FT; - typedef typename Kernel::Point_3 Point; - typedef typename Kernel::Vector_3 Vector; - const Tree& tree; - const unsigned int k; - const FT neighbor_radius; - const std::vector& input; - std::vector& output; - cpp11::atomic& advancement; - cpp11::atomic& interrupted; - - public: - PCA_estimate_normals(Tree& tree, unsigned int k, FT neighbor_radius, - std::vector& points, - std::vector& output, - cpp11::atomic& advancement, - cpp11::atomic& interrupted) - : tree(tree), k (k), neighbor_radius (neighbor_radius) - , input (points), output (output) - , advancement (advancement) - , interrupted (interrupted) - { } - - void operator()(const tbb::blocked_range& r) const - { - for( std::size_t i = r.begin(); i != r.end(); ++i) - { - if (interrupted) - break; - output[i] = CGAL::internal::pca_estimate_normal(input[i], tree, k, neighbor_radius); - ++ advancement; - } - } - - }; -#endif // CGAL_LINKED_WITH_TBB - - } /* namespace internal */ /// \endcond @@ -209,12 +163,12 @@ pca_estimate_normals( typedef typename Kernel::Point_3 Point; // Input points types + typedef typename PointRange::iterator iterator; + typedef typename iterator::value_type value_type; typedef typename boost::property_traits::value_type Vector; // types for K nearest neighbors search structure - typedef typename CGAL::Search_traits_3 Tree_traits; - typedef typename CGAL::Orthogonal_k_neighbor_search Neighbor_search; - typedef typename Neighbor_search::Tree Tree; + typedef Point_set_processing_3::internal::Neighbor_query Neighbor_query; // precondition: at least one element in the container. // to fix: should have at least three distinct points @@ -227,18 +181,13 @@ pca_estimate_normals( std::size_t memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20); CGAL_TRACE(" Creates KD-tree\n"); - typename PointRange::iterator it; - - // Instanciate a KD-tree search. - // Note: We have to convert each input iterator to Point_3. - std::vector kd_tree_points; - for(it = points.begin(); it != points.end(); it++) - kd_tree_points.push_back(get(point_map, *it)); - Tree tree(kd_tree_points.begin(), kd_tree_points.end()); + Neighbor_query neighbor_query (points, point_map); memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20); CGAL_TRACE(" Computes normals\n"); + std::size_t nb_points = points.size(); + // iterate over input points, compute and output normal // vectors (already normalized) #ifndef CGAL_LINKED_WITH_TBB @@ -246,40 +195,44 @@ pca_estimate_normals( "Parallel_tag is enabled but TBB is unavailable."); #else if (boost::is_convertible::value) - { - Point_set_processing_3::internal::Parallel_callback - parallel_callback (callback, kd_tree_points.size()); + { + Point_set_processing_3::internal::Parallel_callback + parallel_callback (callback, nb_points); - std::vector normals (kd_tree_points.size (), - CGAL::NULL_VECTOR); - CGAL::internal::PCA_estimate_normals - f (tree, k, neighbor_radius, kd_tree_points, normals, - parallel_callback.advancement(), - parallel_callback.interrupted()); - tbb::parallel_for(tbb::blocked_range(0, kd_tree_points.size ()), f); - unsigned int i = 0; - for(it = points.begin(); it != points.end(); ++ it, ++ i) - if (normals[i] != CGAL::NULL_VECTOR) - put (normal_map, *it, normals[i]); + tbb::parallel_for(tbb::blocked_range(0, nb_points), + [&](const tbb::blocked_range& r) + { + for( std::size_t i = r.begin(); i != r.end(); ++i) + { + if (parallel_callback.interrupted()) + break; + + put (normal_map, *(points.begin() + i), + CGAL::internal::pca_estimate_normal + (get(point_map, *(points.begin() + i)), neighbor_query, k, neighbor_radius)); + + ++ parallel_callback.advancement(); + } + }); - parallel_callback.join(); - } + parallel_callback.join(); + } else #endif + { + std::size_t nb = 0; + for (const value_type& vt : points) { - std::size_t nb = 0; - for(it = points.begin(); it != points.end(); it++, ++ nb) - { - Vector normal = internal::pca_estimate_normal( - get(point_map,*it), - tree, - k, neighbor_radius); - - put(normal_map, *it, normal); // normal_map[it] = normal - if (callback && !callback ((nb+1) / double(kd_tree_points.size()))) - break; - } + put (normal_map, vt, + internal::pca_estimate_normal( + get(point_map, vt), + neighbor_query, + k, neighbor_radius)); + if (callback && !callback ((nb+1) / double(nb_points))) + break; + ++ nb; } + } memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20); CGAL_TRACE("End of pca_estimate_normals()\n"); diff --git a/Point_set_processing_3/include/CGAL/remove_outliers.h b/Point_set_processing_3/include/CGAL/remove_outliers.h index 60a5f2c4af0..63b4754216c 100644 --- a/Point_set_processing_3/include/CGAL/remove_outliers.h +++ b/Point_set_processing_3/include/CGAL/remove_outliers.h @@ -16,9 +16,7 @@ #include -#include -#include -#include +#include #include #include #include @@ -49,12 +47,11 @@ namespace internal { /// @tparam Tree KD-tree. /// /// @return computed distance. -template < typename Kernel, - typename Tree > -typename Kernel::FT +template +typename NeighborQuery::Kernel::FT compute_avg_knn_sq_distance_3( - const typename Kernel::Point_3& query, ///< 3D point to project - Tree& tree, ///< KD-tree + const typename NeighborQuery::Kernel::Point_3& query, ///< 3D point to project + NeighborQuery& neighbor_query, ///< KD-tree unsigned int k, ///< number of neighbors typename Kernel::FT neighbor_radius) { @@ -63,8 +60,7 @@ compute_avg_knn_sq_distance_3( typedef typename Kernel::Point_3 Point; std::vector points; - CGAL::Point_set_processing_3::internal::neighbor_query - (query, tree, k, neighbor_radius, points); + neighbor_query.get_points (query, k, neighbor_radius, std::back_inserter(points)); // compute average squared distance typename Kernel::Compute_squared_distance_3 sqd; @@ -162,15 +158,15 @@ remove_outliers( typedef typename Kernel::FT FT; // basic geometric types + typedef typename PointRange::iterator iterator; + typedef typename iterator::value_type value_type; typedef typename Kernel::Point_3 Point; // actual type of input points typedef typename std::iterator_traits::value_type Enriched_point; // types for K nearest neighbors search structure - typedef typename CGAL::Search_traits_3 Tree_traits; - typedef typename CGAL::Orthogonal_k_neighbor_search Neighbor_search; - typedef typename Neighbor_search::Tree Tree; + typedef Point_set_processing_3::internal::Neighbor_query Neighbor_query; // precondition: at least one element in the container. // to fix: should have at least three distinct points @@ -182,26 +178,22 @@ remove_outliers( CGAL_point_set_processing_precondition(threshold_percent >= 0 && threshold_percent <= 100); - typename PointRange::iterator it; + Neighbor_query neighbor_query (points, point_map); - // Instanciate a KD-tree search. - // Note: We have to convert each input iterator to Point_3. - std::vector kd_tree_points; - for(it = points.begin(); it != points.end(); it++) - kd_tree_points.push_back( get(point_map, *it) ); - Tree tree(kd_tree_points.begin(), kd_tree_points.end()); + std::size_t nb_points = points.size(); // iterate over input points and add them to multimap sorted by distance to k std::multimap sorted_points; std::size_t nb = 0; - for(it = points.begin(); it != points.end(); it++, ++ nb) + for(const value_type& vt : points) { - FT sq_distance = internal::compute_avg_knn_sq_distance_3( - get(point_map,*it), - tree, k, neighbor_radius); - sorted_points.insert( std::make_pair(sq_distance, *it) ); - if (callback && !callback ((nb+1) / double(kd_tree_points.size()))) + FT sq_distance = internal::compute_avg_knn_sq_distance_3( + get(point_map, vt), + neighbor_query, k, neighbor_radius); + sorted_points.insert( std::make_pair(sq_distance, vt) ); + if (callback && !callback ((nb+1) / double(nb_points))) return points.end(); + ++ nb; } // Replaces [points.begin(), points.end()) range by the multimap content. From b99402f9535fe8029ac4828e78a20cd1da67fbb2 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 2 Mar 2020 12:23:10 +0100 Subject: [PATCH 02/26] Add convenient for_each to transparently use sequential/parallel/randomaccess/not --- STL_Extension/include/CGAL/for_each.h | 142 ++++++++++++++++++ STL_Extension/include/CGAL/iterator.h | 11 ++ .../test/STL_Extension/CMakeLists.txt | 4 + .../test/STL_Extension/test_for_each.cpp | 44 ++++++ 4 files changed, 201 insertions(+) create mode 100644 STL_Extension/include/CGAL/for_each.h create mode 100644 STL_Extension/test/STL_Extension/test_for_each.cpp diff --git a/STL_Extension/include/CGAL/for_each.h b/STL_Extension/include/CGAL/for_each.h new file mode 100644 index 00000000000..8096592370d --- /dev/null +++ b/STL_Extension/include/CGAL/for_each.h @@ -0,0 +1,142 @@ +// Copyright (c) 2020 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) : Simon Giraudot + +#ifndef CGAL_FOR_EACH_H +#define CGAL_FOR_EACH_H + +#include + +#ifdef CGAL_LINKED_WITH_TBB +#include +#include +#include +#endif // CGAL_LINKED_WITH_TBB + +namespace CGAL { + +namespace internal { + +// To emulate either a "break" in sequential and a "return" in +// parallel, we use an interal throw/catch mechanism +struct stop_for_each : public std::exception { }; + +template +void for_each (RangeRef range, + const std::function::type>::reference)>& functor, + const Sequential_tag&, + const IteratorCategory&) +{ + for (typename std::iterator_traits + ::type>::reference r : range) + try + { + functor(r); + } + catch (stop_for_each) + { + break; + } +} + +#ifdef CGAL_LINKED_WITH_TBB +template +void for_each (RangeRef range, + const std::function::type>::reference)>& functor, + const Parallel_tag&, + const IteratorCategory&) +{ + std::size_t range_size = std::distance (range.begin(), range.end()); + + std::vector::type> iterators; + iterators.reserve (range_size); + for (typename Range_iterator_type::type it = range.begin(); it != range.end(); ++ it) + iterators.push_back (it); + + tbb::parallel_for (tbb::blocked_range(0, range_size), + [&](const tbb::blocked_range& r) + { + for (std::size_t i = r.begin(); i != r.end(); ++ i) + try + { + functor (*(iterators[i])); + } + catch (stop_for_each) + { + return; + } + }); +} + +template +void for_each (const RangeRef range, + const std::function::type>::reference)>& functor, + const Parallel_tag&, + const std::random_access_iterator_tag&) +{ + std::size_t range_size = std::distance (range.begin(), range.end()); + + tbb::parallel_for (tbb::blocked_range(0, range_size), + [&](const tbb::blocked_range& r) + { + for (std::size_t i = r.begin(); i != r.end(); ++ i) + try + { + functor (*(range.begin() + i)); + } + catch (stop_for_each) + { + return; + } + }); +} +#endif + +} // namespace internal + +template +void for_each (const Range& range, + const std::function::reference)>& functor) +{ +#ifndef CGAL_LINKED_WITH_TBB + CGAL_static_assertion_msg (!(boost::is_convertible::value), + "Parallel_tag is enabled but TBB is unavailable."); +#endif + + internal::for_each + (range, functor, + ConcurrencyTag(), + typename std::iterator_traits::iterator_category()); +} + +template +void for_each (Range& range, + const std::function::reference)>& functor) +{ +#ifndef CGAL_LINKED_WITH_TBB + CGAL_static_assertion_msg (!(boost::is_convertible::value), + "Parallel_tag is enabled but TBB is unavailable."); +#endif + + internal::for_each + (range, functor, + ConcurrencyTag(), + typename std::iterator_traits::iterator_category()); +} + +} // namespace CGAL + + +#endif // CGAL_FOR_EACH_H diff --git a/STL_Extension/include/CGAL/iterator.h b/STL_Extension/include/CGAL/iterator.h index a219fdf3226..4875fb69aa5 100644 --- a/STL_Extension/include/CGAL/iterator.h +++ b/STL_Extension/include/CGAL/iterator.h @@ -1471,6 +1471,17 @@ dispatch_or_drop_output(O... o) return Dispatch_or_drop_output_iterator, std::tuple >(o...); } + +// Trick to select iterator or const_iterator depending on the range constness +template +struct Range_iterator_type { typedef int type; }; // Should generate errors +template +struct Range_iterator_type { typedef typename RangeRef::iterator type; }; +template +struct Range_iterator_type { typedef typename RangeRef::const_iterator type; }; + + + } //namespace CGAL #include diff --git a/STL_Extension/test/STL_Extension/CMakeLists.txt b/STL_Extension/test/STL_Extension/CMakeLists.txt index 419220ed841..105fb37149f 100644 --- a/STL_Extension/test/STL_Extension/CMakeLists.txt +++ b/STL_Extension/test/STL_Extension/CMakeLists.txt @@ -42,6 +42,10 @@ if ( CGAL_FOUND ) create_single_source_cgal_program( "test_Uncertain.cpp" ) create_single_source_cgal_program( "test_vector.cpp" ) create_single_source_cgal_program( "test_join_iterators.cpp" ) + create_single_source_cgal_program( "test_for_each.cpp" ) + if(TBB_FOUND) + CGAL_target_use_TBB(test_for_each) + endif() else() message(STATUS "This program requires the CGAL library, and will not be compiled.") diff --git a/STL_Extension/test/STL_Extension/test_for_each.cpp b/STL_Extension/test/STL_Extension/test_for_each.cpp new file mode 100644 index 00000000000..b82ba01468c --- /dev/null +++ b/STL_Extension/test/STL_Extension/test_for_each.cpp @@ -0,0 +1,44 @@ +#include + +#include +#include + +int main() +{ + std::vector vec { 0, 1, 2, 3, 4, 5 }; + std::list list { 0, 1, 2, 3, 4, 5 }; + + std::cerr << "Testing sequential random access" << std::endl; + CGAL::for_each + (vec, [](int& i) { i *= 2; }); + + for (const int& i : vec) + std::cerr << i << " "; + std::cerr << std::endl; + + std::cerr << "Testing parallel random access" << std::endl; + CGAL::for_each + (vec, [](int& i) { i *= 2; }); + + for (const int& i : vec) + std::cerr << i << " "; + std::cerr << std::endl; + + std::cerr << "Testing sequential non-random access" << std::endl; + CGAL::for_each + (list, [](int& i) { i *= 2; }); + + for (const int& i : list) + std::cerr << i << " "; + std::cerr << std::endl; + + std::cerr << "Testing parallel non-random access" << std::endl; + CGAL::for_each + (list, [](int& i) { i *= 2; }); + + for (const int& i : list) + std::cerr << i << " "; + std::cerr << std::endl; + + return 0; +} From db8650a8758357663aa01e4cb259265c1e55ed12 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 2 Mar 2020 12:23:56 +0100 Subject: [PATCH 03/26] Make filter iterator copiable --- .../include/CGAL/Poisson_reconstruction_function.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Poisson_surface_reconstruction_3/include/CGAL/Poisson_reconstruction_function.h b/Poisson_surface_reconstruction_3/include/CGAL/Poisson_reconstruction_function.h index 09b119bbe3b..bc434ba814a 100644 --- a/Poisson_surface_reconstruction_3/include/CGAL/Poisson_reconstruction_function.h +++ b/Poisson_surface_reconstruction_3/include/CGAL/Poisson_reconstruction_function.h @@ -106,13 +106,13 @@ struct Poisson_visitor { struct Poisson_skip_vertices { double ratio; - Random& m_random; - Poisson_skip_vertices(const double ratio, Random& random) + Random* m_random; + Poisson_skip_vertices(const double ratio = 0, Random* random = nullptr) : ratio(ratio), m_random(random) {} template bool operator()(Iterator) const { - return m_random.get_double() < ratio; + return m_random->get_double() < ratio; } }; @@ -419,7 +419,7 @@ public: Poisson_skip_vertices> Some_points_iterator; //make it deterministic Random random(0); - Poisson_skip_vertices skip(1.-approximation_ratio,random); + Poisson_skip_vertices skip(1.-approximation_ratio,&random); CGAL_TRACE_STREAM << "SPECIAL PASS that uses an approximation of the result (approximation ratio: " << approximation_ratio << ")" << std::endl; From 50ae0aeba4b9eae5bda72088d9e11ac381a05895 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 2 Mar 2020 12:24:40 +0100 Subject: [PATCH 04/26] Replace Parallel_callback by Callback_wrapper + cleaning/improvements of factorized KD Tree --- .../internal/Neighbor_query.h | 40 ++--- .../internal/Parallel_callback.h | 108 ----------- .../include/CGAL/bilateral_smooth_point_set.h | 165 +++++++---------- .../include/CGAL/compute_average_spacing.h | 126 ++++--------- .../include/CGAL/jet_estimate_normals.h | 65 ++----- .../include/CGAL/jet_smooth_point_set.h | 77 +++----- .../include/CGAL/mst_orient_normals.h | 2 +- .../include/CGAL/pca_estimate_normals.h | 72 +++----- .../include/CGAL/remove_outliers.h | 2 +- .../wlop_simplify_and_regularize_point_set.h | 168 ++++-------------- 10 files changed, 204 insertions(+), 621 deletions(-) delete mode 100644 Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Parallel_callback.h diff --git a/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Neighbor_query.h b/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Neighbor_query.h index 74ed1e17b5b..1160fb3a3e5 100644 --- a/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Neighbor_query.h +++ b/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Neighbor_query.h @@ -19,6 +19,8 @@ #include #include +#include + #include namespace CGAL { @@ -27,26 +29,26 @@ namespace internal { struct Maximum_points_reached_exception : public std::exception { }; -template +template class Neighbor_query { public: typedef Kernel_ Kernel; - typedef PointRange Point_range; + typedef PointRangeRef Point_range; typedef PointMap Point_map; typedef typename Kernel::FT FT; typedef typename Kernel::Point_3 Point_3; - typedef typename PointRange::iterator input_iterator; + typedef typename Range_iterator_type::type input_iterator; typedef typename input_iterator::value_type value_type; typedef CGAL::Prevent_deref iterator; struct Deref_point_map { - typedef iterator key_type; + typedef input_iterator key_type; typedef typename boost::property_traits::reference reference; typedef typename boost::property_traits::value_type value_type; typedef typename boost::property_traits::category category; @@ -58,14 +60,14 @@ public: friend reference get (const Deref_point_map& map, key_type it) { - return get(map.point_map, **it); + return get(map.point_map, *it); } }; typedef CGAL::Search_traits_3 Tree_traits_base; - typedef CGAL::Search_traits_adapter Tree_traits; + typedef CGAL::Search_traits_adapter Tree_traits; typedef CGAL::Sliding_midpoint Splitter; - typedef CGAL::Distance_adapter > Distance; + typedef CGAL::Distance_adapter > Distance; typedef CGAL::Kd_tree Tree; typedef CGAL::Fuzzy_sphere Sphere; @@ -74,7 +76,7 @@ public: private: - PointRange& m_points; + PointRangeRef m_points; PointMap m_point_map; Deref_point_map m_deref_map; Tree_traits m_traits; @@ -86,7 +88,7 @@ private: public: - Neighbor_query (PointRange& points, PointMap point_map) + Neighbor_query (PointRangeRef points, PointMap point_map) : m_points (points) , m_point_map (point_map) , m_deref_map (point_map) @@ -97,18 +99,6 @@ public: m_tree.build(); } - // Hack to avoid problems with const ranges - Neighbor_query (const PointRange& points, PointMap point_map) - : m_points (const_cast(points)) - , m_point_map (point_map) - , m_deref_map (point_map) - , m_traits (m_deref_map) - , m_tree (iterator(m_points.begin()), iterator(m_points.end()), Splitter(), m_traits) - , m_distance (m_deref_map) - { - m_tree.build(); - } - PointMap point_map() const { return m_point_map; } template @@ -127,10 +117,10 @@ public: try { - std::function output_iterator_with_limit - = [&](const iterator& it) + std::function output_iterator_with_limit + = [&](const input_iterator& it) { - *(output ++) = *it; + *(output ++) = it; if (++ nb == k) throw Maximum_points_reached_exception(); }; @@ -166,7 +156,7 @@ public: { if(search_iterator == search.end()) break; // premature ending - *(output ++) = *(search_iterator->first); + *(output ++) = search_iterator->first; search_iterator++; } } diff --git a/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Parallel_callback.h b/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Parallel_callback.h deleted file mode 100644 index 0064a9da985..00000000000 --- a/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Parallel_callback.h +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) 2018 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) : Simon Giraudot - -#ifndef CGAL_PSP_INTERNAL_PARALLEL_CALLBACK_H -#define CGAL_PSP_INTERNAL_PARALLEL_CALLBACK_H - -#include - -#include - -#include - -namespace CGAL { -namespace Point_set_processing_3 { -namespace internal { - -class Parallel_callback -{ - const std::function& m_callback; - cpp11::atomic* m_advancement; - cpp11::atomic* m_interrupted; - std::size_t m_size; - bool m_creator; - cpp11::thread* m_thread; - - // assignment operator shouldn't be used (m_callback is const ref) - Parallel_callback& operator= (const Parallel_callback&) - { - return *this; - } - -public: - Parallel_callback (const std::function& callback, - std::size_t size, - std::size_t advancement = 0, - bool interrupted = false) - : m_callback (callback) - , m_advancement (new cpp11::atomic()) - , m_interrupted (new cpp11::atomic()) - , m_size (size) - , m_creator (true) - , m_thread (nullptr) - { - // cpp11::atomic only has default constructor, initialization done in two steps - *m_advancement = advancement; - *m_interrupted = interrupted; - if (m_callback) - m_thread = new cpp11::thread (*this); - } - - Parallel_callback (const Parallel_callback& other) - : m_callback (other.m_callback) - , m_advancement (other.m_advancement) - , m_interrupted (other.m_interrupted) - , m_size (other.m_size) - , m_creator (false) - , m_thread (nullptr) - { - - } - - - ~Parallel_callback () - { - if (m_creator) - { - delete m_advancement; - delete m_interrupted; - } - if (m_thread != nullptr) - delete m_thread; - } - - cpp11::atomic& advancement() { return *m_advancement; } - cpp11::atomic& interrupted() { return *m_interrupted; } - void join() - { - if (m_thread != nullptr) - m_thread->join(); - } - - void operator()() - { - while (*m_advancement != m_size) - { - if (!m_callback (*m_advancement / double(m_size))) - *m_interrupted = true; - if (*m_interrupted) - return; - cpp11::sleep_for (0.00001); - } - m_callback (1.); - } -}; - -} // namespace internal -} // namespace Point_set_processing_3 -} // namespace CGAL - -#endif // CGAL_PSP_INTERNAL_PARALLEL_CALLBACK_H 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 ca871cca2cb..7a5ce9d36de 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 @@ -18,6 +18,8 @@ #include #include +#include +#include #include #include #include @@ -26,6 +28,8 @@ #include #include +#include + #include #include #include @@ -35,23 +39,6 @@ #include #include -#ifdef CGAL_LINKED_WITH_TBB - -#include -#include -#include -#include -#include -#endif // CGAL_LINKED_WITH_TBB - -// Default allocator: use TBB allocators if available -#ifdef CGAL_LINKED_WITH_TBB -# define CGAL_PSP3_DEFAULT_ALLOCATOR tbb::scalable_allocator -#else // CGAL_LINKED_WITH_TBB -# define CGAL_PSP3_DEFAULT_ALLOCATOR std::allocator -#endif // CGAL_LINKED_WITH_TBB - - //#define CGAL_PSP3_VERBOSE namespace CGAL { @@ -271,7 +258,7 @@ bilateral_smooth_point_set( CGAL_point_set_processing_precondition(k > 1); // types for K nearest neighbors search structure - typedef Point_set_processing_3::internal::Neighbor_query Neighbor_query; + typedef Point_set_processing_3::internal::Neighbor_query Neighbor_query; PointMap point_map = choose_parameter(get_parameter(np, internal_np::point_map), PointMap()); NormalMap normal_map = choose_parameter(get_parameter(np, internal_np::normal_map), NormalMap()); @@ -314,56 +301,38 @@ bilateral_smooth_point_set( task_timer.start(); #endif // compute all neighbors - std::vector > pwns_neighbors; + typedef std::vector iterators; + std::vector pwns_neighbors; pwns_neighbors.resize(nb_points); -#ifndef CGAL_LINKED_WITH_TBB - CGAL_static_assertion_msg (!(boost::is_convertible::value), - "Parallel_tag is enabled but TBB is unavailable."); -#else - if (boost::is_convertible::value) - { - Point_set_processing_3::internal::Parallel_callback - parallel_callback (callback, 2 * nb_points); + Point_set_processing_3::internal::Callback_wrapper + callback_wrapper (callback, 2 * nb_points); - tbb::parallel_for(tbb::blocked_range(0, nb_points), - [&](const tbb::blocked_range& r) - { - for (size_t i = r.begin(); i!=r.end(); i++) - { - if (parallel_callback.interrupted()) - break; + typedef boost::zip_iterator::iterator> > Zip_iterator; - neighbor_query.get_iterators (get(point_map, *(points.begin() + i)), k, neighbor_radius, - std::back_inserter (pwns_neighbors[i])); + CGAL::for_each + (CGAL::make_range (boost::make_zip_iterator (boost::make_tuple (points.begin(), pwns_neighbors.begin())), + boost::make_zip_iterator (boost::make_tuple (points.end(), pwns_neighbors.end()))), + [&](const typename Zip_iterator::reference& t) + { + if (callback_wrapper.interrupted()) + throw CGAL::internal::stop_for_each(); + + neighbor_query.get_iterators (get(point_map, get<0>(t)), k, neighbor_radius, + std::back_inserter (get<1>(t))); - ++ parallel_callback.advancement(); - } - }); + ++ callback_wrapper.advancement(); + }); - bool interrupted = parallel_callback.interrupted(); + bool interrupted = callback_wrapper.interrupted(); - // We interrupt by hand as counter only goes halfway and won't terminate by itself - parallel_callback.interrupted() = true; - parallel_callback.join(); + // We interrupt by hand as counter only goes halfway and won't terminate by itself + callback_wrapper.interrupted() = true; + callback_wrapper.join(); - // If interrupted during this step, nothing is computed, we return NaN - if (interrupted) - return std::numeric_limits::quiet_NaN(); - } - else -#endif - { - std::size_t nb = 0; - for (const value_type& vt : points) - { - neighbor_query.get_iterators (get (point_map, vt), k, neighbor_radius, std::back_inserter (pwns_neighbors[nb])); - - if (callback && !callback ((nb+1) / double(2. * nb_points))) - return std::numeric_limits::quiet_NaN(); - ++ nb; - } - } + // If interrupted during this step, nothing is computed, we return NaN + if (interrupted) + return std::numeric_limits::quiet_NaN(); #ifdef CGAL_PSP3_VERBOSE task_timer.stop(); @@ -378,53 +347,41 @@ bilateral_smooth_point_set( // update points and normals std::vector > update_pwns(nb_points); -#ifdef CGAL_LINKED_WITH_TBB - if(boost::is_convertible::value) - { - Point_set_processing_3::internal::Parallel_callback - parallel_callback (callback, 2 * nb_points, nb_points); + callback_wrapper.reset (2 * nb_points, nb_points); + + typedef boost::zip_iterator + ::iterator, + typename std::vector >::iterator> > Zip_iterator_2; + - tbb::parallel_for(tbb::blocked_range (0, nb_points), - [&](const tbb::blocked_range& r) - { - for (size_t i = r.begin(); i != r.end(); ++i) - { - if (parallel_callback.interrupted()) - break; - update_pwns[i] = bilateral_smooth_point_set_internal:: - compute_denoise_projection - (*(points.begin() + i), - point_map, normal_map, - pwns_neighbors[i], - guess_neighbor_radius, - sharpness_angle); - ++ parallel_callback.advancement(); - } - }); + CGAL::for_each + (CGAL::make_range (boost::make_zip_iterator (boost::make_tuple + (points.begin(), pwns_neighbors.begin(), update_pwns.begin())), + boost::make_zip_iterator (boost::make_tuple + (points.end(), pwns_neighbors.end(), update_pwns.end()))), + [&](const typename Zip_iterator_2::reference& t) + { + if (callback_wrapper.interrupted()) + throw CGAL::internal::stop_for_each(); - parallel_callback.join(); + get<2>(t) = bilateral_smooth_point_set_internal:: + compute_denoise_projection + (get<0>(t), + point_map, normal_map, + get<1>(t), + guess_neighbor_radius, + sharpness_angle); + + ++ callback_wrapper.advancement(); + }); + + callback_wrapper.join(); - // If interrupted during this step, nothing is computed, we return NaN - if (parallel_callback.interrupted()) - return std::numeric_limits::quiet_NaN(); - } - else -#endif // CGAL_LINKED_WITH_TBB - { - std::size_t nb = 0; - for (const value_type& vt : points) - { - update_pwns[nb] =bilateral_smooth_point_set_internal:: - compute_denoise_projection - (vt, point_map, normal_map, - pwns_neighbors[nb], - guess_neighbor_radius, - sharpness_angle); - if (callback && !callback ((nb+1) / double(2. * nb_points))) - return std::numeric_limits::quiet_NaN(); - ++ nb; - } - } + // If interrupted during this step, nothing is computed, we return NaN + if (callback_wrapper.interrupted()) + return std::numeric_limits::quiet_NaN(); + #ifdef CGAL_PSP3_VERBOSE task_timer.stop(); memory = CGAL::Memory_sizer().virtual_size(); 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 dd8242912d0..dfa111c50d6 100644 --- a/Point_set_processing_3/include/CGAL/compute_average_spacing.h +++ b/Point_set_processing_3/include/CGAL/compute_average_spacing.h @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include #include @@ -27,15 +29,12 @@ #include #include +#include + #include #include -#ifdef CGAL_LINKED_WITH_TBB -#include -#include -#include -#include -#endif // CGAL_LINKED_WITH_TBB + #ifdef DOXYGEN_RUNNING #define CGAL_BGL_NP_TEMPLATE_PARAMETERS NamedParameters @@ -91,43 +90,6 @@ compute_average_spacing(const typename NeighborQuery::Kernel::Point_3& query, // } -#ifdef CGAL_LINKED_WITH_TBB - template - class Compute_average_spacings { - typedef typename Kernel::Point_3 Point; - typedef typename Kernel::FT FT; - const Tree& tree; - const unsigned int k; - const std::vector& input; - std::vector& output; - cpp11::atomic& advancement; - cpp11::atomic& interrupted; - - public: - Compute_average_spacings(Tree& tree, unsigned int k, std::vector& points, - std::vector& output, - cpp11::atomic& advancement, - cpp11::atomic& interrupted) - : tree(tree), k (k), input (points), output (output) - , advancement (advancement) - , interrupted (interrupted) - { } - - void operator()(const tbb::blocked_range& r) const - { - for( std::size_t i = r.begin(); i != r.end(); ++i) - { - if (interrupted) - break; - - output[i] = CGAL::internal::compute_average_spacing(input[i], tree, k); - ++ advancement; - } - } - - }; -#endif // CGAL_LINKED_WITH_TBB - } /* namespace internal */ /// \endcond @@ -188,7 +150,7 @@ compute_average_spacing( using parameters::get_parameter; // basic geometric types - typedef typename PointRange::iterator iterator; + typedef typename PointRange::const_iterator iterator; typedef typename iterator::value_type value_type; typedef typename Point_set_processing_3::GetPointMap::const_type PointMap; typedef typename Point_set_processing_3::GetK::Kernel Kernel; @@ -201,7 +163,7 @@ compute_average_spacing( // types for K nearest neighbors search structure typedef typename Kernel::FT FT; - typedef Point_set_processing_3::internal::Neighbor_query Neighbor_query; + typedef Point_set_processing_3::internal::Neighbor_query Neighbor_query; // precondition: at least one element in the container. // to fix: should have at least three distinct points @@ -218,60 +180,38 @@ compute_average_spacing( // vectors (already normalized) FT sum_spacings = (FT)0.0; std::size_t nb = 0; - std::size_t nb_points = points.size(); + std::size_t nb_points = std::distance(points.begin(), points.end()); -#ifndef CGAL_LINKED_WITH_TBB - CGAL_static_assertion_msg (!(boost::is_convertible::value), - "Parallel_tag is enabled but TBB is unavailable."); -#else - if (boost::is_convertible::value) - { - Point_set_processing_3::internal::Parallel_callback - parallel_callback (callback, nb_points); + Point_set_processing_3::internal::Callback_wrapper + callback_wrapper (callback, nb_points); - std::vector spacings (nb_points, -1); - tbb::parallel_for(tbb::blocked_range(0, nb_points), - [&](const tbb::blocked_range& r) - { - for( std::size_t i = r.begin(); i != r.end(); ++i) - { - if (parallel_callback.interrupted()) - break; - - spacings[i] = CGAL::internal::compute_average_spacing - (get(point_map, *(points.begin() + i)), neighbor_query, k); - ++ parallel_callback.advancement(); - } + std::vector spacings (nb_points, -1); - }); - - for (unsigned int i = 0; i < spacings.size (); ++ i) - if (spacings[i] >= 0.) - { - sum_spacings += spacings[i]; - ++ nb; - } - - parallel_callback.join(); - } - else -#endif + typedef boost::zip_iterator::iterator> > Zip_iterator; + + CGAL::for_each + (CGAL::make_range (boost::make_zip_iterator (boost::make_tuple (points.begin(), spacings.begin())), + boost::make_zip_iterator (boost::make_tuple (points.end(), spacings.end()))), + [&](const typename Zip_iterator::reference& t) { - for(typename PointRange::const_iterator it = points.begin(); it != points.end(); it++, nb++) - { - sum_spacings += internal::compute_average_spacing( - get(point_map,*it), - neighbor_query,k); - if (callback && !callback ((nb+1) / double(nb_points))) - { - ++ nb; - break; - } - } - } + if (callback_wrapper.interrupted()) + throw CGAL::internal::stop_for_each(); + + get<1>(t) = CGAL::internal::compute_average_spacing + (get(point_map, get<0>(t)), neighbor_query, k); + ++ callback_wrapper.advancement(); + }); + + for (unsigned int i = 0; i < spacings.size (); ++ i) + if (spacings[i] >= 0.) + { + sum_spacings += spacings[i]; + ++ nb; + } + callback_wrapper.join(); // return average spacing - return sum_spacings / (FT)(nb); + return sum_spacings / (FT)(nb); } /// \cond SKIP_IN_MANUAL 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 5095bfacb70..61affa8787b 100644 --- a/Point_set_processing_3/include/CGAL/jet_estimate_normals.h +++ b/Point_set_processing_3/include/CGAL/jet_estimate_normals.h @@ -18,6 +18,8 @@ #include #include +#include +#include #include #include #include @@ -30,13 +32,6 @@ #include #include -#ifdef CGAL_LINKED_WITH_TBB -#include -#include -#include -#include -#endif // CGAL_LINKED_WITH_TBB - namespace CGAL { @@ -183,7 +178,7 @@ jet_estimate_normals( typedef typename boost::property_traits::value_type Vector; // types for K nearest neighbors search structure - typedef Point_set_processing_3::internal::Neighbor_query Neighbor_query; + typedef Point_set_processing_3::internal::Neighbor_query Neighbor_query; // precondition: at least one element in the container. // to fix: should have at least three distinct points @@ -203,51 +198,23 @@ jet_estimate_normals( std::size_t nb_points = points.size(); - // iterate over input points, compute and output normal - // vectors (already normalized) -#ifndef CGAL_LINKED_WITH_TBB - CGAL_static_assertion_msg (!(boost::is_convertible::value), - "Parallel_tag is enabled but TBB is unavailable."); -#else - if (boost::is_convertible::value) - { - Point_set_processing_3::internal::Parallel_callback - parallel_callback (callback, nb_points); - - tbb::parallel_for(tbb::blocked_range(0, points.size ()), - [&](const tbb::blocked_range& r) - { - for( std::size_t i = r.begin(); i != r.end(); ++i) - { - if (parallel_callback.interrupted()) - break; - put (normal_map, *(points.begin() + i), - CGAL::internal::jet_estimate_normal - (get(point_map, *(points.begin() + i)), neighbor_query, k, neighbor_radius, degree_fitting)); - ++ parallel_callback.advancement(); - } - }); + Point_set_processing_3::internal::Callback_wrapper + callback_wrapper (callback, nb_points); - parallel_callback.join(); - } - else -#endif - { - std::size_t nb = 0; - for (const value_type& vt : points) + CGAL::for_each + (points, + [&](const value_type& vt) { + if (callback_wrapper.interrupted()) + throw internal::stop_for_each(); + put (normal_map, vt, - internal::jet_estimate_normal( - get(point_map, vt), - neighbor_query, k, neighbor_radius, degree_fitting)); - - if (callback && !callback ((nb+1) / double(nb_points))) - break; - - ++ nb; - } - } + CGAL::internal::jet_estimate_normal + (get(point_map, vt), neighbor_query, k, neighbor_radius, degree_fitting)); + ++ callback_wrapper.advancement(); + }); + callback_wrapper.join(); memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20); CGAL_TRACE("End of jet_estimate_normals()\n"); 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 acf12856e4b..8f4e5134ef2 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 @@ -18,6 +18,8 @@ #include #include +#include +#include #include #include #include @@ -29,13 +31,6 @@ #include #include -#ifdef CGAL_LINKED_WITH_TBB -#include -#include -#include -#include -#endif // CGAL_LINKED_WITH_TBB - namespace CGAL { @@ -178,7 +173,7 @@ jet_smooth_point_set( typedef typename Kernel::Point_3 Point; // types for K nearest neighbors search structure - typedef Point_set_processing_3::internal::Neighbor_query Neighbor_query; + typedef Point_set_processing_3::internal::Neighbor_query Neighbor_query; // precondition: at least one element in the container. // to fix: should have at least three distinct points @@ -196,59 +191,27 @@ jet_smooth_point_set( std::size_t nb_points = points.size(); -#ifndef CGAL_LINKED_WITH_TBB - CGAL_static_assertion_msg (!(boost::is_convertible::value), - "Parallel_tag is enabled but TBB is unavailable."); -#else - if (boost::is_convertible::value) - { - Point_set_processing_3::internal::Parallel_callback - parallel_callback (callback, nb_points); - - std::vector mutated_points (nb_points, CGAL::ORIGIN); - tbb::parallel_for(tbb::blocked_range(0, nb_points), - [&](const tbb::blocked_range& r) - { - for( std::size_t i = r.begin(); i != r.end(); ++i) - { - if (parallel_callback.interrupted()) - break; - mutated_points[i] = - CGAL::internal::jet_smooth_point - (get (point_map, *(points.begin() + i)), neighbor_query, - k, - neighbor_radius, - degree_fitting, - degree_monge); - ++ parallel_callback.advancement(); - } - }); + Point_set_processing_3::internal::Callback_wrapper + callback_wrapper (callback, nb_points); - unsigned int i = 0; - for (const value_type& vt : points) + CGAL::for_each + (points, + [&](value_type vt) { - if (mutated_points[i] != CGAL::ORIGIN) - put(point_map, vt, mutated_points[i]); - ++ i; - } + if (callback_wrapper.interrupted()) + throw internal::stop_for_each(); - parallel_callback.join(); + put (point_map, vt, + CGAL::internal::jet_smooth_point + (get (point_map, vt), neighbor_query, + k, + neighbor_radius, + degree_fitting, + degree_monge)); + ++ callback_wrapper.advancement(); + }); - } - else -#endif - { - std::size_t nb = 0; - for (const value_type& vt : points) - { - put(point_map, vt, - internal::jet_smooth_point - (get (point_map, vt), neighbor_query,k,neighbor_radius,degree_fitting,degree_monge) ); - if (callback && !callback ((nb+1) / double(nb_points))) - break; - ++ nb; - } - } + callback_wrapper.join(); } diff --git a/Point_set_processing_3/include/CGAL/mst_orient_normals.h b/Point_set_processing_3/include/CGAL/mst_orient_normals.h index 1db0b213053..2b21c7b31d7 100644 --- a/Point_set_processing_3/include/CGAL/mst_orient_normals.h +++ b/Point_set_processing_3/include/CGAL/mst_orient_normals.h @@ -317,7 +317,7 @@ create_riemannian_graph( // Types for K nearest neighbors search structure typedef typename PointRange::iterator ForwardIterator; - typedef Point_set_processing_3::internal::Neighbor_query Neighbor_query; + typedef Point_set_processing_3::internal::Neighbor_query Neighbor_query; // Riemannian_graph types typedef internal::Riemannian_graph Riemannian_graph; 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 63c9782b60c..515e8489de3 100644 --- a/Point_set_processing_3/include/CGAL/pca_estimate_normals.h +++ b/Point_set_processing_3/include/CGAL/pca_estimate_normals.h @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include #include @@ -31,13 +33,6 @@ #include #include -#ifdef CGAL_LINKED_WITH_TBB -#include -#include -#include -#include -#endif // CGAL_LINKED_WITH_TBB - namespace CGAL { @@ -168,7 +163,7 @@ pca_estimate_normals( typedef typename boost::property_traits::value_type Vector; // types for K nearest neighbors search structure - typedef Point_set_processing_3::internal::Neighbor_query Neighbor_query; + typedef Point_set_processing_3::internal::Neighbor_query Neighbor_query; // precondition: at least one element in the container. // to fix: should have at least three distinct points @@ -188,51 +183,24 @@ pca_estimate_normals( std::size_t nb_points = points.size(); - // iterate over input points, compute and output normal - // vectors (already normalized) -#ifndef CGAL_LINKED_WITH_TBB - CGAL_static_assertion_msg (!(boost::is_convertible::value), - "Parallel_tag is enabled but TBB is unavailable."); -#else - if (boost::is_convertible::value) - { - Point_set_processing_3::internal::Parallel_callback - parallel_callback (callback, nb_points); - - tbb::parallel_for(tbb::blocked_range(0, nb_points), - [&](const tbb::blocked_range& r) - { - for( std::size_t i = r.begin(); i != r.end(); ++i) - { - if (parallel_callback.interrupted()) - break; - - put (normal_map, *(points.begin() + i), - CGAL::internal::pca_estimate_normal - (get(point_map, *(points.begin() + i)), neighbor_query, k, neighbor_radius)); - - ++ parallel_callback.advancement(); - } - }); + Point_set_processing_3::internal::Callback_wrapper + callback_wrapper (callback, nb_points); - parallel_callback.join(); - } - else -#endif - { - std::size_t nb = 0; - for (const value_type& vt : points) - { - put (normal_map, vt, - internal::pca_estimate_normal( - get(point_map, vt), - neighbor_query, - k, neighbor_radius)); - if (callback && !callback ((nb+1) / double(nb_points))) - break; - ++ nb; - } - } + CGAL::for_each + (points, + [&](const value_type& vt) + { + if (callback_wrapper.interrupted()) + throw internal::stop_for_each(); + + put (normal_map, vt, + CGAL::internal::pca_estimate_normal + (get(point_map, vt), neighbor_query, k, neighbor_radius)); + + ++ callback_wrapper.advancement(); + }); + + callback_wrapper.join(); memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20); CGAL_TRACE("End of pca_estimate_normals()\n"); diff --git a/Point_set_processing_3/include/CGAL/remove_outliers.h b/Point_set_processing_3/include/CGAL/remove_outliers.h index 63b4754216c..4a625c181a5 100644 --- a/Point_set_processing_3/include/CGAL/remove_outliers.h +++ b/Point_set_processing_3/include/CGAL/remove_outliers.h @@ -166,7 +166,7 @@ remove_outliers( typedef typename std::iterator_traits::value_type Enriched_point; // types for K nearest neighbors search structure - typedef Point_set_processing_3::internal::Neighbor_query Neighbor_query; + typedef Point_set_processing_3::internal::Neighbor_query Neighbor_query; // precondition: at least one element in the container. // to fix: should have at least three distinct points 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 cbe5b1ca5fb..388a2a23ed1 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 @@ -32,12 +32,8 @@ #include #include -#ifdef CGAL_LINKED_WITH_TBB -#include -#include -#include -#include -#endif // CGAL_LINKED_WITH_TBB +#include +#include #include #include @@ -329,67 +325,6 @@ compute_density_weight_for_sample_point( /// \endcond -#ifdef CGAL_LINKED_WITH_TBB -/// \cond SKIP_IN_MANUAL -/// This is for parallelization of function: compute_denoise_projection() -template -class Sample_point_updater -{ - typedef typename Kernel::Point_3 Point; - typedef typename Kernel::FT FT; - - std::vector &update_sample_points; - std::vector &sample_points; - const Tree &original_kd_tree; - const Tree &sample_kd_tree; - const typename Kernel::FT radius; - const std::vector &original_densities; - const std::vector &sample_densities; - cpp11::atomic& advancement; - cpp11::atomic& interrupted; - -public: - Sample_point_updater( - std::vector &out, - std::vector &in, - const Tree &_original_kd_tree, - const Tree &_sample_kd_tree, - const typename Kernel::FT _radius, - const std::vector &_original_densities, - const std::vector &_sample_densities, - cpp11::atomic& advancement, - cpp11::atomic& interrupted): - update_sample_points(out), - sample_points(in), - original_kd_tree(_original_kd_tree), - sample_kd_tree(_sample_kd_tree), - radius(_radius), - original_densities(_original_densities), - sample_densities(_sample_densities), - advancement (advancement), - interrupted (interrupted) {} - - void operator() ( const tbb::blocked_range& r ) const - { - for (size_t i = r.begin(); i != r.end(); ++i) - { - if (interrupted) - break; - update_sample_points[i] = simplify_and_regularize_internal:: - compute_update_sample_point( - sample_points[i], - original_kd_tree, - sample_kd_tree, - radius, - original_densities, - sample_densities); - ++ advancement; - } - } -}; -/// \endcond -#endif // CGAL_LINKED_WITH_TBB - // ---------------------------------------------------------------------------- // Public section @@ -464,6 +399,8 @@ wlop_simplify_and_regularize_point_set( using parameters::get_parameter; // basic geometric types + typedef typename PointRange::iterator iterator; + typedef typename iterator::value_type value_type; typedef typename Point_set_processing_3::GetPointMap::type PointMap; typedef typename Point_set_processing_3::GetK::Kernel Kernel; @@ -587,80 +524,49 @@ wlop_simplify_and_regularize_point_set( sample_density_weights.push_back(density); } - - typename std::vector::iterator update_iter = update_sample_points.begin(); -#ifndef CGAL_LINKED_WITH_TBB - CGAL_static_assertion_msg (!(boost::is_convertible::value), - "Parallel_tag is enabled but TBB is unavailable."); -#else - //parallel - if (boost::is_convertible::value) - { - Point_set_processing_3::internal::Parallel_callback - parallel_callback (callback, iter_number * number_of_sample, iter_n * number_of_sample); - - tbb::blocked_range block(0, number_of_sample); - Sample_point_updater sample_updater( - update_sample_points, - sample_points, - original_kd_tree, - sample_kd_tree, - radius2, - original_density_weights, - sample_density_weights, - parallel_callback.advancement(), - parallel_callback.interrupted()); + typedef boost::zip_iterator::iterator, + typename std::vector::iterator> > Zip_iterator; - tbb::parallel_for(block, sample_updater); + Point_set_processing_3::internal::Callback_wrapper + callback_wrapper (callback, iter_number * number_of_sample, iter_n * number_of_sample); - bool interrupted = parallel_callback.interrupted(); + CGAL::for_each + (CGAL::make_range (boost::make_zip_iterator (boost::make_tuple (sample_points.begin(), update_sample_points.begin())), + boost::make_zip_iterator (boost::make_tuple (sample_points.end(), update_sample_points.end()))), + [&](const typename Zip_iterator::reference& t) + { + if (callback_wrapper.interrupted()) + throw internal::stop_for_each(); + + get<1>(t) = simplify_and_regularize_internal:: + compute_update_sample_point( + get<0>(t), + original_kd_tree, + sample_kd_tree, + radius, + original_density_weights, + sample_density_weights); + ++ callback_wrapper.advancement(); + }); + + bool interrupted = callback_wrapper.interrupted(); - // We interrupt by hand as counter only goes halfway and won't terminate by itself - parallel_callback.interrupted() = true; - parallel_callback.join(); + // We interrupt by hand as counter only goes halfway and won't terminate by itself + callback_wrapper.interrupted() = true; + callback_wrapper.join(); - // If interrupted during this step, nothing is computed, we return NaN - if (interrupted) - return output; - }else -#endif - { - //sequential - std::size_t nb = iter_n * number_of_sample; - for (sample_iter = sample_points.begin(); - sample_iter != sample_points.end(); ++sample_iter, ++update_iter, ++ nb) - { - *update_iter = simplify_and_regularize_internal:: - compute_update_sample_point - (*sample_iter, - original_kd_tree, - sample_kd_tree, - radius2, - original_density_weights, - sample_density_weights); - if (callback && !callback ((nb+1) / double(iter_number * number_of_sample))) - return output; - } - } + // If interrupted during this step, nothing is computed, we return NaN + if (interrupted) + return output; sample_iter = sample_points.begin(); - for (update_iter = update_sample_points.begin(); - update_iter != update_sample_points.end(); - ++update_iter, ++sample_iter) - { - *sample_iter = *update_iter; - } + for (std::size_t i = 0; i < sample_points.size(); ++ i) + sample_points[i] = update_sample_points[i]; } // final output - for(sample_iter = sample_points.begin(); - sample_iter != sample_points.end(); ++sample_iter) - { - *output++ = *sample_iter; - } + std::copy (sample_points.begin(), sample_points.end(), output); return output; } From fb3ed791484c9f8529ec70fe0e2c877e0c35bdc4 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 2 Mar 2020 13:26:23 +0100 Subject: [PATCH 05/26] Add missing file --- .../internal/Callback_wrapper.h | 182 ++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Callback_wrapper.h diff --git a/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Callback_wrapper.h b/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Callback_wrapper.h new file mode 100644 index 00000000000..c8ea5f10dfa --- /dev/null +++ b/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Callback_wrapper.h @@ -0,0 +1,182 @@ +// Copyright (c) 2018 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) : Simon Giraudot + +#ifndef CGAL_PSP_INTERNAL_CALLBACK_WRAPPER_H +#define CGAL_PSP_INTERNAL_CALLBACK_WRAPPER_H + +#include + +#include + +#include + +namespace CGAL { +namespace Point_set_processing_3 { +namespace internal { + +template +class Callback_wrapper +{ + std::size_t m_advancement; + bool m_interrupted; + +public: + Callback_wrapper (const std::function&, std::size_t, std::size_t, bool = false) { } + void reset (std::size_t, std::size_t, bool = false) { } + std::size_t& advancement() { return m_advancement; } + bool& interrupted() { return m_interrupted; } + void join() { } +}; + +template <> +class Callback_wrapper +{ + const std::function& m_callback; + std::size_t m_advancement; + bool m_interrupted; + std::size_t m_size; + +public: + + Callback_wrapper (const std::function& callback, + std::size_t size, + std::size_t advancement = 0, + bool interrupted = false) + : m_callback (callback) + , m_advancement (advancement) + , m_interrupted (interrupted) + , m_size (size) + { } + + Callback_wrapper (const Callback_wrapper& other) + : m_callback (other.m_callback) + , m_advancement (other.m_advancement) + , m_interrupted (other.m_interrupted) + , m_size (other.m_size) + { } + + ~Callback_wrapper () { } + + void reset (std::size_t size, std::size_t advancement, bool interrupted = false) + { + m_size = size; + m_advancement = advancement; + m_interrupted = interrupted; + } + std::size_t& advancement() + { + return m_advancement; + } + + bool& interrupted() + { + m_interrupted = (m_callback(m_advancement / double(m_size))); + return m_interrupted; + } + + void join() { } +}; + +#ifdef CGAL_LINKED_WITH_TBB +template <> +class Callback_wrapper +{ + const std::function& m_callback; + cpp11::atomic* m_advancement; + cpp11::atomic* m_interrupted; + std::size_t m_size; + bool m_creator; + cpp11::thread* m_thread; + + // assignment operator shouldn't be used (m_callback is const ref) + Callback_wrapper& operator= (const Callback_wrapper&) + { + return *this; + } + +public: + Callback_wrapper (const std::function& callback, + std::size_t size, + std::size_t advancement = 0, + bool interrupted = false) + : m_callback (callback) + , m_advancement (new cpp11::atomic()) + , m_interrupted (new cpp11::atomic()) + , m_size (size) + , m_creator (true) + , m_thread (nullptr) + { + // cpp11::atomic only has default constructor, initialization done in two steps + *m_advancement = advancement; + *m_interrupted = interrupted; + if (m_callback) + m_thread = new cpp11::thread (*this); + } + + Callback_wrapper (const Callback_wrapper& other) + : m_callback (other.m_callback) + , m_advancement (other.m_advancement) + , m_interrupted (other.m_interrupted) + , m_size (other.m_size) + , m_creator (false) + , m_thread (nullptr) + { + + } + + ~Callback_wrapper () + { + if (m_creator) + { + delete m_advancement; + delete m_interrupted; + } + if (m_thread != nullptr) + delete m_thread; + } + + void reset (std::size_t size, std::size_t advancement, bool interrupted = false) + { + m_size = size; + *m_advancement = advancement; + *m_interrupted = interrupted; + if (m_callback) + m_thread = new cpp11::thread (*this); + } + + cpp11::atomic& advancement() { return *m_advancement; } + cpp11::atomic& interrupted() { return *m_interrupted; } + void join() + { + if (m_thread != nullptr) + m_thread->join(); + } + + void operator()() + { + while (*m_advancement != m_size) + { + if (!m_callback (*m_advancement / double(m_size))) + *m_interrupted = true; + if (*m_interrupted) + return; + cpp11::sleep_for (0.00001); + } + m_callback (1.); + } +}; +#endif + +} // namespace internal +} // namespace Point_set_processing_3 +} // namespace CGAL + +#endif // CGAL_PSP_INTERNAL_CALLBACK_WRAPPER_H From 90f7d81291f79fbd0ef533bfdc1cc64969844d6a Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 2 Mar 2020 16:11:55 +0100 Subject: [PATCH 06/26] Fix callback wrapper if no callback provided --- .../internal/Callback_wrapper.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Callback_wrapper.h b/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Callback_wrapper.h index c8ea5f10dfa..e6b13e234fe 100644 --- a/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Callback_wrapper.h +++ b/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Callback_wrapper.h @@ -47,9 +47,9 @@ class Callback_wrapper public: Callback_wrapper (const std::function& callback, - std::size_t size, - std::size_t advancement = 0, - bool interrupted = false) + std::size_t size, + std::size_t advancement = 0, + bool interrupted = false) : m_callback (callback) , m_advancement (advancement) , m_interrupted (interrupted) @@ -78,7 +78,8 @@ public: bool& interrupted() { - m_interrupted = (m_callback(m_advancement / double(m_size))); + if (m_callback) + m_interrupted = (m_callback(m_advancement / double(m_size))); return m_interrupted; } @@ -164,13 +165,14 @@ public: { while (*m_advancement != m_size) { - if (!m_callback (*m_advancement / double(m_size))) + if (m_callback && !m_callback (*m_advancement / double(m_size))) *m_interrupted = true; if (*m_interrupted) return; cpp11::sleep_for (0.00001); } - m_callback (1.); + if (m_callback) + m_callback (1.); } }; #endif From 74151aea0f437641f32ed5bc1abb4812ceb22eb9 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 5 Mar 2020 10:01:01 +0100 Subject: [PATCH 07/26] Fix constness error --- Point_set_processing_3/include/CGAL/jet_estimate_normals.h | 2 +- Point_set_processing_3/include/CGAL/pca_estimate_normals.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 61affa8787b..c78c3f9951f 100644 --- a/Point_set_processing_3/include/CGAL/jet_estimate_normals.h +++ b/Point_set_processing_3/include/CGAL/jet_estimate_normals.h @@ -203,7 +203,7 @@ jet_estimate_normals( CGAL::for_each (points, - [&](const value_type& vt) + [&](value_type& vt) { if (callback_wrapper.interrupted()) throw internal::stop_for_each(); 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 515e8489de3..50dd11631ed 100644 --- a/Point_set_processing_3/include/CGAL/pca_estimate_normals.h +++ b/Point_set_processing_3/include/CGAL/pca_estimate_normals.h @@ -188,7 +188,7 @@ pca_estimate_normals( CGAL::for_each (points, - [&](const value_type& vt) + [&](value_type& vt) { if (callback_wrapper.interrupted()) throw internal::stop_for_each(); From 10676940593368f8b9f2138eeab214f65e575ce7 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 5 Mar 2020 11:44:45 +0100 Subject: [PATCH 08/26] Fix some errors --- .../include/CGAL/bilateral_smooth_point_set.h | 2 +- Point_set_processing_3/include/CGAL/remove_outliers.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) 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 7a5ce9d36de..9c4d7cd8cf7 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 @@ -392,7 +392,7 @@ bilateral_smooth_point_set( FT sum_move_error = 0; std::size_t nb = 0; typename PointRange::iterator it = points.begin(); - for (const value_type& vt : points) + for (value_type& vt : points) { sum_move_error += CGAL::squared_distance(get(point_map, vt), update_pwns[nb].first); put (point_map, vt, update_pwns[nb].first); diff --git a/Point_set_processing_3/include/CGAL/remove_outliers.h b/Point_set_processing_3/include/CGAL/remove_outliers.h index 4a625c181a5..f49932d308a 100644 --- a/Point_set_processing_3/include/CGAL/remove_outliers.h +++ b/Point_set_processing_3/include/CGAL/remove_outliers.h @@ -53,9 +53,10 @@ compute_avg_knn_sq_distance_3( const typename NeighborQuery::Kernel::Point_3& query, ///< 3D point to project NeighborQuery& neighbor_query, ///< KD-tree unsigned int k, ///< number of neighbors - typename Kernel::FT neighbor_radius) + typename NeighborQuery::Kernel::FT neighbor_radius) { // geometric types + typedef typename NeighborQuery::Kernel Kernel; typedef typename Kernel::FT FT; typedef typename Kernel::Point_3 Point; From b2db69f8f1a6e7e2c066a3958ed5ac0ad721f1a6 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 5 Mar 2020 14:36:38 +0100 Subject: [PATCH 09/26] Fix license --- STL_Extension/include/CGAL/for_each.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/STL_Extension/include/CGAL/for_each.h b/STL_Extension/include/CGAL/for_each.h index 8096592370d..819e95f063d 100644 --- a/STL_Extension/include/CGAL/for_each.h +++ b/STL_Extension/include/CGAL/for_each.h @@ -5,7 +5,7 @@ // // $URL$ // $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial // // Author(s) : Simon Giraudot From 0fe2ee40e88822430d203587e42f00ef1db346b7 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 12 Mar 2020 10:27:59 +0100 Subject: [PATCH 10/26] Fix outdated precondition --- Point_set_processing_3/include/CGAL/mst_orient_normals.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/Point_set_processing_3/include/CGAL/mst_orient_normals.h b/Point_set_processing_3/include/CGAL/mst_orient_normals.h index 2b21c7b31d7..ce1b00ce43f 100644 --- a/Point_set_processing_3/include/CGAL/mst_orient_normals.h +++ b/Point_set_processing_3/include/CGAL/mst_orient_normals.h @@ -323,9 +323,6 @@ create_riemannian_graph( typedef internal::Riemannian_graph Riemannian_graph; typedef typename boost::property_map::type Riemannian_graph_weight_map; - // Precondition: at least one element in the container. - CGAL_point_set_processing_precondition(first != beyond); - // Precondition: at least 2 nearest neighbors CGAL_point_set_processing_precondition(k >= 2); From 6b2242356d3d5271184625421981986983f734f4 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 17 Mar 2020 12:03:58 +0100 Subject: [PATCH 11/26] Fix uninitialized variable --- Point_set_processing_3/include/CGAL/compute_average_spacing.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 dfa111c50d6..2ee0b8ad0bc 100644 --- a/Point_set_processing_3/include/CGAL/compute_average_spacing.h +++ b/Point_set_processing_3/include/CGAL/compute_average_spacing.h @@ -75,7 +75,7 @@ compute_average_spacing(const typename NeighborQuery::Kernel::Point_3& query, // // output first). search may be aborted when k is greater // than number of input points FT sum_distances = (FT)0.0; - unsigned int i; + unsigned int i = 0; neighbor_query.get_points (query, k, 0, boost::make_function_output_iterator From a27ab3aa66f585dbe7a144e1143599508a070107 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 18 Mar 2020 09:05:57 +0100 Subject: [PATCH 12/26] Fix unused variable --- Point_set_processing_3/include/CGAL/jet_smooth_point_set.h | 2 -- 1 file changed, 2 deletions(-) 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 8f4e5134ef2..c29d67c55c1 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 @@ -170,8 +170,6 @@ jet_smooth_point_set( const std::function& callback = choose_parameter(get_parameter(np, internal_np::callback), std::function()); - typedef typename Kernel::Point_3 Point; - // types for K nearest neighbors search structure typedef Point_set_processing_3::internal::Neighbor_query Neighbor_query; From 61b51605b2ae3f2a5725d1aa772d81baf73cd487 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 18 Mar 2020 09:06:09 +0100 Subject: [PATCH 13/26] Fix sequential callback wrapper --- .../CGAL/Point_set_processing_3/internal/Callback_wrapper.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Callback_wrapper.h b/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Callback_wrapper.h index e6b13e234fe..8612be034fd 100644 --- a/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Callback_wrapper.h +++ b/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Callback_wrapper.h @@ -79,7 +79,7 @@ public: bool& interrupted() { if (m_callback) - m_interrupted = (m_callback(m_advancement / double(m_size))); + m_interrupted = !(m_callback(m_advancement / double(m_size))); return m_interrupted; } From 61d331f45698fb518383526d3efbc3c28ef5c62b Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 18 Mar 2020 09:11:41 +0100 Subject: [PATCH 14/26] Fix for_each --- STL_Extension/include/CGAL/for_each.h | 8 ++++---- STL_Extension/include/CGAL/iterator.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/STL_Extension/include/CGAL/for_each.h b/STL_Extension/include/CGAL/for_each.h index 819e95f063d..e0ac595c753 100644 --- a/STL_Extension/include/CGAL/for_each.h +++ b/STL_Extension/include/CGAL/for_each.h @@ -41,7 +41,7 @@ void for_each (RangeRef range, { functor(r); } - catch (stop_for_each) + catch (const stop_for_each&) { break; } @@ -70,7 +70,7 @@ void for_each (RangeRef range, { functor (*(iterators[i])); } - catch (stop_for_each) + catch (const stop_for_each&) { return; } @@ -78,7 +78,7 @@ void for_each (RangeRef range, } template -void for_each (const RangeRef range, +void for_each (RangeRef range, const std::function::type>::reference)>& functor, const Parallel_tag&, @@ -94,7 +94,7 @@ void for_each (const RangeRef range, { functor (*(range.begin() + i)); } - catch (stop_for_each) + catch (const stop_for_each&) { return; } diff --git a/STL_Extension/include/CGAL/iterator.h b/STL_Extension/include/CGAL/iterator.h index 4875fb69aa5..8424af8487f 100644 --- a/STL_Extension/include/CGAL/iterator.h +++ b/STL_Extension/include/CGAL/iterator.h @@ -1474,7 +1474,7 @@ dispatch_or_drop_output(O... o) // Trick to select iterator or const_iterator depending on the range constness template -struct Range_iterator_type { typedef int type; }; // Should generate errors +struct Range_iterator_type; template struct Range_iterator_type { typedef typename RangeRef::iterator type; }; template From 49674688dc931a79cfe26ce501ee9f81cc8429f3 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 18 Mar 2020 14:03:31 +0100 Subject: [PATCH 15/26] Fix unused typedefs --- Point_set_processing_3/include/CGAL/jet_estimate_normals.h | 5 ----- 1 file changed, 5 deletions(-) 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 c78c3f9951f..302fdadc19c 100644 --- a/Point_set_processing_3/include/CGAL/jet_estimate_normals.h +++ b/Point_set_processing_3/include/CGAL/jet_estimate_normals.h @@ -172,11 +172,6 @@ jet_estimate_normals( const std::function& callback = choose_parameter(get_parameter(np, internal_np::callback), std::function()); - typedef typename Kernel::Point_3 Point; - - // Input points types - typedef typename boost::property_traits::value_type Vector; - // types for K nearest neighbors search structure typedef Point_set_processing_3::internal::Neighbor_query Neighbor_query; From 8d9dac02eabb10d190d21331737dc1762f68dacc Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 18 Mar 2020 16:14:00 +0100 Subject: [PATCH 16/26] Fix many warnings --- .../include/CGAL/bilateral_smooth_point_set.h | 6 ++---- .../include/CGAL/compute_average_spacing.h | 3 --- Point_set_processing_3/include/CGAL/pca_estimate_normals.h | 3 --- Point_set_processing_3/include/CGAL/remove_outliers.h | 1 - .../include/CGAL/wlop_simplify_and_regularize_point_set.h | 5 +---- 5 files changed, 3 insertions(+), 15 deletions(-) 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 9c4d7cd8cf7..12ee8b09411 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 @@ -129,12 +129,11 @@ compute_denoise_projection( /// @tparam Tree KD-tree. /// /// @return max spacing. -template +template typename NeighborQuery::Kernel::FT compute_max_spacing( const typename NeighborQuery::value_type& vt, typename NeighborQuery::Point_map point_map, - VectorMap normal_map, NeighborQuery& neighbor_query, ///< KD-tree unsigned int k) ///< number of neighbors { @@ -282,7 +281,7 @@ bilateral_smooth_point_set( for (const value_type& vt : points) { FT max_spacing = bilateral_smooth_point_set_internal:: - compute_max_spacing (vt, point_map, normal_map, neighbor_query, k); + compute_max_spacing (vt, point_map, neighbor_query, k); guess_neighbor_radius = (CGAL::max)(max_spacing, guess_neighbor_radius); } @@ -391,7 +390,6 @@ bilateral_smooth_point_set( // save results FT sum_move_error = 0; std::size_t nb = 0; - typename PointRange::iterator it = points.begin(); for (value_type& vt : points) { sum_move_error += CGAL::squared_distance(get(point_map, vt), update_pwns[nb].first); 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 2ee0b8ad0bc..c202f9b4dc5 100644 --- a/Point_set_processing_3/include/CGAL/compute_average_spacing.h +++ b/Point_set_processing_3/include/CGAL/compute_average_spacing.h @@ -151,12 +151,9 @@ compute_average_spacing( // basic geometric types typedef typename PointRange::const_iterator iterator; - typedef typename iterator::value_type value_type; typedef typename Point_set_processing_3::GetPointMap::const_type PointMap; typedef typename Point_set_processing_3::GetK::Kernel Kernel; - typedef typename Kernel::Point_3 Point; - PointMap point_map = choose_parameter(get_parameter(np, internal_np::point_map), PointMap()); const std::function& callback = choose_parameter(get_parameter(np, internal_np::callback), std::function()); 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 50dd11631ed..648edbbb953 100644 --- a/Point_set_processing_3/include/CGAL/pca_estimate_normals.h +++ b/Point_set_processing_3/include/CGAL/pca_estimate_normals.h @@ -155,12 +155,9 @@ pca_estimate_normals( const std::function& callback = choose_parameter(get_parameter(np, internal_np::callback), std::function()); - typedef typename Kernel::Point_3 Point; - // Input points types typedef typename PointRange::iterator iterator; typedef typename iterator::value_type value_type; - typedef typename boost::property_traits::value_type Vector; // types for K nearest neighbors search structure typedef Point_set_processing_3::internal::Neighbor_query Neighbor_query; diff --git a/Point_set_processing_3/include/CGAL/remove_outliers.h b/Point_set_processing_3/include/CGAL/remove_outliers.h index f49932d308a..47e35435d18 100644 --- a/Point_set_processing_3/include/CGAL/remove_outliers.h +++ b/Point_set_processing_3/include/CGAL/remove_outliers.h @@ -161,7 +161,6 @@ remove_outliers( // basic geometric types typedef typename PointRange::iterator iterator; typedef typename iterator::value_type value_type; - typedef typename Kernel::Point_3 Point; // actual type of input points typedef typename std::iterator_traits::value_type Enriched_point; 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 388a2a23ed1..91ef43575d3 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 @@ -7,7 +7,7 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s) : Shihao Wu, Clement Jamin, Pierre Alliez +// Author(s) : Shihao Wu, Cl:mement Jamin, Pierre Alliez #ifndef CGAL_wlop_simplify_and_regularize_point_set_H #define CGAL_wlop_simplify_and_regularize_point_set_H @@ -399,8 +399,6 @@ wlop_simplify_and_regularize_point_set( using parameters::get_parameter; // basic geometric types - typedef typename PointRange::iterator iterator; - typedef typename iterator::value_type value_type; typedef typename Point_set_processing_3::GetPointMap::type PointMap; typedef typename Point_set_processing_3::GetK::Kernel Kernel; @@ -466,7 +464,6 @@ wlop_simplify_and_regularize_point_set( #endif } - FT radius2 = radius * radius; CGAL_point_set_processing_precondition(radius > 0); // Initiate a KD-tree search for original points From de64512f5c08485b4b3c2f2d78c26232c86e68e1 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 18 Mar 2020 16:33:40 +0100 Subject: [PATCH 17/26] Fix mistake introduced in header --- .../include/CGAL/wlop_simplify_and_regularize_point_set.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 91ef43575d3..b631d225db3 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 @@ -7,7 +7,7 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s) : Shihao Wu, Cl:mement Jamin, Pierre Alliez +// Author(s) : Shihao Wu, Clement Jamin, Pierre Alliez #ifndef CGAL_wlop_simplify_and_regularize_point_set_H #define CGAL_wlop_simplify_and_regularize_point_set_H From 1f3f57ecc39bc21d901b3af4302688a45c650dec Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 19 Mar 2020 10:24:52 +0100 Subject: [PATCH 18/26] Fix poisson non-deterministic iterator filtering --- .../include/CGAL/Poisson_reconstruction_function.h | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/Poisson_surface_reconstruction_3/include/CGAL/Poisson_reconstruction_function.h b/Poisson_surface_reconstruction_3/include/CGAL/Poisson_reconstruction_function.h index bc434ba814a..b0f0f095e1f 100644 --- a/Poisson_surface_reconstruction_3/include/CGAL/Poisson_reconstruction_function.h +++ b/Poisson_surface_reconstruction_3/include/CGAL/Poisson_reconstruction_function.h @@ -106,13 +106,13 @@ struct Poisson_visitor { struct Poisson_skip_vertices { double ratio; - Random* m_random; - Poisson_skip_vertices(const double ratio = 0, Random* random = nullptr) - : ratio(ratio), m_random(random) {} + Poisson_skip_vertices(const double ratio = 0) + : ratio(ratio) {} template - bool operator()(Iterator) const { - return m_random->get_double() < ratio; + bool operator()(Iterator it) const { + // make the result deterministic for each iterator + return Random((std::size_t)(&*it)).get_double() < ratio; } }; @@ -417,9 +417,7 @@ public: typedef Filter_iterator Some_points_iterator; - //make it deterministic - Random random(0); - Poisson_skip_vertices skip(1.-approximation_ratio,&random); + Poisson_skip_vertices skip(1.-approximation_ratio); CGAL_TRACE_STREAM << "SPECIAL PASS that uses an approximation of the result (approximation ratio: " << approximation_ratio << ")" << std::endl; From 16625cda016b88269169a1618ee1fddad7411f3c Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 19 Mar 2020 10:38:58 +0100 Subject: [PATCH 19/26] Fix for_each and add a comment on what it does --- STL_Extension/include/CGAL/for_each.h | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/STL_Extension/include/CGAL/for_each.h b/STL_Extension/include/CGAL/for_each.h index e0ac595c753..9a320177344 100644 --- a/STL_Extension/include/CGAL/for_each.h +++ b/STL_Extension/include/CGAL/for_each.h @@ -20,6 +20,19 @@ #include #endif // CGAL_LINKED_WITH_TBB +/* + CGAL::for_each(Range, Function) does the following: + + - if Sequential_tag is used, apply Function to all elements of Range + - if Parallel_tag is used: + * static assert that TBB is available + * if Range has random access iterators, use a TBB parallel_for + loop to apply Function to all elements of Range + * if Range doesn't have random access iterators, first copy the + iterators in a vector and then use a TBB parallel_for loop to + apply Function to all elements of Range +*/ + namespace CGAL { namespace internal { @@ -33,7 +46,7 @@ void for_each (RangeRef range, const std::function::type>::reference)>& functor, const Sequential_tag&, - const IteratorCategory&) + IteratorCategory) { for (typename std::iterator_traits ::type>::reference r : range) @@ -53,7 +66,7 @@ void for_each (RangeRef range, const std::function::type>::reference)>& functor, const Parallel_tag&, - const IteratorCategory&) + IteratorCategory) { std::size_t range_size = std::distance (range.begin(), range.end()); @@ -82,7 +95,7 @@ void for_each (RangeRef range, const std::function::type>::reference)>& functor, const Parallel_tag&, - const std::random_access_iterator_tag&) + std::random_access_iterator_tag) { std::size_t range_size = std::distance (range.begin(), range.end()); From 0c23a6502879c503ea3a6bd5d94bb7b606973a52 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 19 Mar 2020 15:50:11 +0100 Subject: [PATCH 20/26] Add variant identity map read only without lvalue --- Property_map/include/CGAL/property_map.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Property_map/include/CGAL/property_map.h b/Property_map/include/CGAL/property_map.h index 159b18a64da..e86feb322ff 100644 --- a/Property_map/include/CGAL/property_map.h +++ b/Property_map/include/CGAL/property_map.h @@ -216,6 +216,22 @@ struct Identity_property_map /// @} }; + +/// \cond SKIP_IN_MANUAL +template +struct Identity_property_map_no_lvalue +{ + typedef T key_type; ///< typedef to `T` + typedef T value_type; ///< typedef to `T` + typedef T reference; ///< typedef to `T` + typedef boost::readable_property_map_tag category; ///< `boost::readable_property_map_tag` + + typedef Identity_property_map_no_lvalue Self; + + friend reference get(const Self&, const key_type& k) {return k;} +}; +/// \endcond + /// Free function to create a `Identity_property_map` property map. /// /// \relates Identity_property_map From 37a6a4360f3189d0b24cc6cb1527fe86a05e7125 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 19 Mar 2020 15:50:22 +0100 Subject: [PATCH 21/26] Fix warnings --- .../demo/Optimal_transportation_reconstruction_2/scene.h | 2 +- Spatial_searching/include/CGAL/Kd_tree_rectangle.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) 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 5693f0fbb30..2947db39636 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 @@ -407,7 +407,7 @@ public: Point_3_from_sample()), boost::make_transform_iterator (m_samples.end(), Point_3_from_sample())), - 3); + 3, CGAL::parameters::point_map (CGAL::Identity_property_map_no_lvalue())); std::cerr << "Average spacing = " << spacing << std::endl; } diff --git a/Spatial_searching/include/CGAL/Kd_tree_rectangle.h b/Spatial_searching/include/CGAL/Kd_tree_rectangle.h index 297c2203f6c..f0b9b68e48f 100644 --- a/Spatial_searching/include/CGAL/Kd_tree_rectangle.h +++ b/Spatial_searching/include/CGAL/Kd_tree_rectangle.h @@ -105,6 +105,7 @@ namespace CGAL { } Kd_tree_rectangle() + : max_span_coord_(-1) {} From c8aa0c8f573cb4542b48040d826dcdfa5df8fe1b Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 19 Mar 2020 15:54:53 +0100 Subject: [PATCH 22/26] Prevent from testing Parallel_tag if TBB is not here --- STL_Extension/test/STL_Extension/test_for_each.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/STL_Extension/test/STL_Extension/test_for_each.cpp b/STL_Extension/test/STL_Extension/test_for_each.cpp index b82ba01468c..d540297dead 100644 --- a/STL_Extension/test/STL_Extension/test_for_each.cpp +++ b/STL_Extension/test/STL_Extension/test_for_each.cpp @@ -15,7 +15,8 @@ int main() for (const int& i : vec) std::cerr << i << " "; std::cerr << std::endl; - + +#ifdef CGAL_LINKED_WITH_TBB std::cerr << "Testing parallel random access" << std::endl; CGAL::for_each (vec, [](int& i) { i *= 2; }); @@ -23,6 +24,7 @@ int main() for (const int& i : vec) std::cerr << i << " "; std::cerr << std::endl; +#endif std::cerr << "Testing sequential non-random access" << std::endl; CGAL::for_each @@ -32,6 +34,7 @@ int main() std::cerr << i << " "; std::cerr << std::endl; +#ifdef CGAL_LINKED_WITH_TBB std::cerr << "Testing parallel non-random access" << std::endl; CGAL::for_each (list, [](int& i) { i *= 2; }); @@ -39,6 +42,7 @@ int main() for (const int& i : list) std::cerr << i << " "; std::cerr << std::endl; +#endif return 0; } From 320876ab230479dc0c2db40b0383bfb6e064df01 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 23 Mar 2020 08:27:55 +0100 Subject: [PATCH 23/26] Replace exception by return value to stop for_each loops --- .../include/CGAL/bilateral_smooth_point_set.h | 8 +++- .../include/CGAL/compute_average_spacing.h | 4 +- .../include/CGAL/jet_estimate_normals.h | 4 +- .../include/CGAL/jet_smooth_point_set.h | 4 +- .../include/CGAL/pca_estimate_normals.h | 4 +- .../wlop_simplify_and_regularize_point_set.h | 4 +- STL_Extension/include/CGAL/for_each.h | 45 ++++++------------- 7 files changed, 34 insertions(+), 39 deletions(-) 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 d382ce2b792..4246460d55a 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 @@ -315,12 +315,14 @@ bilateral_smooth_point_set( [&](const typename Zip_iterator::reference& t) { if (callback_wrapper.interrupted()) - throw CGAL::internal::stop_for_each(); + return false; neighbor_query.get_iterators (get(point_map, get<0>(t)), k, neighbor_radius, std::back_inserter (get<1>(t))); ++ callback_wrapper.advancement(); + + return true; }); bool interrupted = callback_wrapper.interrupted(); @@ -362,7 +364,7 @@ bilateral_smooth_point_set( [&](const typename Zip_iterator_2::reference& t) { if (callback_wrapper.interrupted()) - throw CGAL::internal::stop_for_each(); + return false; get<2>(t) = bilateral_smooth_point_set_internal:: compute_denoise_projection @@ -373,6 +375,8 @@ bilateral_smooth_point_set( sharpness_angle); ++ callback_wrapper.advancement(); + + return true; }); callback_wrapper.join(); 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 192a7c537a1..3156d0ff469 100644 --- a/Point_set_processing_3/include/CGAL/compute_average_spacing.h +++ b/Point_set_processing_3/include/CGAL/compute_average_spacing.h @@ -192,11 +192,13 @@ compute_average_spacing( [&](const typename Zip_iterator::reference& t) { if (callback_wrapper.interrupted()) - throw CGAL::internal::stop_for_each(); + return false; get<1>(t) = CGAL::internal::compute_average_spacing (get(point_map, get<0>(t)), neighbor_query, k); ++ callback_wrapper.advancement(); + + return true; }); for (unsigned int i = 0; i < spacings.size (); ++ i) 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 e88405ca49d..9a021398c6a 100644 --- a/Point_set_processing_3/include/CGAL/jet_estimate_normals.h +++ b/Point_set_processing_3/include/CGAL/jet_estimate_normals.h @@ -201,12 +201,14 @@ jet_estimate_normals( [&](value_type& vt) { if (callback_wrapper.interrupted()) - throw internal::stop_for_each(); + return false; put (normal_map, vt, CGAL::internal::jet_estimate_normal (get(point_map, vt), neighbor_query, k, neighbor_radius, degree_fitting)); ++ callback_wrapper.advancement(); + + return true; }); callback_wrapper.join(); 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 0920b89ec30..6203dc76e0c 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 @@ -197,7 +197,7 @@ jet_smooth_point_set( [&](value_type vt) { if (callback_wrapper.interrupted()) - throw internal::stop_for_each(); + return false; put (point_map, vt, CGAL::internal::jet_smooth_point @@ -207,6 +207,8 @@ jet_smooth_point_set( degree_fitting, degree_monge)); ++ callback_wrapper.advancement(); + + return true; }); callback_wrapper.join(); 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 8bc566253de..845978f73d6 100644 --- a/Point_set_processing_3/include/CGAL/pca_estimate_normals.h +++ b/Point_set_processing_3/include/CGAL/pca_estimate_normals.h @@ -188,13 +188,15 @@ pca_estimate_normals( [&](value_type& vt) { if (callback_wrapper.interrupted()) - throw internal::stop_for_each(); + return false; put (normal_map, vt, CGAL::internal::pca_estimate_normal (get(point_map, vt), neighbor_query, k, neighbor_radius)); ++ callback_wrapper.advancement(); + + return true; }); callback_wrapper.join(); 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 49c246c56b0..0648df4e386 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 @@ -534,7 +534,7 @@ wlop_simplify_and_regularize_point_set( [&](const typename Zip_iterator::reference& t) { if (callback_wrapper.interrupted()) - throw internal::stop_for_each(); + return false; get<1>(t) = simplify_and_regularize_internal:: compute_update_sample_point( @@ -545,6 +545,8 @@ wlop_simplify_and_regularize_point_set( original_density_weights, sample_density_weights); ++ callback_wrapper.advancement(); + + return true; }); bool interrupted = callback_wrapper.interrupted(); diff --git a/STL_Extension/include/CGAL/for_each.h b/STL_Extension/include/CGAL/for_each.h index 9a320177344..e65c1ec9ade 100644 --- a/STL_Extension/include/CGAL/for_each.h +++ b/STL_Extension/include/CGAL/for_each.h @@ -31,39 +31,32 @@ * if Range doesn't have random access iterators, first copy the iterators in a vector and then use a TBB parallel_for loop to apply Function to all elements of Range + + The loop is interrupted if `functor` returns false (it carries on + until the end otherwise). */ namespace CGAL { namespace internal { -// To emulate either a "break" in sequential and a "return" in -// parallel, we use an interal throw/catch mechanism -struct stop_for_each : public std::exception { }; - template void for_each (RangeRef range, - const std::function::type>::reference)>& functor, const Sequential_tag&, IteratorCategory) { for (typename std::iterator_traits ::type>::reference r : range) - try - { - functor(r); - } - catch (const stop_for_each&) - { + if (!functor(r)) break; - } } #ifdef CGAL_LINKED_WITH_TBB template void for_each (RangeRef range, - const std::function::type>::reference)>& functor, const Parallel_tag&, IteratorCategory) @@ -79,20 +72,14 @@ void for_each (RangeRef range, [&](const tbb::blocked_range& r) { for (std::size_t i = r.begin(); i != r.end(); ++ i) - try - { - functor (*(iterators[i])); - } - catch (const stop_for_each&) - { - return; - } + if (!functor (*(iterators[i]))) + break; }); } template void for_each (RangeRef range, - const std::function::type>::reference)>& functor, const Parallel_tag&, std::random_access_iterator_tag) @@ -103,14 +90,8 @@ void for_each (RangeRef range, [&](const tbb::blocked_range& r) { for (std::size_t i = r.begin(); i != r.end(); ++ i) - try - { - functor (*(range.begin() + i)); - } - catch (const stop_for_each&) - { - return; - } + if (!functor (*(range.begin() + i))) + break; }); } #endif @@ -119,7 +100,7 @@ void for_each (RangeRef range, template void for_each (const Range& range, - const std::function::reference)>& functor) { #ifndef CGAL_LINKED_WITH_TBB @@ -135,7 +116,7 @@ void for_each (const Range& range, template void for_each (Range& range, - const std::function::reference)>& functor) { #ifndef CGAL_LINKED_WITH_TBB From 0b1d13e815ce91e45f5c9ee51076c4d39c55f1db Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 23 Mar 2020 09:49:17 +0100 Subject: [PATCH 24/26] Fix conversion warning --- Spatial_searching/include/CGAL/Search_traits_adapter.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Spatial_searching/include/CGAL/Search_traits_adapter.h b/Spatial_searching/include/CGAL/Search_traits_adapter.h index d7ac0549565..d1d0b3bc43f 100644 --- a/Spatial_searching/include/CGAL/Search_traits_adapter.h +++ b/Spatial_searching/include/CGAL/Search_traits_adapter.h @@ -182,7 +182,11 @@ public: } Dereference_type& - dereference() const { return const_cast((*point)[idx]); } + dereference() const + { + // Point::operator[] takes an int as parameter... + return const_cast((*point)[static_cast(idx)]); + } }; From 63c1090c04635fc6f8d1a24ddd049643e735ca71 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 23 Mar 2020 13:42:45 +0100 Subject: [PATCH 25/26] Upate test_for_each --- STL_Extension/test/STL_Extension/test_for_each.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/STL_Extension/test/STL_Extension/test_for_each.cpp b/STL_Extension/test/STL_Extension/test_for_each.cpp index d540297dead..cfb003a4aa3 100644 --- a/STL_Extension/test/STL_Extension/test_for_each.cpp +++ b/STL_Extension/test/STL_Extension/test_for_each.cpp @@ -10,7 +10,7 @@ int main() std::cerr << "Testing sequential random access" << std::endl; CGAL::for_each - (vec, [](int& i) { i *= 2; }); + (vec, [](int& i) -> bool { i *= 2; return true; }); for (const int& i : vec) std::cerr << i << " "; @@ -19,7 +19,7 @@ int main() #ifdef CGAL_LINKED_WITH_TBB std::cerr << "Testing parallel random access" << std::endl; CGAL::for_each - (vec, [](int& i) { i *= 2; }); + (vec, [](int& i) -> bool { i *= 2; return true; }); for (const int& i : vec) std::cerr << i << " "; @@ -28,7 +28,7 @@ int main() std::cerr << "Testing sequential non-random access" << std::endl; CGAL::for_each - (list, [](int& i) { i *= 2; }); + (list, [](int& i) -> bool { i *= 2; return true; }); for (const int& i : list) std::cerr << i << " "; @@ -37,7 +37,7 @@ int main() #ifdef CGAL_LINKED_WITH_TBB std::cerr << "Testing parallel non-random access" << std::endl; CGAL::for_each - (list, [](int& i) { i *= 2; }); + (list, [](int& i) -> bool { i *= 2; return true; }); for (const int& i : list) std::cerr << i << " "; From 929e1e4bcee50e09ec2b5860a6ceaaf7db2d21b4 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 24 Mar 2020 16:05:44 +0100 Subject: [PATCH 26/26] Fix "may be used uninitialized" warning --- Spatial_searching/include/CGAL/Kd_tree_rectangle.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Spatial_searching/include/CGAL/Kd_tree_rectangle.h b/Spatial_searching/include/CGAL/Kd_tree_rectangle.h index f0b9b68e48f..3cb7132be3e 100644 --- a/Spatial_searching/include/CGAL/Kd_tree_rectangle.h +++ b/Spatial_searching/include/CGAL/Kd_tree_rectangle.h @@ -139,6 +139,7 @@ namespace CGAL { template // was PointIter Kd_tree_rectangle(int, PointPointerIter begin, PointPointerIter end,const Construct_cartesian_const_iterator_d& construct_it) + : max_span_coord_(-1) { update_from_point_pointers(begin,end,construct_it); } @@ -289,7 +290,7 @@ namespace CGAL { } Kd_tree_rectangle() - : coords_(0), dim(0) + : coords_(0), dim(0), max_span_coord_(-1) { } @@ -324,7 +325,7 @@ namespace CGAL { template // was PointIter Kd_tree_rectangle(int d, PointPointerIter begin, PointPointerIter end,const Construct_cartesian_const_iterator_d& construct_it) - : coords_(new FT[2*d]), dim(d) + : coords_(new FT[2*d]), dim(d), max_span_coord_(-1) { update_from_point_pointers(begin,end,construct_it); }