Rewrote test_minkowski_sum

This commit is contained in:
Sebastian Morr 2014-08-11 17:19:32 +02:00
parent 427fd6e2db
commit 722ea5c9da
5 changed files with 208 additions and 268 deletions

View File

@ -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 <CGAL/Polygon_2.h>
#include <iostream>
#include <fstream>
/*!
* 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 <class Kernel>
bool read_polygon (const char *filename, CGAL::Polygon_2<Kernel>& pgn)
void read_polygon (const char *filename, CGAL::Polygon_2<Kernel>& 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 <class Kernel>
bool read_polygon_with_holes (const char *filename, CGAL::Polygon_with_holes_2<Kernel>& pgn)
{
std::ifstream ifile(filename);
ifile >> pgn;
// TODO: what can go wrong?
return true;
}
template <class Kernel>
bool write_polygon_with_holes (const char *filename, CGAL::Polygon_with_holes_2<Kernel>& pgn)
{
std::cout << filename << std::endl;
std::ofstream ofile(filename);
if (ofile.is_open()) {
ofile << pgn;
} else {
exit(1);
}
return true;
file >> pgn;
}
#endif

View File

@ -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

View File

@ -1,213 +0,0 @@
#include <CGAL/basic.h>
#ifdef CGAL_USE_GMP
// GMP is installed. Use the GMP rational number-type.
#include <CGAL/Gmpq.h>
typedef CGAL::Gmpq Rational;
#else
// GMP is not installed. Use CGAL's exact rational number-type.
#include <CGAL/MP_Float.h>
#include <CGAL/Quotient.h>
typedef CGAL::Quotient<CGAL::MP_Float> Rational;
#endif
#include <CGAL/Cartesian.h>
#include <CGAL/minkowski_sum_2.h>
#include <CGAL/Small_side_angle_bisector_decomposition_2.h>
#include <CGAL/Polygon_convex_decomposition_2.h>
#include <CGAL/Boolean_set_operations_2.h>
#include <CGAL/Timer.h>
#include "read_polygon.h"
#include <cstring>
#include <libgen.h>
#include <list>
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef Kernel::Point_2 Point_2;
typedef Kernel::Segment_2 Segment_2;
typedef CGAL::Polygon_2<Kernel> Polygon_2;
typedef CGAL::Polygon_with_holes_2<Kernel> 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<Polygon_with_holes_2> 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:"
<< "<compare|verify> <polygon#1> <polygon#2> [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<Kernel> ssab_decomp;
CGAL::Optimal_convex_decomposition_2<Kernel> opt_decomp;
CGAL::Hertel_Mehlhorn_convex_decomposition_2<Kernel> hm_approx_decomp;
CGAL::Greene_convex_decomposition_2<Kernel> 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);
}

View File

@ -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

View File

@ -0,0 +1,183 @@
#include <CGAL/basic.h>
#ifdef CGAL_USE_GMP
// GMP is installed. Use the GMP rational number-type.
#include <CGAL/Gmpq.h>
typedef CGAL::Gmpq Rational;
#else
// GMP is not installed. Use CGAL's exact rational number-type.
#include <CGAL/MP_Float.h>
#include <CGAL/Quotient.h>
typedef CGAL::Quotient<CGAL::MP_Float> Rational;
#endif
#include <CGAL/minkowski_sum_2.h>
#include <CGAL/Small_side_angle_bisector_decomposition_2.h>
#include <CGAL/Polygon_convex_decomposition_2.h>
#include <CGAL/Boolean_set_operations_2.h>
#include <CGAL/Timer.h>
#include "read_polygon.h"
#include <string.h>
#include <list>
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef CGAL::Polygon_2<Kernel> Polygon_2;
typedef CGAL::Polygon_with_holes_2<Kernel> Polygon_with_holes_2;
bool are_equal(const Polygon_with_holes_2& ph1,
const Polygon_with_holes_2& ph2)
{
std::list<Polygon_with_holes_2> 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<Kernel> decomp;
return minkowski_sum_2(p, q, decomp);
break;
}
case OPT_DECOMP:
{
CGAL::Optimal_convex_decomposition_2<Kernel> decomp;
return minkowski_sum_2(p, q, decomp);
break;
}
case HM_DECOMP:
{
CGAL::Hertel_Mehlhorn_convex_decomposition_2<Kernel> decomp;
return minkowski_sum_2(p, q, decomp);
break;
}
case GREENE_DECOMP:
{
CGAL::Greene_convex_decomposition_2<Kernel> 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<Strategy> 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<Strategy>::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;
}