From e4428e2dd760f40a5566f8616b4775e9f44a1eed Mon Sep 17 00:00:00 2001 From: Lingjie Zhu Date: Mon, 28 Aug 2017 17:16:49 +0800 Subject: [PATCH] cleanup seeding by target error drop --- .../vsa_autoinit_timing_benchmark.cpp | 9 +- .../include/CGAL/VSA_approximation.h | 194 ++++++++++++------ .../vsa_class_interface_test.cpp | 5 +- .../vsa_correctness_test.cpp | 3 +- 4 files changed, 143 insertions(+), 68 deletions(-) diff --git a/Surface_mesh_approximation/benchmark/Surface_mesh_approximation/vsa_autoinit_timing_benchmark.cpp b/Surface_mesh_approximation/benchmark/Surface_mesh_approximation/vsa_autoinit_timing_benchmark.cpp index d4cb9fc58d3..3ca90ca802d 100644 --- a/Surface_mesh_approximation/benchmark/Surface_mesh_approximation/vsa_autoinit_timing_benchmark.cpp +++ b/Surface_mesh_approximation/benchmark/Surface_mesh_approximation/vsa_autoinit_timing_benchmark.cpp @@ -28,7 +28,7 @@ typedef CGAL::Timer Timer; */ int main(int argc, char *argv[]) { - if (argc < 4) + if (argc < 5) return 1; Polyhedron mesh; @@ -52,13 +52,18 @@ int main(int argc, char *argv[]) if (init < 0 || init > 2) return 1; const FT tol(std::atof(argv[3])); + int iterations = std::atoi(argv[4]); std::cerr << "#init " << init << std::endl; std::cerr << "#tolerance " << tol << std::endl; + std::cerr << "#iterations " << iterations << std::endl; Timer t; std::cerr << "start initialization" << std::endl; t.start(); - l21_vsa.init_proxies_error(tol, static_cast(init)); + l21_vsa.seeding_error( + static_cast(init), + tol, + iterations); t.stop(); std::cerr << "initialization time " << t.time() << " sec." << std::endl; std::cerr << "#proxies " << l21_vsa.get_proxies_size() << std::endl; diff --git a/Surface_mesh_approximation/include/CGAL/VSA_approximation.h b/Surface_mesh_approximation/include/CGAL/VSA_approximation.h index 59e647b0188..902b2e1d6c9 100644 --- a/Surface_mesh_approximation/include/CGAL/VSA_approximation.h +++ b/Surface_mesh_approximation/include/CGAL/VSA_approximation.h @@ -334,12 +334,12 @@ public: /*! * @brief Incremental initialize proxies. * @param num_seed number of proxies seed - * @param inner_iteration number of iterations of coarse re-fitting + * @param num_iterations number of iterations of coarse re-fitting * before each incremental proxy insertion * @return number of proxies initialized */ std::size_t seed_incremental(const std::size_t num_seed, - const std::size_t inner_iteration = 5) { + const std::size_t num_iterations = 5) { proxies.clear(); if (num_faces(*m_pmesh) < num_seed) return 0; @@ -349,19 +349,19 @@ public: BOOST_FOREACH(face_descriptor f, faces(*m_pmesh)) fproxy_map[f] = 0; - insert_proxy_furthest(num_seed - 1, inner_iteration); + insert_proxy_furthest(num_seed - 1, num_iterations); return proxies.size(); } /*! * @brief Hierarchical initialize proxies. * @param num_seed number of proxies seed - * @param inner_iteration number of iterations of coarse re-fitting + * @param num_iterations number of iterations of coarse re-fitting * before each hierarchical proxy insertion * @return number of proxies initialized */ std::size_t seed_hierarchical(const std::size_t num_seed, - const std::size_t inner_iteration = 5) { + const std::size_t num_iterations = 5) { proxies.clear(); if (num_faces(*m_pmesh) < num_seed) return 0; @@ -373,7 +373,7 @@ public: proxies.push_back(fit_new_proxy(*(++fitr))); while (proxies.size() < num_seed) { - for (std::size_t i = 0; i < inner_iteration; ++i) { + for (std::size_t i = 0; i < num_iterations; ++i) { partition(); fit(); } @@ -388,66 +388,26 @@ public: } /*! - * @brief Initialize by targeted error drop. + * @brief Seeding by targeted error drop. + * @param method seeding method * @param target_drop targeted error drop to initial state, usually in range (0, 1) - * @param seeding_method select one of the seeding method: random, hierarchical, incremental + * @param num_iterations number of iterations of coarse re-fitting * @return number of proxies initialized */ - std::size_t init_proxies_error(const FT &target_drop, const Initialization &seeding_method) { - proxies.clear(); - // initialize a proxy and the proxy map to prepare for the insertion - proxies.push_back(fit_new_proxy(*(faces(*m_pmesh).first))); - BOOST_FOREACH(face_descriptor f, faces(*m_pmesh)) - fproxy_map[f] = 0; - const FT initial_err = compute_fitting_error(); - - // maximum allowed number of proxies - const std::size_t max_proxies = num_faces(*m_pmesh) / 3; - if (max_proxies < 1) - return 0; - - FT sum_err(0); - FT drop(0); - if (seeding_method == RandomInit) { - std::size_t target_px = 2; - do { - proxies.clear(); - seed_random(target_px); - for (std::size_t i = 0; i < 5; ++i) { - partition(); - fit(); - } - sum_err = compute_fitting_error(); - target_px *= 2; - drop = sum_err / initial_err; - } while(drop > target_drop && proxies.size() < max_proxies); + std::size_t seeding_error( + const Initialization method, + const FT target_drop, + const std::size_t num_iterations) { + switch (method) { + case RandomInit: + return seed_error_random(target_drop, num_iterations); + case IncrementalInit: + return seed_error_incremental(target_drop, num_iterations); + case HierarchicalInit: + return seed_error_hierarchical(target_drop, num_iterations); + default: + return 0; } - else if (seeding_method == IncrementalInit) { - do { - insert_proxy_furthest(); - for (std::size_t i = 0; i < 5; ++i) { - partition(); - fit(); - } - sum_err = compute_fitting_error(); - drop = sum_err / initial_err; - } while (drop > target_drop && proxies.size() < max_proxies); - } - else { - std::size_t target_px = 1; - do { - insert_proxy_hierarchical(target_px); - for (std::size_t i = 0; i < 5; ++i) { - partition(); - fit(); - } - sum_err = compute_fitting_error(); - target_px *= 2; - drop = sum_err / initial_err; - } while(drop > target_drop && proxies.size() < max_proxies); - } - - return proxies.size(); } /*! @@ -902,7 +862,115 @@ public: // private member functions private: - + /*! + * @brief Initialize by targeted error drop. + * @param target_drop targeted error drop to initial state, usually in range (0, 1) + * @param num_iterations number of iterations of coarse re-fitting + * @return number of proxies initialized + */ + std::size_t seed_error_random(const FT target_drop, + const std::size_t num_iterations) { + // maximum allowed number of proxies + const std::size_t max_proxies = num_faces(*m_pmesh) / 3; + if (max_proxies < 1) + return 0; + + // initialize a proxy and the proxy map to prepare for the insertion + proxies.clear(); + proxies.push_back(fit_new_proxy(*(faces(*m_pmesh).first))); + BOOST_FOREACH(face_descriptor f, faces(*m_pmesh)) + fproxy_map[f] = 0; + const FT initial_err = compute_fitting_error(); + + FT sum_err(0); + FT drop(0); + std::size_t target_px = 2; + do { + proxies.clear(); + seed_random(target_px); + for (std::size_t i = 0; i < num_iterations; ++i) { + partition(); + fit(); + } + sum_err = compute_fitting_error(); + target_px *= 2; + drop = sum_err / initial_err; + } while(drop > target_drop && proxies.size() < max_proxies); + + return proxies.size(); + } + + /*! + * @brief Initialize by targeted error drop. + * @param target_drop targeted error drop to initial state, usually in range (0, 1) + * @param num_iterations number of iterations of coarse re-fitting + * @return number of proxies initialized + */ + std::size_t seed_error_incremental(const FT target_drop, + const std::size_t num_iterations) { + // maximum allowed number of proxies + const std::size_t max_proxies = num_faces(*m_pmesh) / 3; + if (max_proxies < 1) + return 0; + + // initialize a proxy and the proxy map to prepare for the insertion + proxies.clear(); + proxies.push_back(fit_new_proxy(*(faces(*m_pmesh).first))); + BOOST_FOREACH(face_descriptor f, faces(*m_pmesh)) + fproxy_map[f] = 0; + const FT initial_err = compute_fitting_error(); + + FT sum_err(0); + FT drop(0); + do { + insert_proxy_furthest(); + for (std::size_t i = 0; i < num_iterations; ++i) { + partition(); + fit(); + } + sum_err = compute_fitting_error(); + drop = sum_err / initial_err; + } while (drop > target_drop && proxies.size() < max_proxies); + + return proxies.size(); + } + + /*! + * @brief Initialize by targeted error drop. + * @param target_drop targeted error drop to initial state, usually in range (0, 1) + * @param num_iterations number of iterations of coarse re-fitting + * @return number of proxies initialized + */ + std::size_t seed_error_hierarchical(const FT target_drop, + const std::size_t num_iterations) { + // maximum allowed number of proxies + const std::size_t max_proxies = num_faces(*m_pmesh) / 3; + if (max_proxies < 1) + return 0; + + // initialize a proxy and the proxy map to prepare for the insertion + proxies.clear(); + proxies.push_back(fit_new_proxy(*(faces(*m_pmesh).first))); + BOOST_FOREACH(face_descriptor f, faces(*m_pmesh)) + fproxy_map[f] = 0; + const FT initial_err = compute_fitting_error(); + + FT sum_err(0); + FT drop(0); + std::size_t target_px = 1; + do { + insert_proxy_hierarchical(target_px); + for (std::size_t i = 0; i < num_iterations; ++i) { + partition(); + fit(); + } + sum_err = compute_fitting_error(); + target_px *= 2; + drop = sum_err / initial_err; + } while(drop > target_drop && proxies.size() < max_proxies); + + return proxies.size(); + } /*! * @brief Inserts a proxy at the furthest facet of the region with the maximum fitting error. diff --git a/Surface_mesh_approximation/test/Surface_mesh_approximation/vsa_class_interface_test.cpp b/Surface_mesh_approximation/test/Surface_mesh_approximation/vsa_class_interface_test.cpp index 4cff3e70723..92ff1e3e4e6 100644 --- a/Surface_mesh_approximation/test/Surface_mesh_approximation/vsa_class_interface_test.cpp +++ b/Surface_mesh_approximation/test/Surface_mesh_approximation/vsa_class_interface_test.cpp @@ -119,11 +119,12 @@ int main() boundary = l2_approx.get_indexed_boundary_polygons(); const FT drop(0.001); + const std::size_t iterations = 5; std::cout << "rebuild and hierarchical init" << std::endl; l2_approx.rebuild(); if (l2_approx.get_proxies_size() != 0) return EXIT_FAILURE; - l2_approx.init_proxies_error(drop, L2VSA::HierarchicalInit); + l2_approx.seeding_error(L2VSA::HierarchicalInit, drop, iterations); for (std::size_t i = 0; i < 10; ++i) l2_approx.run_one_step(); std::cout << "#proxies " << l2_approx.get_proxies_size() << std::endl; @@ -132,7 +133,7 @@ int main() l2_approx.rebuild(); if (l2_approx.get_proxies_size() != 0) return EXIT_FAILURE; - l2_approx.init_proxies_error(drop, L2VSA::IncrementalInit); + l2_approx.seeding_error(L2VSA::IncrementalInit, drop, iterations); for (std::size_t i = 0; i < 10; ++i) l2_approx.run_one_step(); std::cout << "#proxies " << l2_approx.get_proxies_size() << std::endl; diff --git a/Surface_mesh_approximation/test/Surface_mesh_approximation/vsa_correctness_test.cpp b/Surface_mesh_approximation/test/Surface_mesh_approximation/vsa_correctness_test.cpp index 2b92c1e6484..b5a2f393c12 100644 --- a/Surface_mesh_approximation/test/Surface_mesh_approximation/vsa_correctness_test.cpp +++ b/Surface_mesh_approximation/test/Surface_mesh_approximation/vsa_correctness_test.cpp @@ -38,7 +38,8 @@ bool test_shape(const char *file_name, const std::size_t target_num_proxies) // should reach targeted number of proxies gradually const FT drop(1e-8); const std::size_t num_iterations = 20; - vsa_l21.init_proxies_error(drop, L21VSA::IncrementalInit); + const std::size_t inner_iterations = 10; + vsa_l21.seeding_error(L21VSA::IncrementalInit, drop, inner_iterations); for (std::size_t i = 0; i < num_iterations; ++i) vsa_l21.run_one_step(); if (vsa_l21.get_proxies_size() != target_num_proxies) {