Completed the test suite + some bug fixes.

This commit is contained in:
Ron Wein 2006-08-06 06:20:56 +00:00
parent ef0f5d103f
commit acd8037f11
10 changed files with 686 additions and 135 deletions

2
.gitattributes vendored
View File

@ -1219,6 +1219,8 @@ Minkowski_sum_2/test/Minkowski_sum_2/data/mchain_part1.dat -text
Minkowski_sum_2/test/Minkowski_sum_2/data/mchain_part2.dat -text
Minkowski_sum_2/test/Minkowski_sum_2/data/random_part1.dat -text
Minkowski_sum_2/test/Minkowski_sum_2/data/random_part2.dat -text
Minkowski_sum_2/test/Minkowski_sum_2/data/rooms_part1.dat -text
Minkowski_sum_2/test/Minkowski_sum_2/data/rooms_part2.dat -text
Minkowski_sum_2/test/Minkowski_sum_2/data/wheels_part1.dat -text
Minkowski_sum_2/test/Minkowski_sum_2/data/wheels_part2.dat -text
Modifier/doc_tex/Modifier/idraw/modifier.eps -text svneol=unset#application/postscript

View File

@ -115,6 +115,9 @@ protected:
// Traverse the polygon vertices and edges and construct the arcs that
// constitute the single convolution cycle.
Alg_kernel alg_ker;
typename Alg_kernel::Equal_2 f_equal = alg_ker.equal_2_object();
Nt_traits nt_traits;
const Rational sqr_r = CGAL::square (r);
const Algebraic alg_r = nt_traits.convert (r);
@ -127,7 +130,6 @@ protected:
Alg_point_2 first_op; // The first offset point.
Algebraic a, b, c;
unsigned int curve_index = 0;
Traits_2 traits;
std::list<Object> xobjs;
@ -187,28 +189,31 @@ protected:
}
else
{
// Connect op2 (from the previous iteration) and op1 with a circular
// arc, whose supporting circle is (x1, x2) with radius r.
arc = Curve_2 (Rat_circle_2 (*curr, sqr_r),
CGAL::COUNTERCLOCKWISE,
op2, op1);
// Subdivide the arc into x-monotone subarcs and append them to the
// convolution cycle.
xobjs.clear();
f_make_x_monotone (arc, std::back_inserter(xobjs));
for (xobj_it = xobjs.begin(); xobj_it != xobjs.end(); ++xobj_it)
if (! f_equal (op2, op1))
{
assign_success = CGAL::assign (xarc, *xobj_it);
CGAL_assertion (assign_success);
// Connect op2 (from the previous iteration) and op1 with a circular
// arc, whose supporting circle is (x1, x2) with radius r.
arc = Curve_2 (Rat_circle_2 (*curr, sqr_r),
CGAL::COUNTERCLOCKWISE,
op2, op1);
// Subdivide the arc into x-monotone subarcs and append them to the
// convolution cycle.
xobjs.clear();
f_make_x_monotone (arc, std::back_inserter(xobjs));
for (xobj_it = xobjs.begin(); xobj_it != xobjs.end(); ++xobj_it)
{
assign_success = CGAL::assign (xarc, *xobj_it);
CGAL_assertion (assign_success);
*oi = Labeled_curve_2 (xarc,
X_curve_label (xarc.is_directed_right(),
cycle_id,
curve_index));
++oi;
curve_index++;
*oi = Labeled_curve_2 (xarc,
X_curve_label (xarc.is_directed_right(),
cycle_id,
curve_index));
++oi;
curve_index++;
}
}
}
@ -240,35 +245,38 @@ protected:
} while (curr != first);
// Close the convolution cycle by creating the final circular arc,
// centered at the first vertex.
arc = Curve_2 (Rat_circle_2 (*first, sqr_r),
CGAL::COUNTERCLOCKWISE,
op2, first_op);
// Subdivide the arc into x-monotone subarcs and append them to the
// convolution cycle.
bool is_last;
xobjs.clear();
f_make_x_monotone (arc, std::back_inserter(xobjs));
xobj_it = xobjs.begin();
while (xobj_it != xobjs.end())
if (! f_equal (op2, first_op))
{
assign_success = CGAL::assign (xarc, *xobj_it);
CGAL_assertion (assign_success);
// Close the convolution cycle by creating the final circular arc,
// centered at the first vertex.
arc = Curve_2 (Rat_circle_2 (*first, sqr_r),
CGAL::COUNTERCLOCKWISE,
op2, first_op);
++xobj_it;
is_last = (xobj_it == xobjs.end());
*oi = Labeled_curve_2 (xarc,
X_curve_label (xarc.is_directed_right(),
cycle_id,
curve_index,
is_last));
++oi;
curve_index++;
// Subdivide the arc into x-monotone subarcs and append them to the
// convolution cycle.
bool is_last;
xobjs.clear();
f_make_x_monotone (arc, std::back_inserter(xobjs));
xobj_it = xobjs.begin();
while (xobj_it != xobjs.end())
{
assign_success = CGAL::assign (xarc, *xobj_it);
CGAL_assertion (assign_success);
++xobj_it;
is_last = (xobj_it == xobjs.end());
*oi = Labeled_curve_2 (xarc,
X_curve_label (xarc.is_directed_right(),
cycle_id,
curve_index,
is_last));
++oi;
curve_index++;
}
}
return (oi);

