#include #include #include #include #include #include #include "../../test/Shape_regularization/include/Saver.h" using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel; using FT = typename Kernel::FT; using Point_2 = typename Kernel::Point_2; using Segment_2 = typename Kernel::Segment_2; using Contour = std::vector; using Timer = CGAL::Real_timer; using Creator = CGAL::Creator_uniform_2; using Generator = CGAL::Random_points_in_square_2; using CD = CGAL::Shape_regularization::Contours::Longest_direction_2; void create_pattern( const std::size_t n, std::vector& contour, const FT d) { contour.clear(); contour.reserve(n); FT step = FT(1); FT x = FT(0), y = FT(0); for (std::size_t i = 0; i < n / 2; ++i) { x = step * i; if (i % 2 == 0) y = FT(0); else y = d; const Point_2 vertex = Point_2(x, y); contour.push_back(vertex); } contour.push_back(Point_2(x, FT(2))); for (std::size_t i = 0; i < n / 2 - 1; ++i) { x -= step; if (i % 2 == 0) y = FT(2) - d; else y = FT(2); const Point_2 vertex = Point_2(x, y); contour.push_back(vertex); } assert(contour.size() == n); // CGAL::Shape_regularization::Tests::Saver saver; // saver.export_eps_closed_contour(contour, "pattern_closed", 100.0); // saver.export_eps_open_contour(contour, "pattern_open", 100.0); // exit(EXIT_SUCCESS); } void create_pseudo_random( const std::size_t n, std::vector& contour) { const FT d = FT(0); create_pattern(n, contour, d); // Perturb edges. CGAL::Random rand; for (std::size_t i = 0; i < contour.size(); ++i) { const std::size_t ip = (i + 1) % contour.size(); Segment_2 edge(contour[i], contour[ip]); const FT angle = static_cast(rand.get_int(-15, 15)); CGAL::Shape_regularization::internal:: rotate_segment_2(angle, FT(0), edge); contour[i] = edge.source(); contour[ip] = edge.target(); } // CGAL::Shape_regularization::Tests::Saver saver; // saver.export_eps_closed_contour(contour, "pseudo_random_closed", 100.0); // saver.export_eps_open_contour(contour, "pseudo_random_open", 100.0); // exit(EXIT_SUCCESS); } void create_random( const std::size_t n, std::vector& contour) { contour.clear(); contour.reserve(n); const FT radius = 100.0; std::vector point_set; point_set.reserve(n); CGAL::copy_n_unique( Generator(radius), n, std::back_inserter(point_set)); CGAL::random_polygon_2( point_set.size(), std::back_inserter(contour), point_set.begin()); // The above algorithm does not guarantee to have exactly n vertices! // assert(contour.size() == n); // CGAL::Shape_regularization::Tests::Saver saver; // saver.export_eps_closed_contour(contour, "random_closed", 1.0); // saver.export_eps_open_contour(contour, "random_open", 1.0); // exit(EXIT_SUCCESS); } void benchmark_contours( const std::size_t n, const bool simple_output, const std::size_t num_iters) { Timer timer; std::vector contour, regularized; const FT d = FT(1) / FT(10); create_pattern(n, contour, d); // create_pseudo_random(n, contour); // create_random(n, contour); const FT max_offset_2 = FT(1) / FT(5); regularized.clear(); timer.start(); CD closed_directions(contour, true); timer.stop(); // const double longest_closed = timer.time(); timer.reset(); double closed_time = 0.0; for (std::size_t i = 0; i < num_iters; ++i) { regularized.clear(); timer.start(); CGAL::Shape_regularization::Contours::regularize_closed_contour( contour, closed_directions, std::back_inserter(regularized), CGAL::parameters::maximum_offset(max_offset_2)); timer.stop(); closed_time += timer.time(); timer.reset(); } closed_time /= static_cast(num_iters); regularized.clear(); timer.start(); CD open_directions(contour, false); timer.stop(); // const double longest_open = timer.time(); timer.reset(); double open_time = 0.0; for (std::size_t i = 0; i < num_iters; ++i) { regularized.clear(); timer.start(); CGAL::Shape_regularization::Contours::regularize_open_contour( contour, open_directions, std::back_inserter(regularized), CGAL::parameters::maximum_offset(max_offset_2)); timer.stop(); open_time += timer.time(); timer.reset(); } open_time /= static_cast(num_iters); std::cout.precision(10); if (simple_output) { std::cout << contour.size() << " " << closed_time << " " << open_time << std::endl; } else { std::cout << "benchmark_contours " << contour.size() << " (CPU time " << "closed/open): " << closed_time << "/" << open_time << " seconds" << std::endl; } } int main() { const std::size_t num_iters = 1; const std::vector ns = { 10, 100, 1000, 10000, 100000, 1000000, 10000000 }; for (const std::size_t n : ns) { benchmark_contours(n, false, num_iters); } // Dense results for plotting. // std::vector ns; // for (std::size_t i = 10; i <= 10000; i += 10) // ns.push_back(i); // for (const std::size_t n : ns) // benchmark_contours(n, true, num_iters); return EXIT_SUCCESS; }