diff --git a/Minkowski_sum_2/test/Minkowski_sum_2/read_polygon.h b/Minkowski_sum_2/test/Minkowski_sum_2/read_polygon.h index b3410e6a51a..073c941e4fb 100644 --- a/Minkowski_sum_2/test/Minkowski_sum_2/read_polygon.h +++ b/Minkowski_sum_2/test/Minkowski_sum_2/read_polygon.h @@ -1,52 +1,22 @@ -#ifndef CGAL_READ_POLYGON_TEST_H -#define CGAL_READ_POLYGON_TEST_H +#ifndef CGAL_READ_POLYGON_H +#define CGAL_READ_POLYGON_H #include #include #include -/*! - * Read a polygon from an input file. - * \param filename The name of the input file. - * \param pgn Output: The polygon. - * \return Whether the polygon was successfuly read. - */ template -bool read_polygon (const char *filename, CGAL::Polygon_2& pgn) +void read_polygon (const char *filename, CGAL::Polygon_2& pgn) { - std::ifstream ifile(filename); - ifile >> pgn; + std::ifstream file(filename); - // Make sure the polygon is simple. - if (! pgn.is_simple()) + if (!file) { - std::cerr << "Error - the polygon is not simple." << std::endl; - return false; + std::cerr << "Failed to open " << filename << std::endl; + exit(1); } - return true; -} - -template -bool read_polygon_with_holes (const char *filename, CGAL::Polygon_with_holes_2& pgn) -{ - std::ifstream ifile(filename); - ifile >> pgn; - // TODO: what can go wrong? - return true; -} - -template -bool write_polygon_with_holes (const char *filename, CGAL::Polygon_with_holes_2& pgn) -{ - std::cout << filename << std::endl; - std::ofstream ofile(filename); - if (ofile.is_open()) { - ofile << pgn; - } else { - exit(1); - } - return true; + file >> pgn; } #endif diff --git a/Minkowski_sum_2/test/Minkowski_sum_2/test_Minkowski_sum.cmd b/Minkowski_sum_2/test/Minkowski_sum_2/test_Minkowski_sum.cmd deleted file mode 100644 index fa5c8ec3bba..00000000000 --- a/Minkowski_sum_2/test/Minkowski_sum_2/test_Minkowski_sum.cmd +++ /dev/null @@ -1,17 +0,0 @@ -compare ./data/rooms_part1.dat ./data/rooms_part2.dat -compare ./data/comb_part1.dat ./data/comb_part2.dat -compare ./data/knife_part1.dat ./data/knife_part2.dat -compare ./data/mchain_part1.dat ./data/mchain_part2.dat -compare ./data/random_part1.dat ./data/random_part2.dat -compare ./data/wheels_part1.dat ./data/wheels_part2.dat -compare ./data/r35975_part1.dat ./data/r35975_part2.dat -compare ./data/r38305_part1.dat ./data/r38305_part2.dat -compare ./data/D.dat ./data/E.dat -compare ./data/F.dat ./data/G.dat -compare ./data/F.dat ./data/E.dat -compare ./data/F.dat ./data/D.dat -compare ./data/F.dat ./data/A.dat -compare ./data/A.dat ./data/G.dat -compare ./data/B.dat ./data/G.dat -verify ./data/dangling_edge_part1.dat ./data/dangling_edge_part2.dat ./data/dangling_edge_result.dat -verify ./data/isolated_vertex_part1.dat ./data/isolated_vertex_part2.dat ./data/isolated_vertex_result.dat diff --git a/Minkowski_sum_2/test/Minkowski_sum_2/test_Minkowski_sum.cpp b/Minkowski_sum_2/test/Minkowski_sum_2/test_Minkowski_sum.cpp deleted file mode 100644 index 6cc34ffafb5..00000000000 --- a/Minkowski_sum_2/test/Minkowski_sum_2/test_Minkowski_sum.cpp +++ /dev/null @@ -1,213 +0,0 @@ -#include - -#ifdef CGAL_USE_GMP - // GMP is installed. Use the GMP rational number-type. - #include - typedef CGAL::Gmpq Rational; -#else - // GMP is not installed. Use CGAL's exact rational number-type. - #include - #include - typedef CGAL::Quotient Rational; -#endif - -#include -#include -#include -#include -#include -#include -#include "read_polygon.h" -#include -#include - -#include - -typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel; - -typedef Kernel::Point_2 Point_2; -typedef Kernel::Segment_2 Segment_2; -typedef CGAL::Polygon_2 Polygon_2; -typedef CGAL::Polygon_with_holes_2 Polygon_with_holes_2; - -/*! Check if two polygons with holes are the same. */ -bool are_equal (const Polygon_with_holes_2& ph1, - const Polygon_with_holes_2& ph2) -{ - std::list sym_diff; - - CGAL::symmetric_difference (ph1, ph2, - std::back_inserter(sym_diff)); - - return (sym_diff.empty()); -} - -/*! The main program. */ -int main (int argc, char **argv) -{ - // Read the input file. Because of the structure of the *.cmd file - // (which is concatenated to the command line) we need to get all the - // inputs in one command line. This is the reason we read triplets/quadruplets of - // arguments. Each triplet/quadruplet is one input for the program. - if (argc < 3) - { - std::cerr << "Usage: " << argv[0] << ". The input are triplets/quadruplets of:" - << " [polygon#3]" - << std::endl; - return (1); - } - - int i = 1; - while (i < argc) - { - bool verify = strcmp(argv[i], "verify") == 0; - - // Read the polygons from the input files. - Polygon_2 pgn1, pgn2; - Polygon_with_holes_2 result; - CGAL::Timer timer; - - if (! read_polygon (argv[i+1], pgn1)) - { - std::cerr << "Failed to read: <" << argv[i+1] << ">." << std::endl; - return (1); - } - - if (! read_polygon (argv[i+2], pgn2)) - { - std::cerr << "Failed to read: <" << argv[i+2] << ">." << std::endl; - return (1); - } - - if (verify) - { - if (! read_polygon_with_holes (argv[i+3], result)) - { - std::cerr << "Failed to read: <" << argv[i+3] << ">." << std::endl; - return (1); - } - } - - std::cout << "Testing " << argv[i+1] << " and " << argv[i+2] << std::endl; - - Polygon_with_holes_2 sum_conv_new; - - std::cout << "Using the reduced convolution method ... "; - timer.reset(); - timer.start(); - sum_conv_new = minkowski_sum_by_reduced_convolution_2 (pgn1, pgn2); - timer.stop(); - std::cout << "Done (" << timer.time() << " s)" << std::endl; - - if (verify) - { - if (are_equal (result, sum_conv_new)) - { - std::cout << "OK." << std::endl; - } - else - { - std::cout << "ERROR (different result)." << std::endl; - return 1; - } - } - else - { - result = sum_conv_new; - } - - Polygon_with_holes_2 sum_conv; - std::cout << "Using the convolution method ... "; - timer.reset(); - timer.start(); - sum_conv = minkowski_sum_by_full_convolution_2 (pgn1, pgn2); - timer.stop(); - if (are_equal (result, sum_conv)) - { - std::cout << "OK (" << timer.time() << " s)" << std::endl; - } - else - { - std::cout << "ERROR (different result)." << std::endl; - return 1; - } - - // Define auxiliary polygon-decomposition objects. - CGAL::Small_side_angle_bisector_decomposition_2 ssab_decomp; - CGAL::Optimal_convex_decomposition_2 opt_decomp; - CGAL::Hertel_Mehlhorn_convex_decomposition_2 hm_approx_decomp; - CGAL::Greene_convex_decomposition_2 greene_decomp; - Polygon_with_holes_2 sum_decomp; - - std::cout << "Using the small-side angle-bisector decomposition ... "; - timer.reset(); - timer.start(); - sum_decomp = minkowski_sum_2 (pgn1, pgn2, ssab_decomp); - timer.stop(); - if (are_equal (result, sum_decomp)) - { - std::cout << "OK (" << timer.time() << " s)" << std::endl; - } - else - { - std::cout << "ERROR (different result)." << std::endl; - return 1; - } - - std::cout << "Using the optimal convex decomposition ... "; - timer.reset(); - timer.start(); - sum_decomp = minkowski_sum_2 (pgn1, pgn2, opt_decomp); - timer.stop(); - if (are_equal (result, sum_decomp)) - { - std::cout << "OK (" << timer.time() << " s)" << std::endl; - } - else - { - std::cout << "ERROR (different result)." << std::endl; - return 1; - } - - std::cout << "Using the Hertel--Mehlhorn decomposition ... "; - timer.reset(); - timer.start(); - sum_decomp = minkowski_sum_2 (pgn1, pgn2, hm_approx_decomp); - timer.stop(); - if (are_equal (result, sum_decomp)) - { - std::cout << "OK (" << timer.time() << " s)" << std::endl; - } - else - { - std::cout << "ERROR (different result)." << std::endl; - return 1; - } - - std::cout << "Using the Greene decomposition ... "; - timer.reset(); - timer.start(); - sum_decomp = minkowski_sum_2 (pgn1, pgn2, greene_decomp); - timer.stop(); - if (are_equal (result, sum_decomp)) - { - std::cout << "OK (" << timer.time() << " s)" << std::endl; - } - else - { - std::cout << "ERROR (different result)." << std::endl; - return 1; - } - - write_polygon_with_holes((std::string("./results/") + basename(argv[i+1]) + "-and-" + basename(argv[i+2]) + ".dat").c_str(), sum_conv_new); - - if (verify) - { - i += 4; - } - else - i += 3; - } - - return (0); -} diff --git a/Minkowski_sum_2/test/Minkowski_sum_2/test_minkowski_sum.cmd b/Minkowski_sum_2/test/Minkowski_sum_2/test_minkowski_sum.cmd new file mode 100644 index 00000000000..dc566b9306e --- /dev/null +++ b/Minkowski_sum_2/test/Minkowski_sum_2/test_minkowski_sum.cmd @@ -0,0 +1,17 @@ +rfsohg +data/comb_part1.dat data/comb_part2.dat +data/knife_part1.dat data/knife_part2.dat +data/mchain_part1.dat data/mchain_part2.dat +data/random_part1.dat data/random_part2.dat +data/wheels_part1.dat data/wheels_part2.dat +data/r35975_part1.dat data/r35975_part2.dat +data/r38305_part1.dat data/r38305_part2.dat +data/D.dat data/E.dat +data/F.dat data/G.dat +data/F.dat data/E.dat +data/F.dat data/D.dat +data/F.dat data/A.dat +data/A.dat data/G.dat +data/B.dat data/G.dat +data/dangling_edge_part1.dat data/dangling_edge_part2.dat +data/isolated_vertex_part1.dat data/isolated_vertex_part2.dat diff --git a/Minkowski_sum_2/test/Minkowski_sum_2/test_minkowski_sum.cpp b/Minkowski_sum_2/test/Minkowski_sum_2/test_minkowski_sum.cpp new file mode 100644 index 00000000000..40d1e1ecb6c --- /dev/null +++ b/Minkowski_sum_2/test/Minkowski_sum_2/test_minkowski_sum.cpp @@ -0,0 +1,183 @@ +#include + +#ifdef CGAL_USE_GMP + // GMP is installed. Use the GMP rational number-type. + #include + typedef CGAL::Gmpq Rational; +#else + // GMP is not installed. Use CGAL's exact rational number-type. + #include + #include + typedef CGAL::Quotient Rational; +#endif + +#include +#include +#include +#include +#include + +#include "read_polygon.h" + +#include +#include + +typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel; +typedef CGAL::Polygon_2 Polygon_2; +typedef CGAL::Polygon_with_holes_2 Polygon_with_holes_2; + +bool are_equal(const Polygon_with_holes_2& ph1, + const Polygon_with_holes_2& ph2) +{ + std::list sym_diff; + CGAL::symmetric_difference (ph1, ph2, std::back_inserter(sym_diff)); + return sym_diff.empty(); +} + +typedef enum +{ + REDUCED_CONVOLUTION, + FULL_CONVOLUTION, + SSAB_DECOMP, + OPT_DECOMP, + HM_DECOMP, + GREENE_DECOMP +} Strategy; + +static const char *strategy_names[] = +{ + "reduced convolution", + "full convolution", + "small-side angle-bisector decomposition", + "optimal convex decomposition", + "Hertel-Mehlhorn decomposition", + "Greene decomosition" +}; + +Polygon_with_holes_2 compute_minkowski_sum_2(Polygon_2 &p, Polygon_2 &q, Strategy strategy) +{ + switch (strategy) + { + case REDUCED_CONVOLUTION: + { + return minkowski_sum_by_reduced_convolution_2 (p, q); + break; + } + case FULL_CONVOLUTION: + { + return minkowski_sum_by_full_convolution_2 (p, q); + break; + } + case SSAB_DECOMP: + { + CGAL::Small_side_angle_bisector_decomposition_2 decomp; + return minkowski_sum_2(p, q, decomp); + break; + } + case OPT_DECOMP: + { + CGAL::Optimal_convex_decomposition_2 decomp; + return minkowski_sum_2(p, q, decomp); + break; + } + case HM_DECOMP: + { + CGAL::Hertel_Mehlhorn_convex_decomposition_2 decomp; + return minkowski_sum_2(p, q, decomp); + break; + } + case GREENE_DECOMP: + { + CGAL::Greene_convex_decomposition_2 decomp; + return minkowski_sum_2(p, q, decomp); + break; + } + } +} + +int main (int argc, char **argv) +{ + if (argc < 2) + { + std::cerr << "Usage: " << argv[0] << " [method flag] [polygon files]..." << std::endl; + std::cerr << "For the method flag, use a subset of the letters 'rfsohg'." << std::endl; + std::cerr << "The program will compute the Minkowski sum of the first and second polygon, of the third and fourth, and so on." << std::endl; + return 1; + } + + Polygon_2 p, q; + CGAL::Timer timer; + + std::list strategies; + for (int i = 0; i < strlen(argv[1]); i++) + { + switch (argv[1][i]) { + case 'r': + strategies.push_back(REDUCED_CONVOLUTION); + break; + case 'f': + strategies.push_back(FULL_CONVOLUTION); + break; + case 's': + strategies.push_back(SSAB_DECOMP); + break; + case 'o': + strategies.push_back(OPT_DECOMP); + break; + case 'h': + strategies.push_back(HM_DECOMP); + break; + case 'g': + strategies.push_back(GREENE_DECOMP); + break; + default: + std::cerr << "Unknown flag '" << argv[1][i] << "'" << std::endl; + return 1; + } + } + + int i = 2; + while (i+1 < argc) + { + std::cout << "Testing " << argv[i] << " + " << argv[i+1] << std::endl; + read_polygon (argv[i], p); + read_polygon (argv[i+1], q); + + bool compare = false; + Polygon_with_holes_2 reference; + + for (std::list::iterator it = strategies.begin(); it != strategies.end(); it++) + { + std::cout << "Using " << strategy_names[*it] << ": "; + timer.reset(); + timer.start(); + Polygon_with_holes_2 result = compute_minkowski_sum_2(p, q, *it); + timer.stop(); + std::cout << timer.time() << " s " << std::flush; + + if (compare) + { + if (are_equal(reference, result)) + { + std::cout << "(OK)"; + } + else + { + std::cout << "(ERROR: different result)"; + return 1; + } + } + else + { + compare = true; + reference = result; + } + std::cout << std::endl; + } + + std::cout << std::endl; + i += 2; + } + + return 0; +}