View File

@ -95,10 +95,9 @@ public:
do
{
out_bound.push_back (circ->source()->point());
++circ;
--circ;
} while (circ != first);
++hole_it;
// Locate the holes in the union: Go over all arrangement faces.
@ -116,10 +115,10 @@ public:
do
{
pgn_hole.push_back (circ->source()->point());
++circ;
--circ;
} while (circ != first);
// Insert it to the containers of holes in the Minkowski sum.
*holes = pgn_hole;
++holes;

View File

@ -0,0 +1,141 @@
#! /bin/bash
# This is a script for the CGAL test suite. Such a script must obey
# the following rules:
#
# - the name of the script is cgal_test
# - for every target two one line messages are written to the file 'error.txt'
# the first one indicates if the compilation was successful
# the second one indicates if the execution was successful
# if one of the two was not successful, the line should start with 'ERROR:'
# - running the script should not require any user interaction
# - the script should clean up object files and executables
ERRORFILE=error.txt
#---------------------------------------------------------------------#
# compile_and_run <target>
#---------------------------------------------------------------------#
compile_test()
{
local name=$1;
echo "Compiling $name ... "
if eval 'make CGAL_MAKEFILE=$CGAL_MAKEFILE $name'; then
echo " succesful compilation of $name" >> $ERRORFILE;
res=1;
else
echo " ERROR: compilation of $name" >> $ERRORFILE;
res=0;
fi
}
run_test_Minkowski_sum()
{
local datafile=$1;
local flags=$2;
basedata=`basename "$datafile"`
OUTPUTFILE=ProgramOutput.$basedata.test_Minkowski_sum.$PLATFORM
first_file="$datafile"_part1.dat
second_file="$datafile"_part2.dat
rm -f $OUTPUTFILE
COMMAND="./test_Minkowski_sum"
echo "Executing $COMMAND $first_file $second_file $flags ... "
echo
if eval $COMMAND $first_file $second_file $flags > $OUTPUTFILE 2>&1 ; then
echo " succesful execution of test_Minkowski_sum $datafile" >> $ERRORFILE
else
echo " ERROR: execution of test_Minkowski_sum $datafile" >> $ERRORFILE
fi
}
clean_tests()
{
eval "make CGAL_MAKEFILE=$CGAL_MAKEFILE clean > /dev/null 2>&1 "
}
#---------------------------------------------------------------------#
# Minkowski sum test
#---------------------------------------------------------------------#
Minkowski_sum_tests()
{
compile_test test_Minkowski_sum
if [ ${res} -eq 0 ] ; then
echo " ERROR: not executed test_Minkowski_sum" >> $ERRORFILE
else
run_test_Minkowski_sum data/rooms -sohg
run_test_Minkowski_sum data/comb -sohg
run_test_Minkowski_sum data/fork -soh
run_test_Minkowski_sum data/knife -so
run_test_Minkowski_sum data/mchain -sh
run_test_Minkowski_sum data/random -sg
run_test_Minkowski_sum data/wheels -hg
fi
clean_tests
}
#---------------------------------------------------------------------#
# Offset tests
#---------------------------------------------------------------------#
run_offset_test()
{
local program=$1;
local datafile=$2;
local radius=$3;
local flags=$4;
basedata=`basename "$datafile"`
OUTPUTFILE=ProgramOutput.$basedata.$program.$PLATFORM
rm -f $OUTPUTFILE
COMMAND="./$program"
echo "Executing $COMMAND $datafile $radius $flags ... "
echo
if eval $COMMAND $datafile $radius $flags > $OUTPUTFILE 2>&1 ; then
echo " succesful execution of $program $datafile" >> $ERRORFILE
else
echo " ERROR: execution of $program $datafile" >> $ERRORFILE
fi
}
offset_tests()
{
compile_test test_exact_offset
if [ ${res} -eq 0 ] ; then
echo " ERROR: not executed test_exact_offset" >> $ERRORFILE
else
run_offset_test test_exact_offset data/random_part1.dat 5/1 -sohg
run_offset_test test_exact_offset data/comb_part1.dat 1/1 -sohg
run_offset_test test_exact_offset data/wheels_part1.dat 100000/1 -sohg
fi
compile_test test_approx_offset
if [ ${res} -eq 0 ] ; then
echo " ERROR: not executed test_approx_offset" >> $ERRORFILE
else
run_offset_test test_approx_offset data/rooms_part1.dat 3/1 -sohg
run_offset_test test_approx_offset data/wheels_part1.dat 100000/1 -sohg
fi
clean_tests
}
#---------------------------------------------------------------------#
# remove the previous error file
#---------------------------------------------------------------------#
rm -f $ERRORFILE
touch $ERRORFILE
#---------------------------------------------------------------------#
# compile and run the tests
#---------------------------------------------------------------------#
Minkowski_sum_tests
offset_tests

