diff --git a/Point_set_processing_3/examples/Point_set_processing_3/regularize_and_simplify_point_set_example.cpp b/Point_set_processing_3/examples/Point_set_processing_3/regularize_and_simplify_point_set_example.cpp index 07ae63d4782..52fcdaba1d0 100644 --- a/Point_set_processing_3/examples/Point_set_processing_3/regularize_and_simplify_point_set_example.cpp +++ b/Point_set_processing_3/examples/Point_set_processing_3/regularize_and_simplify_point_set_example.cpp @@ -31,8 +31,9 @@ int main(void) const unsigned int k = 500; // number of neighbors. const double neighbor_radius = 0.31; // neighbors size. const unsigned int iter_number = 30; // number of iterations. - const bool need_compute_density = true; // if needed to compute density to generate more rugularized result, - // especially when the density of input is uneven. + const bool need_compute_density = true; // if needed to compute density to + // generate more rugularized result, + // especially when the density of input is uneven. // Make room for sample points diff --git a/Point_set_processing_3/include/CGAL/regularize_and_simplify_point_set.h b/Point_set_processing_3/include/CGAL/regularize_and_simplify_point_set.h index 66cb9bed6f6..a54e5394a75 100644 --- a/Point_set_processing_3/include/CGAL/regularize_and_simplify_point_set.h +++ b/Point_set_processing_3/include/CGAL/regularize_and_simplify_point_set.h @@ -94,9 +94,10 @@ public: /// @return average spacing (scalar). template < typename Kernel, typename Tree > typename Kernel::FT -compute_max_spacing(const typename Kernel::Point_3& query, ///< 3D point whose spacing we want to compute - Tree& tree, ///< KD-tree - unsigned int k) ///< number of neighbors +compute_max_spacing + (const typename Kernel::Point_3& query, ///< 3D point + Tree& tree, ///< KD-tree + unsigned int k) ///< number of neighbors { // basic geometric types typedef typename Kernel::FT FT; @@ -122,7 +123,7 @@ compute_max_spacing(const typename Kernel::Point_3& query, ///< 3D point whose s Point p = search_iterator->first; double dist2 = CGAL::squared_distance(query,p); - max_distance = dist2 > max_distance ? dist2 : max_distance;// can be simplify, no need to compare.. + max_distance = (CGAL::max)(dist2, max_distance); ++search_iterator; } @@ -147,8 +148,8 @@ compute_average_term( Tree& tree, ///< KD-tree unsigned int& k, // nb neighbors const typename Kernel::FT radius, //accept neighborhood radius - const std::vector& density_weight_set //if user need density - //const std::vector& guess_knn_set//guess knn to spp + const std::vector& density_weight_set//if need density + ) { CGAL_point_set_processing_precondition( k > 1); @@ -253,7 +254,7 @@ compute_repulsion_term( Tree& tree, ///< KD-tree const unsigned int k, // nb neighbors const typename Kernel::FT radius, //accept neighborhood radius - const std::vector& density_weight_set //if user need density + const std::vector& density_weight_set //if need density ) { CGAL_point_set_processing_precondition( k > 1); @@ -515,19 +516,24 @@ guess_KNN_number_for_original_set( /// \ingroup PkgPointSetProcessing /// WLOP Algorithm: The simplification algorithm can produces a set of -/// denoised, outlier-free and evenly distributed particles over the original dense point cloud, -/// so as to improve the reliability of current normal orientation algorithm. -/// The core of the algorithm is a Weighted Locally Optimal projection operator with a density uniformization term. -/// More deatail please see: http://web.siat.ac.cn/~huihuang/WLOP/WLOP_page.html +/// denoised, outlier-free and evenly distributed particles over the original +/// dense point cloud, so as to improve the reliability of other algorithms. +/// +/// The core of the algorithm is a Weighted Locally Optimal projection operator +/// with a density uniformization term. +/// More deatail please see:http://web.siat.ac.cn/~huihuang/WLOP/WLOP_page.html /// /// @tparam ForwardIterator iterator over input points. -/// @tparam PointPMap is a model of `ReadablePropertyMap` with a value_type = Point_3. -/// It can be omitted if ForwardIterator value_type is convertible to Point_3. +/// @tparam PointPMap is a model of `ReadablePropertyMap` +/// with a value_type = Point_3. +/// It can be omitted if ForwardIterator value_type is convertible to +/// Point_3. /// @tparam Kernel Geometric traits class. -/// It can be omitted and deduced automatically from PointPMap value_type. +/// It can be omitted and deduced automatically from PointPMap value_type. /// /// @return iterator of the first point to downsampled points. + // This variant requires all parameters. template ForwardIterator @@ -538,8 +544,8 @@ regularize_and_simplify_point_set( double retain_percentage, ///< percentage of points to retain. unsigned int k, ///< number of neighbors. const unsigned int iter_number,///< number of iterations. - const bool need_compute_density, ///< if needed to compute density to generate more rugularized result, - /// especially when the density of input is uneven. + const bool need_compute_density, ///< if needed to compute density to + /// generate more rugularized result. const Kernel& /*kernel*/ ///< geometric traits. ) { @@ -562,14 +568,16 @@ regularize_and_simplify_point_set( // to fix: should have at least three distinct points // but this is costly to check CGAL_point_set_processing_precondition(first != beyond); - CGAL_point_set_processing_precondition(retain_percentage >= 0 && retain_percentage <= 100); + CGAL_point_set_processing_precondition(retain_percentage >= 0 + && retain_percentage <= 100); // Random shuffle std::random_shuffle (first, beyond); // Computes original(input) and sample points size std::size_t nb_points_original = std::distance(first, beyond); - std::size_t nb_points_sample = (std::size_t)(FT(nb_points_original) * (retain_percentage/100.0)); + std::size_t nb_points_sample = (std::size_t)(FT(nb_points_original) * + (retain_percentage/100.0)); std::size_t first_index_to_sample = nb_points_original - nb_points_sample; // The first point iter of original and sample points @@ -594,17 +602,22 @@ regularize_and_simplify_point_set( Point& p0 = get(point_pmap,it); original_treeElements.push_back(KdTreeElement(p0,i)); } - Tree original_tree(original_treeElements.begin(), original_treeElements.end()); + Tree original_tree(original_treeElements.begin(), + original_treeElements.end()); // Guess spacing - FT guess_neighbor_radius = (FT)(std::numeric_limits::max)(); // Or a better max number: (numeric_limits::max)()? + FT guess_neighbor_radius = (FT)(std::numeric_limits::max)(); for(it = first_original_point; it != beyond ; ++it) { - FT max_spacing = regularize_and_simplify_internal::compute_max_spacing(get(point_pmap,it),original_tree,k); - guess_neighbor_radius = max_spacing < guess_neighbor_radius ? max_spacing : guess_neighbor_radius; + FT max_spacing = regularize_and_simplify_internal:: + compute_max_spacing + (get(point_pmap,it), original_tree, k); + + guess_neighbor_radius = (CGAL::max)(max_spacing, guess_neighbor_radius); } guess_neighbor_radius *= 0.95; - std::cout << "Guess Neighborhood Radius:" << guess_neighbor_radius << std::endl; + std::cout << "Guess Neighborhood Radius:" + << guess_neighbor_radius << std::endl; // Compute original density weight for original points if user needed task_timer.start("Compute Density For Original"); @@ -613,7 +626,11 @@ regularize_and_simplify_point_set( { for (it = first_original_point; it != beyond ; ++it) { - FT density = regularize_and_simplify_internal::compute_density_weight_for_original_point(get(point_pmap,it), original_tree, k, guess_neighbor_radius * 0.3); + FT density = regularize_and_simplify_internal:: + compute_density_weight_for_original_point + (get(point_pmap,it), original_tree, k, + guess_neighbor_radius * 0.75); + original_density_weight_set.push_back(density); } } @@ -623,7 +640,10 @@ regularize_and_simplify_point_set( for (i=0 ; i < sample_points.size(); i++) { Point& p0 = sample_points[i]; - unsigned int guess_knn = regularize_and_simplify_internal::guess_KNN_number_for_original_set(p0, original_tree, k, guess_neighbor_radius); + unsigned int guess_knn = regularize_and_simplify_internal:: + guess_KNN_number_for_original_set + (p0, original_tree, k, guess_neighbor_radius); + guess_KNN_set.push_back(guess_knn); } @@ -639,8 +659,6 @@ regularize_and_simplify_point_set( std::cout << "Compute average term and repulsion term " << endl; // Initiate a KD-tree search for sample points - unsigned int k_for_sample = 30; // Or it can be conducted by the "guess_neighbor_radius" - for (i=0 ; i < sample_points.size(); i++) { Point& p0 = sample_points[i]; @@ -655,12 +673,16 @@ regularize_and_simplify_point_set( { for (i=0 ; i < sample_points.size(); i++) { - FT density = regularize_and_simplify_internal::compute_density_weight_for_sample_point(sample_points[i], sample_tree, k_for_sample, guess_neighbor_radius); + FT density = regularize_and_simplify_internal:: + compute_density_weight_for_sample_point + (sample_points[i], sample_tree, + guess_KNN_set[i], guess_neighbor_radius); + sample_density_weight_set.push_back(density); } } - // Compute average term and repulsion term for each sample points separately, + // Compute average term and repulsion term for each sample points , // then update each sample points std::vector average_set(nb_points_sample); std::vector repulsion_set(nb_points_sample); @@ -668,14 +690,20 @@ regularize_and_simplify_point_set( for (i = 0; i < sample_points.size(); i++) { Point& p = sample_points[i]; - average_set[i] = regularize_and_simplify_internal::compute_average_term(p, original_tree, guess_KNN_set[i], guess_neighbor_radius, original_density_weight_set); + average_set[i] = regularize_and_simplify_internal:: + compute_average_term + (p, original_tree, guess_KNN_set[i], + guess_neighbor_radius, original_density_weight_set); } //task_timer.start("Compute Repulsion Term"); for (i = 0; i < sample_points.size(); i++) { Point& p = sample_points[i]; - repulsion_set[i] = regularize_and_simplify_internal::compute_repulsion_term(p, sample_tree, k_for_sample, guess_neighbor_radius, sample_density_weight_set); + repulsion_set[i] = regularize_and_simplify_internal:: + compute_repulsion_term + (p, sample_tree, guess_KNN_set[i], + guess_neighbor_radius, sample_density_weight_set); } for (i = 0; i < sample_points.size(); i++) @@ -689,7 +717,7 @@ regularize_and_simplify_point_set( << (memory>>20) << " Mb allocated" << std::endl; task_timer.stop(); - std::cout << "iterate: " << iter_n + 1 << " "<< std::endl << std::endl;; + std::cout << "iterate: " << iter_n + 1 << " "<< std::endl << std::endl; } //Copy back modified sample points to original points for output @@ -714,8 +742,8 @@ regularize_and_simplify_point_set( double retain_percentage, ///< percentage of points to retain. unsigned int k, ///< number of neighbors. const unsigned int iter_number, ///< number of iterations. - const bool need_compute_density ///< if needed to compute density to generate more rugularized result, - /// especially when the density of input is uneven. + const bool need_compute_density ///< if needed to compute density to + /// generate more rugularized result ) { typedef typename boost::property_traits::value_type Point; @@ -741,8 +769,8 @@ regularize_and_simplify_point_set( double retain_percentage, ///< percentage of points to retain. unsigned int k, ///< number of neighbors. const unsigned int iter_number, ///< number of iterations. - const bool need_compute_density ///< if needed to compute density to generate more rugularized result, - /// especially when the density of input is uneven. + const bool need_compute_density ///< if needed to compute density to + /// generate more rugularized result ) { return regularize_and_simplify_point_set( diff --git a/Point_set_processing_3/include/CGAL/regularize_and_simplify_point_set_using_balltree.h b/Point_set_processing_3/include/CGAL/regularize_and_simplify_point_set_using_balltree.h index 67cfb3dbed3..54bf256f9ec 100644 --- a/Point_set_processing_3/include/CGAL/regularize_and_simplify_point_set_using_balltree.h +++ b/Point_set_processing_3/include/CGAL/regularize_and_simplify_point_set_using_balltree.h @@ -60,9 +60,10 @@ template typename Kernel::Vector_3 compute_average_term( const typename Kernel::Point_3& query, ///< 3D point to project - const std::vector > neighbor_original_points, + const std::vector > + neighbor_original_points,///< neighbor sample points const typename Kernel::FT radius, ///& density_weight_set ///< + const std::vector& density_weight_set ///< densities ) { CGAL_point_set_processing_precondition(radius > 0); @@ -113,9 +114,10 @@ template typename Kernel::Vector_3 compute_repulsion_term( const typename Kernel::Point_3& query, ///< 3D point to project - const std::vector > neighbor_sample_points, ///< neighbor sample points + const std::vector > + neighbor_sample_points, ///< neighbor sample points const typename Kernel::FT radius, ///& density_weight_set ///< if user need density + const std::vector& density_weight_set ///< densities ) { CGAL_point_set_processing_precondition(radius > 0); @@ -174,8 +176,8 @@ template typename Kernel::FT compute_density_weight_for_original_point( const typename Kernel::Point_3& query, ///< 3D point to project - const std::vector neighbor_original_points, ///< neighbor original points - const typename Kernel::FT radius + const std::vector neighbor_original_points, ///< + const typename Kernel::FT radius /// 0); @@ -214,7 +216,7 @@ template typename Kernel::FT compute_density_weight_for_sample_point( const typename Kernel::Point_3& query, ///< 3D point to project - const std::vector neighbor_sample_points, ///< neighbor sample points + const std::vector neighbor_sample_points, ///< const typename Kernel::FT radius ) { @@ -250,16 +252,20 @@ compute_density_weight_for_sample_point( /// \ingroup PkgPointSetProcessing /// WLOP Algorithm: The simplification algorithm can produces a set of -/// denoised, outlier-free and evenly distributed particles over the original dense point cloud, -/// so as to improve the reliability of current normal orientation algorithm. -/// The core of the algorithm is a Weighted Locally Optimal projection operator with a density uniformization term. -/// More deatail please see: http://web.siat.ac.cn/~huihuang/WLOP/WLOP_page.html +/// denoised, outlier-free and evenly distributed particles over the original +/// dense point cloud, so as to improve the reliability of other algorithms. +/// +/// The core of the algorithm is a Weighted Locally Optimal projection operator +/// with a density uniformization term. +/// More deatail please see:http://web.siat.ac.cn/~huihuang/WLOP/WLOP_page.html /// /// @tparam ForwardIterator iterator over input points. -/// @tparam PointPMap is a model of `ReadablePropertyMap` with a value_type = Point_3. -/// It can be omitted if ForwardIterator value_type is convertible to Point_3. +/// @tparam PointPMap is a model of `ReadablePropertyMap` +/// with a value_type = Point_3. +/// It can be omitted if ForwardIterator value_type is convertible to +/// Point_3. /// @tparam Kernel Geometric traits class. -/// It can be omitted and deduced automatically from PointPMap value_type. +/// It can be omitted and deduced automatically from PointPMap value_type. /// /// @return iterator of the first point to downsampled points. @@ -273,8 +279,8 @@ regularize_and_simplify_point_set_using_balltree( double retain_percentage, ///< percentage of points to retain. const typename Kernel::FT neighbor_radius, ///< size of neighbors. const unsigned int iter_number,///< number of iterations. - const bool need_compute_density, ///< if needed to compute density to generate more rugularized result, - /// especially when the density of input is uneven. + const bool need_compute_density, ///< if needed to compute density to + ///generate more rugularized result. const Kernel& /*kernel*/ ///< geometric traits. ) { @@ -291,14 +297,16 @@ regularize_and_simplify_point_set_using_balltree( // to fix: should have at least three distinct points // but this is costly to check CGAL_point_set_processing_precondition(first != beyond); - CGAL_point_set_processing_precondition(retain_percentage >= 0 && retain_percentage <= 100); + CGAL_point_set_processing_precondition(retain_percentage >= 0 && + retain_percentage <= 100); // Random shuffle std::random_shuffle (first, beyond); // Computes original(input) and sample points size std::size_t nb_points_original = std::distance(first, beyond); - std::size_t nb_points_sample = (std::size_t)(FT(nb_points_original) * (retain_percentage/100.0)); + std::size_t nb_points_sample = (std::size_t)(FT(nb_points_original) * + (retain_percentage/100.0)); std::size_t first_index_to_sample = nb_points_original - nb_points_sample; // The first point iter of original and sample points @@ -339,19 +347,23 @@ regularize_and_simplify_point_set_using_balltree( task_timer.start(); std::cout << "Initialization / Compute Density For Original" << std::endl; - rich_grid_internel::compute_ball_neighbors_one_self(original_rich_point_set, box, neighbor_radius); + rich_grid_internel::compute_ball_neighbors_one_self(original_rich_point_set + , box, neighbor_radius); for (it = first_original_point, i = 0; it != beyond ; ++it, i++) { std::vector original_neighbors; - std::vector& neighors_indexes = original_rich_point_set[i].neighbors; + std::vector& neighors_indexes = + original_rich_point_set[i].neighbors; for (unsigned int j = 0; j < neighors_indexes.size(); j++) { original_neighbors.push_back(original_points[neighors_indexes[j]]); } - FT density = regularize_and_simplify_internal::compute_density_weight_for_original_point(get(point_pmap,it), - original_neighbors, neighbor_radius); + FT density = regularize_and_simplify_internal:: + compute_density_weight_for_original_point( + get(point_pmap,it), + original_neighbors, neighbor_radius); original_density_weight_set.push_back(density); original_rich_point_set[i].neighbors.clear(); @@ -376,7 +388,8 @@ regularize_and_simplify_point_set_using_balltree( Rich_point rp(p0, i); sample_rich_point_set[i] = rp; } - rich_grid_internel::compute_ball_neighbors_one_self(sample_rich_point_set, box, neighbor_radius); + rich_grid_internel::compute_ball_neighbors_one_self(sample_rich_point_set, + box, neighbor_radius); // Compute sample density weight for sample points if user needed std::vector sample_density_weight_set; @@ -385,23 +398,28 @@ regularize_and_simplify_point_set_using_balltree( for (i=0 ; i < sample_points.size(); i++) { std::vector sample_neighbors; - std::vector& neighors_indexes = sample_rich_point_set[i].neighbors; + std::vector& neighors_indexes = + sample_rich_point_set[i].neighbors; + for (unsigned int j = 0; j < neighors_indexes.size(); j++) { sample_neighbors.push_back(sample_points[neighors_indexes[j]]); } - FT density = regularize_and_simplify_internal::compute_density_weight_for_sample_point - (sample_points[i], sample_neighbors, neighbor_radius); + FT density = regularize_and_simplify_internal:: + compute_density_weight_for_sample_point + (sample_points[i], sample_neighbors, neighbor_radius); + sample_density_weight_set.push_back(density); } } // Build Ball Tree For Sample-Original Neighbor - rich_grid_internel::compute_ball_neighbors_one_to_another(sample_rich_point_set, - original_rich_point_set, box, neighbor_radius); + rich_grid_internel::compute_ball_neighbors_one_to_another + (sample_rich_point_set, + original_rich_point_set, box, neighbor_radius); - // Compute average term and repulsion term for each sample points separately, + // Compute average term and repulsion term for each sample points, // then update each sample points std::vector average_set(nb_points_sample); std::vector repulsion_set(nb_points_sample); @@ -411,7 +429,8 @@ regularize_and_simplify_point_set_using_balltree( { Point& p = sample_points[i]; std::vector rich_original_neighbors; - std::vector& neighors_indexes = sample_rich_point_set[i].original_neighbors; + std::vector& neighors_indexes = + sample_rich_point_set[i].original_neighbors; if (neighors_indexes.empty()) { @@ -426,14 +445,18 @@ regularize_and_simplify_point_set_using_balltree( rich_original_neighbors.push_back(rp); } - average_set[i] = regularize_and_simplify_internal::compute_average_term(p, rich_original_neighbors, neighbor_radius, original_density_weight_set); + average_set[i] = regularize_and_simplify_internal:: + compute_average_term + (p, rich_original_neighbors, neighbor_radius, + original_density_weight_set); } //repulsion term for (i = 0; i < sample_points.size(); i++) { std::vector rich_sample_neighbors; - std::vector& neighors_indexes = sample_rich_point_set[i].neighbors; + std::vector& neighors_indexes = + sample_rich_point_set[i].neighbors; if (neighors_indexes.empty()) { @@ -449,7 +472,10 @@ regularize_and_simplify_point_set_using_balltree( } Point& p = sample_points[i]; - repulsion_set[i] = regularize_and_simplify_internal::compute_repulsion_term(p, rich_sample_neighbors, neighbor_radius, sample_density_weight_set); + repulsion_set[i] = regularize_and_simplify_internal:: + compute_repulsion_term + (p, rich_sample_neighbors, neighbor_radius, + sample_density_weight_set); } // update points positions according to average and repulsion term @@ -464,7 +490,7 @@ regularize_and_simplify_point_set_using_balltree( << (memory>>20) << " Mb allocated" << std::endl; task_timer.stop(); - std::cout << "iterate: " << iter_n + 1 << " "<< std::endl << std::endl;; + std::cout << "iterate: " << iter_n + 1 << " "<< std::endl << std::endl; } //Copy back modified sample points to original points for output @@ -489,8 +515,8 @@ regularize_and_simplify_point_set_using_balltree( double retain_percentage, ///< percentage of points to retain double neighbor_radius, ///< size of neighbors. const unsigned int iter_number, ///< number of iterations. - const bool need_compute_density ///< if needed to compute density to generate more rugularized result, - /// especially when the density of input is uneven. + const bool need_compute_density ///< if needed to compute density + /// to generate more rugularized result. ) { typedef typename boost::property_traits::value_type Point; @@ -516,8 +542,8 @@ regularize_and_simplify_point_set_using_balltree( double retain_percentage, ///< percentage of points to retain double neighbor_radius, ///< size of neighbors. const unsigned int iter_number, ///< number of iterations. - const bool need_compute_density ///< if needed to compute density to generate more rugularized result, - /// especially when the density of input is uneven. + const bool need_compute_density ///< if needed to compute density to generate + /// more rugularized result. ) { return regularize_and_simplify_point_set_using_balltree(