View File

@ -0,0 +1,27 @@
26
0/1 8/1
0/1 0/1
17/1 0/1
17/1 18/1
0/1 18/1
0/1 9/1
6/1 9/1
6/1 10/1
1/1 10/1
1/1 17/1
8/1 17/1
8/1 14/1
9/1 14/1
9/1 17/1
16/1 17/1
16/1 10/1
9/1 10/1
8/1 9/1
16/1 9/1
16/1 1/1
9/1 1/1
9/1 8/1
8/1 8/1
8/1 1/1
1/1 1/1
1/1 8/1

View File

@ -0,0 +1,9 @@
8
0/1 -3/1
1/1 -1/1
3/1 0/1
1/1 1/1
0/1 3/1
-1/1 1/1
-3/1 0/1
-1/1 -1/1

View File

@ -0,0 +1,56 @@
#ifndef CGAL_READ_POLYGON_TEST_H
#define CGAL_READ_POLYGON_TEST_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)
{
// Open the input file.
std::ifstream ifile (filename);
if (! ifile.is_open())
{
std::cerr << "Failed to open <" << filename << ">." << std::endl;
return (false);
}
// Read the polygon.
int n_vertices;
typename Kernel::FT x, y;
std::list<typename Kernel::Point_2> vertices;
int k;
// Read the number of polygon vertices.
ifile >> n_vertices;
// Read the vertices.
for (k = 0; k < n_vertices; k++)
{
ifile >> x >> y;
vertices.push_back (typename Kernel::Point_2 (x, y));
}
ifile.close();
pgn = CGAL::Polygon_2<Kernel> (vertices.begin(), vertices.end());
// Make sure the polygon is simple.
if (! pgn.is_simple())
{
std::cerr << "Error - the polygon is not simple." << std::endl;
return (false);
}
return (true);
}
#endif

View File

@ -16,10 +16,9 @@
#include <CGAL/Small_side_angle_bisector_decomposition_2.h>
#include <CGAL/Polygon_convex_decomposition_2.h>
#include <CGAL/Boolean_set_operations_2.h>
#include "read_polygon.h"
#include <list>
#include <iostream>
#include <fstream>
typedef CGAL::Cartesian<Rational> Kernel;
typedef Kernel::Point_2 Point_2;
@ -27,53 +26,6 @@ typedef Kernel::Segment_2 Segment_2;
typedef CGAL::Polygon_2<Kernel> Polygon_2;
typedef CGAL::Polygon_with_holes_2<Kernel> Polygon_with_holes_2;
/*!
* Read a polygons from an input file.
* \param filename The name of the input file.
* \param pgn Output: The polygon.
* \return Whether the polygon was successfuly read.
*/
bool read_polygon (const char *filename, Polygon_2& pgn)
{
// Open the input file.
std::ifstream ifile (filename);
if (! ifile.is_open())
{
std::cerr << "Failed to open <" << filename << ">." << std::endl;
return (false);
}
// Read the polygon.
int n_vertices;
Rational x, y;
std::list<Point_2> vertices;
int k;
// Read the number of polygon vertices.
ifile >> n_vertices;
// Read the vertices.
for (k = 0; k < n_vertices; k++)
{
ifile >> x >> y;
vertices.push_back (Point_2 (x, y));
}
ifile.close();
pgn = Polygon_2 (vertices.begin(), vertices.end());
// Make sure the polygon is simple.
if (! pgn.is_simple())
{
std::cerr << "Error - the polygon is not simple." << std::endl;
return (false);
}
return (true);
}
/*! Check if two polygons with holes are the same. */
bool are_equal (const Polygon_with_holes_2& ph1,
const Polygon_with_holes_2& ph2)
@ -87,13 +39,13 @@ bool are_equal (const Polygon_with_holes_2& ph1,
}
/*! The main program. */
int main (int argc, char **argv )
int main (int argc, char **argv)
{
// Read the input file.
if (argc < 3)
{
std::cerr << "Usage: " << argv[0]
<< " <polygon#1> <polygon#2> ."
<< " <polygon#1> <polygon#2> [decomposition flags]"
<< std::endl;
return (1);
}
@ -113,6 +65,20 @@ int main (int argc, char **argv )
return (1);
}
// Read the decomposition flags.
bool use_ssab = true;
bool use_opt = true;
bool use_hm = true;
bool use_greene = true;
if (argc > 3)
{
use_ssab = (strchr (argv[3], 's') != NULL);
use_opt = (strchr (argv[3], 'o') != NULL);
use_hm = (strchr (argv[3], 'h') != NULL);
use_greene = (strchr (argv[3], 'g') != NULL);
}
// Compute the Minkowski sum using the convolution method.
Polygon_with_holes_2 sum_conv;
@ -127,48 +93,60 @@ int main (int argc, char **argv )
CGAL::Greene_convex_decomposition_2<Kernel> greene_decomp;
Polygon_with_holes_2 sum_decomp;
std::cout << "Using the small-side angle-bisector decomposition ... ";
sum_decomp = minkowski_sum_2 (pgn1, pgn2, ssab_decomp);
if (are_equal (sum_conv, sum_decomp))
if (use_ssab)
{
std::cout << "OK." << std::endl;
}
else
{
std::cout << "ERROR (different result)." << std::endl;
std::cout << "Using the small-side angle-bisector decomposition ... ";
sum_decomp = minkowski_sum_2 (pgn1, pgn2, ssab_decomp);
if (are_equal (sum_conv, sum_decomp))
{
std::cout << "OK." << std::endl;
}
else
{
std::cout << "ERROR (different result)." << std::endl;
}
}
std::cout << "Using the optimal convex decomposition ... ";
sum_decomp = minkowski_sum_2 (pgn1, pgn2, opt_decomp);
if (are_equal (sum_conv, sum_decomp))
if (use_opt)
{
std::cout << "OK." << std::endl;
}
else
{
std::cout << "ERROR (different result)." << std::endl;
std::cout << "Using the optimal convex decomposition ... ";
sum_decomp = minkowski_sum_2 (pgn1, pgn2, opt_decomp);
if (are_equal (sum_conv, sum_decomp))
{
std::cout << "OK." << std::endl;
}
else
{
std::cout << "ERROR (different result)." << std::endl;
}
}
std::cout << "Using the Hertel--Mehlhorn decomposition ... ";
sum_decomp = minkowski_sum_2 (pgn1, pgn2, hm_approx_decomp);
if (are_equal (sum_conv, sum_decomp))
if (use_hm)
{
std::cout << "OK." << std::endl;
}
else
{
std::cout << "ERROR (different result)." << std::endl;
std::cout << "Using the Hertel--Mehlhorn decomposition ... ";
sum_decomp = minkowski_sum_2 (pgn1, pgn2, hm_approx_decomp);
if (are_equal (sum_conv, sum_decomp))
{
std::cout << "OK." << std::endl;
}
else
{
std::cout << "ERROR (different result)." << std::endl;
}
}
std::cout << "Using the Greene decomposition ... ";
sum_decomp = minkowski_sum_2 (pgn1, pgn2, greene_decomp);
if (are_equal (sum_conv, sum_decomp))
if (use_greene)
{
std::cout << "OK." << std::endl;
}
else
{
std::cout << "ERROR (different result)." << std::endl;
std::cout << "Using the Greene decomposition ... ";
sum_decomp = minkowski_sum_2 (pgn1, pgn2, greene_decomp);
if (are_equal (sum_conv, sum_decomp))
{
std::cout << "OK." << std::endl;
}
else
{
std::cout << "ERROR (different result)." << std::endl;
}
}
return (0);

View File

@ -0,0 +1,159 @@
#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/Polygon_2.h>
#include <CGAL/approximated_offset_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 "read_polygon.h"
#include <list>
typedef CGAL::Cartesian<Rational> Kernel;
typedef Kernel::Point_2 Point_2;
typedef CGAL::Polygon_2<Kernel> Polygon_2;
typedef CGAL::Gps_circle_segment_traits_2<Kernel> Gps_traits_2;
typedef Gps_traits_2::Polygon_2 Offset_polygon_2;
typedef Gps_traits_2::Polygon_with_holes_2 Offset_polygon_with_holes_2;
/*! Check if two polygons with holes are the same. */
bool are_equal (const Offset_polygon_with_holes_2& ph1,
const Offset_polygon_with_holes_2& ph2)
{
std::list<Offset_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.
if (argc < 3)
{
std::cerr << "Usage: <polygon> <radius> ." << std::endl;
return (1);
}
// Read the polygon from the input file.
Polygon_2 pgn;
if (! read_polygon (argv[1], pgn))
{
std::cerr << "Failed to read: <" << argv[1] << ">." << std::endl;
return (1);
}
// Read the offset radius.
int numer, denom;
if (sscanf (argv[2], "%d/%d", &numer, &denom) != 2)
{
std::cerr << "Invalid radius: " << argv[2] << std::endl;
return (1);
}
Rational r = Rational (numer, denom);
const double eps = 0.0001;
// Read the decomposition flags.
bool use_ssab = true;
bool use_opt = true;
bool use_hm = true;
bool use_greene = true;
if (argc > 3)
{
use_ssab = (strchr (argv[3], 's') != NULL);
use_opt = (strchr (argv[3], 'o') != NULL);
use_hm = (strchr (argv[3], 'h') != NULL);
use_greene = (strchr (argv[3], 'g') != NULL);
}
// Compute the Minkowski sum using the convolution method.
Offset_polygon_with_holes_2 offset_conv;
std::cout << "Using the convolution method ... ";
offset_conv = approximated_offset_2 (pgn, r, eps);
std::cout << "Done." << std::endl;
// 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;
Offset_polygon_with_holes_2 offset_decomp;
if (use_ssab)
{
std::cout << "Using the small-side angle-bisector decomposition ... ";
offset_decomp = approximated_offset_2 (pgn, r, eps, ssab_decomp);
if (are_equal (offset_conv, offset_decomp))
{
std::cout << "OK." << std::endl;
}
else
{
std::cout << "ERROR (different result)." << std::endl;
}
}
if (use_opt)
{
std::cout << "Using the optimal convex decomposition ... ";
offset_decomp = approximated_offset_2 (pgn, r, eps, opt_decomp);
if (are_equal (offset_conv, offset_decomp))
{
std::cout << "OK." << std::endl;
}
else
{
std::cout << "ERROR (different result)." << std::endl;
}
}
if (use_hm)
{
std::cout << "Using the Hertel--Mehlhorn decomposition ... ";
offset_decomp = approximated_offset_2 (pgn, r, eps, hm_approx_decomp);
if (are_equal (offset_conv, offset_decomp))
{
std::cout << "OK." << std::endl;
}
else
{
std::cout << "ERROR (different result)." << std::endl;
}
}
if (use_greene)
{
std::cout << "Using the Greene decomposition ... ";
offset_decomp = approximated_offset_2 (pgn, r, eps, greene_decomp);
if (are_equal (offset_conv, offset_decomp))
{
std::cout << "OK." << std::endl;
}
else
{
std::cout << "ERROR (different result)." << std::endl;
}
}
return (0);
}

View File

@ -0,0 +1,172 @@
#include <CGAL/basic.h>
#ifndef CGAL_USE_CORE
#include <iostream>
int main ()
{
std::cout << "Sorry, this test needs CORE ..." << std::endl;
return (0);
}
#else
#include <CGAL/Cartesian.h>
#include <CGAL/CORE_algebraic_number_traits.h>
#include <CGAL/Arr_conic_traits_2.h>
#include <CGAL/Polygon_2.h>
#include <CGAL/offset_polygon_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 "read_polygon.h"
#include <list>
typedef CGAL::CORE_algebraic_number_traits Nt_traits;
typedef Nt_traits::Rational Rational;
typedef Nt_traits::Algebraic Algebraic;
typedef CGAL::Cartesian<Rational> Rat_kernel;
typedef CGAL::Cartesian<Algebraic> Alg_kernel;
typedef CGAL::Arr_conic_traits_2<Rat_kernel,
Alg_kernel,Nt_traits> Conic_traits_2;
typedef Rat_kernel::Point_2 Point_2;
typedef CGAL::Polygon_2<Rat_kernel> Polygon_2;
typedef CGAL::Gps_traits_2<Conic_traits_2> Gps_traits_2;
typedef Gps_traits_2::Polygon_2 Offset_polygon_2;
typedef Gps_traits_2::Polygon_with_holes_2 Offset_polygon_with_holes_2;
/*! Check if two polygons with holes are the same. */
bool are_equal (const Offset_polygon_with_holes_2& ph1,
const Offset_polygon_with_holes_2& ph2)
{
std::list<Offset_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.
if (argc < 3)
{
std::cerr << "Usage: <polygon> <radius> ." << std::endl;
return (1);
}
// Read the polygon from the input file.
Polygon_2 pgn;
if (! read_polygon (argv[1], pgn))
{
std::cerr << "Failed to read: <" << argv[1] << ">." << std::endl;
return (1);
}
// Read the offset radius.
int numer, denom;
if (sscanf (argv[2], "%d/%d", &numer, &denom) != 2)
{
std::cerr << "Invalid radius: " << argv[2] << std::endl;
return (1);
}
Rational r = Rational (numer, denom);
// Read the decomposition flags.
bool use_ssab = true;
bool use_opt = true;
bool use_hm = true;
bool use_greene = true;
if (argc > 3)
{
use_ssab = (strchr (argv[3], 's') != NULL);
use_opt = (strchr (argv[3], 'o') != NULL);
use_hm = (strchr (argv[3], 'h') != NULL);
use_greene = (strchr (argv[3], 'g') != NULL);
}
// Compute the Minkowski sum using the convolution method.
Conic_traits_2 traits;
Offset_polygon_with_holes_2 offset_conv;
std::cout << "Using the convolution method ... ";
offset_conv = offset_polygon_2 (pgn, r, traits);
std::cout << "Done." << std::endl;
// Define auxiliary polygon-decomposition objects.
CGAL::Small_side_angle_bisector_decomposition_2<Rat_kernel> ssab_decomp;
CGAL::Optimal_convex_decomposition_2<Rat_kernel> opt_decomp;
CGAL::Hertel_Mehlhorn_convex_decomposition_2<Rat_kernel> hm_approx_decomp;
CGAL::Greene_convex_decomposition_2<Rat_kernel> greene_decomp;
Offset_polygon_with_holes_2 offset_decomp;
if (use_ssab)
{
std::cout << "Using the small-side angle-bisector decomposition ... ";
offset_decomp = offset_polygon_2 (pgn, r, ssab_decomp, traits);
if (are_equal (offset_conv, offset_decomp))
{
std::cout << "OK." << std::endl;
}
else
{
std::cout << "ERROR (different result)." << std::endl;
}
}
if (use_opt)
{
std::cout << "Using the optimal convex decomposition ... ";
offset_decomp = offset_polygon_2 (pgn, r, opt_decomp, traits);
if (are_equal (offset_conv, offset_decomp))
{
std::cout << "OK." << std::endl;
}
else
{
std::cout << "ERROR (different result)." << std::endl;
}
}
if (use_hm)
{
std::cout << "Using the Hertel--Mehlhorn decomposition ... ";
offset_decomp = offset_polygon_2 (pgn, r, hm_approx_decomp, traits);
if (are_equal (offset_conv, offset_decomp))
{
std::cout << "OK." << std::endl;
}
else
{
std::cout << "ERROR (different result)." << std::endl;
}
}
if (use_greene)
{
std::cout << "Using the Greene decomposition ... ";
offset_decomp = offset_polygon_2 (pgn, r, greene_decomp, traits);
if (are_equal (offset_conv, offset_decomp))
{
std::cout << "OK." << std::endl;
}
else
{
std::cout << "ERROR (different result)." << std::endl;
}
}
return (0);
}
#endif