Merge pull request #7950 from efifogel/Ss_2-test_conics-efif

Surface_sweep_2: enhance the conic tests
This commit is contained in:
Laurent Rineau 2024-01-08 10:59:18 +01:00
commit 078b07ba62
13 changed files with 335 additions and 397 deletions

View File

@ -49,7 +49,7 @@ endfunction()
compile_and_run_sweep(test_sweep test_sweep.cpp ${NAIVE} compile_and_run_sweep(test_sweep test_sweep.cpp ${NAIVE}
${CGAL_SEGMENT_TRAITS} "data/segments_tight") ${CGAL_SEGMENT_TRAITS} "data/segments_tight")
compile_and_run_sweep(test_sweep_conic test_sweep_conic.cpp ${NAIVE} compile_and_run_sweep(test_sweep_conic test_sweep.cpp ${NAIVE}
${CGAL_CONIC_TRAITS} "data/conics") ${CGAL_CONIC_TRAITS} "data/conics")
compile_and_run_sweep(test_sweep_polyline test_sweep.cpp ${NAIVE} compile_and_run_sweep(test_sweep_polyline test_sweep.cpp ${NAIVE}
${CGAL_POLYLINE_TRAITS} "data/polylines") ${CGAL_POLYLINE_TRAITS} "data/polylines")

View File

@ -8,4 +8,3 @@ e 3 3 7 5 4 5 10 5
{1*x^2 + 1*y^2 + 0*xy + -14*x + -10*y + 65} : (4.66667,6.88562) --cw--> (10,5) {1*x^2 + 1*y^2 + 0*xy + -14*x + -10*y + 65} : (4.66667,6.88562) --cw--> (10,5)
5 5
1 1

View File

@ -10,5 +10,3 @@ e 3 3 4 9 7 9 1 9
{1*x^2 + 1*y^2 + 0*xy + -8*x + -18*y + 88} : (7,9) --cw--> (5.45237,6.375) {1*x^2 + 1*y^2 + 0*xy + -8*x + -18*y + 88} : (7,9) --cw--> (5.45237,6.375)
6 6
2 2

View File

@ -12,8 +12,3 @@ f 3 3 4 9
{1*x^2 + 1*y^2 + 0*xy + -8*x + -18*y + 88} : (1,9) --cw--> (7,9) {1*x^2 + 1*y^2 + 0*xy + -8*x + -18*y + 88} : (1,9) --cw--> (7,9)
6 6
2 2

View File

@ -12,6 +12,4 @@ f 1 1 3 2
{1*x^2 + 1*y^2 + 0*xy + -6*x + -4*y + 12} : (4,2) --cw--> (2,2) {1*x^2 + 1*y^2 + 0*xy + -6*x + -4*y + 12} : (4,2) --cw--> (2,2)
{1*x^2 + 1*y^2 + 0*xy + -6*x + -4*y + 12} : (2,2) --cw--> (4,2) {1*x^2 + 1*y^2 + 0*xy + -6*x + -4*y + 12} : (2,2) --cw--> (4,2)
6 6
0 1

View File

@ -12,7 +12,3 @@ f 3 3 4 9
{1*x^2 + 1*y^2 + 0*xy + -8*x + -18*y + 88} : (1,9) --cw--> (7,9) {1*x^2 + 1*y^2 + 0*xy + -8*x + -18*y + 88} : (1,9) --cw--> (7,9)
6 6
2 2

View File

@ -14,4 +14,3 @@ f 1 1 1 1
{1*x^2 + 1*y^2 + 0*xy + -4*x + 0*y + 3} : (2,1) --cw--> (3,0) {1*x^2 + 1*y^2 + 0*xy + -4*x + 0*y + 3} : (2,1) --cw--> (3,0)
5 5
3 3

View File

@ -10,4 +10,3 @@ f 2 2 2 2
{1*x^2 + 1*y^2 + 0*xy + -4*x + -4*y + 4} : (0,2) --cw--> (4,2) {1*x^2 + 1*y^2 + 0*xy + -4*x + -4*y + 4} : (0,2) --cw--> (4,2)
5 5
1 1

View File

@ -26,5 +26,3 @@ f 3 1 0 0
{4*x^2 + 25*y^2 + 0*xy + -16*x + 0*y + -84} : (2.75552,1.97704) --cw--> (7,0) {4*x^2 + 25*y^2 + 0*xy + -16*x + 0*y + -84} : (2.75552,1.97704) --cw--> (7,0)
10 10
6 6

View File

@ -121,5 +121,4 @@ f 1 1 -4 0
{1*x^2 + 1*y^2 + 0*xy + -8*x + 0*y + 0} : (8,0) --cw--> (4.5,-3.96863) {1*x^2 + 1*y^2 + 0*xy + -8*x + 0*y + 0} : (8,0) --cw--> (4.5,-3.96863)
{1*x^2 + 1*y^2 + 0*xy + -8*x + 0*y + 0} : (4.5,3.96863) --cw--> (8,0) {1*x^2 + 1*y^2 + 0*xy + -8*x + 0*y + 0} : (4.5,3.96863) --cw--> (8,0)
59 59
34 41

View File

@ -18,5 +18,4 @@ s 7 -2 3 2
{1*x^2 + 1*y^2 + 0*xy + -14*x + 2*y + 49} : (8,-1) --cw--> (7,-2) {1*x^2 + 1*y^2 + 0*xy + -14*x + 2*y + 49} : (8,-1) --cw--> (7,-2)
{1*x^2 + 1*y^2 + 0*xy + -14*x + 2*y + 49} : (7,0) --cw--> (8,-1) {1*x^2 + 1*y^2 + 0*xy + -14*x + 2*y + 49} : (7,0) --cw--> (8,-1)
8 8
7 5

View File

@ -8,6 +8,8 @@
#include <string> #include <string>
#include <CGAL/config.h> #include <CGAL/config.h>
#include <CGAL/Arrangement_2.h>
// #include <CGAL/draw_arrangement_2.h>
#define CGAL_SEGMENT_TRAITS 1 #define CGAL_SEGMENT_TRAITS 1
#define CGAL_POLYLINE_TRAITS 11 #define CGAL_POLYLINE_TRAITS 11
@ -101,8 +103,8 @@ typedef Rat_kernel::Segment_2 Rat_segment_2;
typedef Rat_kernel::Circle_2 Rat_circle_2; typedef Rat_kernel::Circle_2 Rat_circle_2;
typedef CGAL::Cartesian<Algebraic> Alg_kernel; typedef CGAL::Cartesian<Algebraic> Alg_kernel;
typedef CGAL::Arr_conic_traits_2<Rat_kernel, Alg_kernel, Nt_traits> typedef CGAL::Arr_conic_traits_2<Rat_kernel, Alg_kernel, Nt_traits>
Traits_2; Traits;
#elif CGAL_ARR_TEST_TRAITS == CGAL_POLYCURVE_TRAITS #elif CGAL_ARR_TEST_TRAITS == CGAL_POLYCONIC_TRAITS
typedef CGAL::CORE_algebraic_number_traits Nt_traits; typedef CGAL::CORE_algebraic_number_traits Nt_traits;
typedef Nt_traits::Rational Rational; typedef Nt_traits::Rational Rational;
typedef Nt_traits::Algebraic Algebraic; typedef Nt_traits::Algebraic Algebraic;
@ -125,10 +127,6 @@ typedef std::list<Point_2> Points;
typedef std::list<Curve_2> Curves; typedef std::list<Curve_2> Curves;
typedef std::list<X_monotone_curve_2> X_monotone_curves; typedef std::list<X_monotone_curve_2> X_monotone_curves;
bool read_curves(std::ifstream& inp, Curves& curves, const Traits& traits);
bool read_xcurves(std::ifstream& inp, X_monotone_curves& xcurves,
const Traits& traits);
bool read_points(std::ifstream& inp, Points& points, const Traits& traits);
bool curves_identical(X_monotone_curves& list1, X_monotone_curves& list2); bool curves_identical(X_monotone_curves& list1, X_monotone_curves& list2);
bool points_identical(Points& list1, Points& list2); bool points_identical(Points& list1, Points& list2);
@ -148,109 +146,31 @@ std::istream& skip_comment(std::istream& in) {
return in; return in;
} }
int main(int argc, char* argv[]) { #if CGAL_ARR_TEST_TRAITS != CGAL_CONIC_TRAITS
if (argc != 2) {
std::cout << "Specify a file name " << std::endl; bool read_points(std::ifstream& inp, Points& points, const Traits&) {
return -1; int count;
inp >> skip_comment >> count;
// std::cout << "read_points " << count << "\n";
for (int i = 0; i < count; i++) {
NT x, y;
inp >> skip_comment >> x >> y;
Point_2 p(x, y);
// std::cout << p << "\n";
points.push_back(p);
} }
return true;
std::ifstream inp(argv[1]);
if (! inp.is_open()) {
std::cerr << "Error: Cannot open file " << argv[1] << "!" << std::endl;
return -1;
}
Traits tr;
Curves curves;
if (! read_curves(inp, curves, tr)) return -1;
// Test subcurves w/o overlapping
X_monotone_curves curves_no_overlap_out;
CGAL::compute_subcurves(curves.begin(), curves.end(),
std::back_inserter(curves_no_overlap_out),
false, tr);
X_monotone_curves curves_no_overlap;
if (! read_xcurves(inp, curves_no_overlap, tr)) return -1;
if (! compare_lists(curves_no_overlap_out, curves_no_overlap, tr)) {
std::cerr << "Curves w/o overlapping do not match!\n";
for (const auto& xcv : curves_no_overlap_out) std::cerr << xcv << std::endl;
return -1;
}
// Test intersection points (with endpoints)
Points points_with_ends_out;
CGAL::compute_intersection_points(curves.begin(), curves.end(),
std::back_inserter(points_with_ends_out),
true, tr);
Points points_with_ends;
if (! read_points(inp, points_with_ends, tr)) return -1;
if (! compare_lists(points_with_ends_out, points_with_ends, tr)) {
std::cerr << "Endpoints do not match!\n";
for (const auto& p : points_with_ends_out) std::cerr << p << std::endl;
return -1;
}
// Test intersection points w/o end points
Points points_without_ends_out;
CGAL::compute_intersection_points(curves.begin(), curves.end(),
std::back_inserter(points_without_ends_out),
false, tr);
Points points_without_ends;
if (! read_points(inp, points_without_ends, tr)) return -1;
if (! compare_lists(points_without_ends_out, points_without_ends, tr)) {
std::cerr << "Intersection points do not match!\n";
for (const auto& p : points_without_ends_out) std::cerr << p << std::endl;
return -1;
}
// Test subcurves w/ overlapping
X_monotone_curves curves_with_overlap_out;
CGAL::compute_subcurves(curves.begin(), curves.end(),
std::back_inserter(curves_with_overlap_out),
true, tr);
X_monotone_curves curves_with_overlap;
if (! read_xcurves(inp, curves_with_overlap, tr)) return -1;
if (! compare_lists(curves_with_overlap_out, curves_with_overlap, tr)) {
std::cerr << "Curves w/ overlapping do not match!\n";
for (const auto& xcv : curves_with_overlap_out)
std::cerr << xcv << std::endl;
return -1;
}
// Test the do_curves_intersecting method
bool do_intersect_out =
CGAL::do_curves_intersect(curves.begin(), curves.end());
bool do_intersect = false;
if ((points_without_ends.size() != 0) ||
(curves_no_overlap_out.size() != curves_with_overlap_out.size()))
do_intersect = true;
if (do_intersect_out != do_intersect) {
std::cerr << "Error: do_intersect()\n";
return -1;
}
std::cout << "Passed\n";
return 0;
} }
#endif
#if CGAL_ARR_TEST_TRAITS == CGAL_SEGMENT_TRAITS #if CGAL_ARR_TEST_TRAITS == CGAL_SEGMENT_TRAITS
bool read_curves(std::ifstream& inp, Curves& curves, const Traits&) { bool read_curves(std::ifstream& inp, Curves& curves, const Traits&) {
int count; int count;
inp >> skip_comment >> count; inp >> skip_comment >> count;
std::cout << "read_curves " << count << "\n"; // std::cout << "read_curves " << count << "\n";
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
NT x0, y0, x1, y1; NT x0, y0, x1, y1;
@ -259,7 +179,7 @@ bool read_curves(std::ifstream& inp, Curves& curves, const Traits&) {
Point_2 p2(x1, y1); Point_2 p2(x1, y1);
Curve_2 curve(p1, p2); Curve_2 curve(p1, p2);
curves.push_back(curve); curves.push_back(curve);
std::cout << curve << "\n"; // std::cout << curve << "\n";
} }
return true; return true;
} }
@ -302,23 +222,320 @@ bool read_xcurves(std::ifstream& inp, X_monotone_curves& xcurves,
return read_curves_(inp, xcurves, traits, ctr_xcv); return read_curves_(inp, xcurves, traits, ctr_xcv);
} }
#else #elif CGAL_ARR_TEST_TRAITS == CGAL_CONIC_TRAITS
#error No traits defined for test
#endif
bool read_points(std::ifstream& inp, Points& points, const Traits&) { void read_curve(std::ifstream& is, Curve_2& cv, const Traits& traits) {
// Read a line from the input file.
char one_line[128];
auto ctr_curve_2 = traits.construct_curve_2_object();
is >> skip_comment;
is.getline(one_line, 128);
std::string stringvalues(one_line);
std::istringstream str_line(stringvalues, std::istringstream::in);
// Get the arc type.
// Supported types are: 'f' - Full ellipse (or circle).
// 'e' - Elliptic arc (or circular arc).
// 's' - Line segment.
char type;
bool is_circle = false; // Is this a circle.
Rat_circle_2 circle;
Rational r, s, t, u, v, w; // The conic coefficients.
str_line >> type;
// An ellipse (full ellipse or a partial ellipse):
if (type == 'f' || type == 'F' || type == 'e' || type == 'E') {
// Read the ellipse (using the format "a b x0 y0"):
//
// x - x0 2 y - y0 2
// ( -------- ) + ( -------- ) = 1
// a b
//
int a, b, x0, y0;
str_line >> a >> b >> x0 >> y0;
Rational a_sq = Rational(a*a);
Rational b_sq = Rational(b*b);
if (a == b) {
is_circle = true;
circle =
Rat_circle_2(Rat_point_2(Rational(x0), Rational(y0)), Rational(a*b));
}
else {
r = b_sq;
s = a_sq;
t = 0;
u = Rational(-2*x0*b_sq);
v = Rational(-2*y0*a_sq);
w = Rational(x0*x0*b_sq + y0*y0*a_sq - a_sq*b_sq);
}
if (type == 'f' || type == 'F') {
// Create a full ellipse (or circle).
if (is_circle) cv = ctr_curve_2(circle);
else cv = ctr_curve_2(r, s, t, u, v, w);
}
else {
// Read the endpointd of the arc.
int x1, y1, x2, y2;
str_line >> x1 >> y1 >> x2 >> y2;
Point_2 source = Point_2(Algebraic(x1), Algebraic(y1));
Point_2 target = Point_2(Algebraic(x2), Algebraic(y2));
// Create the arc. Note that it is always clockwise oriented.
if (is_circle) cv = ctr_curve_2(circle, CGAL::CLOCKWISE, source, target);
else cv = ctr_curve_2(r, s, t, u, v, w, CGAL::CLOCKWISE, source, target);
}
}
else if (type == 's' || type == 'S') {
// Read a segment, given by its endpoints (x1,y1) and (x2,y2);
int x1, y1, x2, y2;
str_line >> x1 >> y1 >> x2 >> y2;
// Create the segment.
Rat_point_2 source = Rat_point_2 (Rational(x1), Rational(y1));
Rat_point_2 target = Rat_point_2 (Rational(x2), Rational(y2));
cv = ctr_curve_2(Rat_segment_2 (source, target));
}
// std::cout << cv << std::endl;
}
/*! Read curves.
*/
bool read_curves(std::ifstream& inp, Curves& curves, const Traits& traits) {
// auto ctr_cv = traits.construct_curve_2_object();
int count; int count;
inp >> skip_comment >> count; inp >> skip_comment >> count;
Curve_2 cv;
// std::cout << "read_points " << count << "\n"; char dummy[256];
for (int i = 0; i < count; i++) { inp.getline(dummy, sizeof(dummy));
NT x, y; for (int i = 0; i < count; ++i) {
inp >> skip_comment >> x >> y; read_curve(inp, cv, traits);
Point_2 p(x, y); curves.push_back(cv);
// std::cout << p << "\n";
points.push_back(p);
} }
return true; return true;
} }
#else
#error No traits defined for test
#endif
#if CGAL_ARR_TEST_TRAITS != CGAL_CONIC_TRAITS
// Test subcurves w/o overlapping
bool test_curves_no_overlap(std::ifstream& inp, Curves& /* curves */,
const X_monotone_curves& curves_no_overlap_out,
const Traits& tr) {
X_monotone_curves curves_no_overlap;
if (! read_xcurves(inp, curves_no_overlap, tr)) return false;
if (! compare_lists(curves_no_overlap_out, curves_no_overlap, tr)) {
std::cerr << "Error: Curves w/o overlapping do not match!\n";
for (const auto& xcv : curves_no_overlap_out) std::cerr << xcv << std::endl;
return false;
}
return true;
}
// Test subcurves w/ overlapping
bool test_curves_with_overlap(std::ifstream& inp, Curves& /* curves */,
const X_monotone_curves& curves_with_overlap_out,
const Traits& tr) {
X_monotone_curves curves_with_overlap;
if (! read_xcurves(inp, curves_with_overlap, tr)) return false;
if (! compare_lists(curves_with_overlap_out, curves_with_overlap, tr)) {
std::cerr << "Error: Curves w/ overlapping do not match!\n";
for (const auto& xcv : curves_with_overlap_out)
std::cerr << xcv << std::endl;
return false;
}
return true;
}
// Test intersection points (with endpoints)
bool test_points_with_ends(std::ifstream& inp, Curves& /* curves */,
const Points& points_with_ends_out,
const Traits& tr) {
Points points_with_ends;
if (! read_points(inp, points_with_ends, tr)) return false;
if (! compare_lists(points_with_ends_out, points_with_ends, tr)) {
std::cerr << "Error: Endpoints do not match!\n";
for (const auto& p : points_with_ends_out) std::cerr << p << std::endl;
return false;
}
return true;
}
// Test intersection points w/o end points
bool test_points_no_ends(std::ifstream& inp, Curves& /* curves */,
const Points& points_no_ends_out,
const Traits& tr) {
Points points_no_ends;
if (! read_points(inp, points_no_ends, tr)) return false;
if (! compare_lists(points_no_ends_out, points_no_ends, tr)) {
std::cerr << "Error: Intersection points do not match!\n";
for (const auto& p : points_no_ends_out) std::cerr << p << std::endl;
return false;
}
return true;
}
#else
/*! Test the surface sweep with conic traits.
*/
bool test_conic(std::ifstream& inp, Curves& curves,
const X_monotone_curves& curves_no_overlap_out,
const Points& points_with_ends_out,
const Points& points_no_ends_out,
const Traits& traits) {
auto ctr_bbox_2 = traits.construct_bbox_2_object();
CGAL::Bbox_2 bbox = ctr_bbox_2(curves.front());
for (auto it = std::next(curves.begin()); it != curves.end(); ++it)
bbox = bbox + ctr_bbox_2(*it);
// generate the string for the output
std::stringstream out1;
for (const auto& xcv : curves_no_overlap_out) out1 << xcv << "\n";
// read the output from the file
std::stringstream out2;
char buf[1024];
int count = 0;
inp >> count;
inp.getline(buf, 1024); // to get rid of the new line
for (int i = 0; i < count; ++i) {
inp.getline(buf, 1024);
out2 << buf << "\n";
}
// std::cout << "Result: \n" << curves_no_overlap_out.size() << "\n";
// for (const auto& xcv : curves_no_overlap_out)
// std::cout << xcv << "\n";
std::string calculated = out1.str();
std::string infile = out2.str();
if (infile != calculated) {
std::cerr << "Error\n";
std::cerr << "\ncalculated:\n";
std::cerr << calculated << std::endl;
std::cerr << "\nin file:\n";
std::cerr << infile << std::endl;
std::cerr << "--" << std::endl;
return false;
}
std::size_t points_with_ends_size, points_no_ends_size;
inp >> skip_comment >> points_with_ends_size >> points_no_ends_size;
auto points_with_ends_out_size = points_with_ends_out.size();
if (points_with_ends_size != points_with_ends_out_size ) {
std::cerr << "Error: Number of endpoints do not match ("
<< points_with_ends_out_size << ", "
<< points_with_ends_size << ")\n";
return false;
}
auto points_no_ends_out_size = points_no_ends_out.size();
if (points_no_ends_size != points_no_ends_out_size) {
std::cerr << "Error: Number of intersection points do not match ("
<< points_no_ends_out_size << ", "
<< points_no_ends_size << ")\n";
return false;
}
return true;
}
#endif
int main(int argc, char* argv[]) {
if (argc != 2) {
std::cout << "Specify a file name " << std::endl;
return -1;
}
std::ifstream inp(argv[1]);
if (! inp.is_open()) {
std::cerr << "Error: Cannot open file " << argv[1] << "!" << std::endl;
return -1;
}
Traits tr;
Curves curves;
if (! read_curves(inp, curves, tr)) return -1;
// {
// using Arrangement = CGAL::Arrangement_2<Traits>;
// Arrangement arr(&tr);
// CGAL::insert(arr, curves.begin(), curves.end());
// CGAL::draw(arr, "conics", true);
// }
X_monotone_curves curves_no_overlap_out;
CGAL::compute_subcurves(curves.begin(), curves.end(),
std::back_inserter(curves_no_overlap_out),
false, tr);
X_monotone_curves curves_with_overlap_out;
CGAL::compute_subcurves(curves.begin(), curves.end(),
std::back_inserter(curves_with_overlap_out),
true, tr);
Points points_with_ends_out;
CGAL::compute_intersection_points(curves.begin(), curves.end(),
std::back_inserter(points_with_ends_out),
true, tr);
Points points_no_ends_out;
CGAL::compute_intersection_points(curves.begin(), curves.end(),
std::back_inserter(points_no_ends_out),
false, tr);
#if CGAL_ARR_TEST_TRAITS == CGAL_CONIC_TRAITS
if (! test_conic(inp, curves, curves_no_overlap_out,
points_with_ends_out, points_no_ends_out, tr))
return -1;
#else
if (! test_curves_no_overlap(inp, curves, curves_no_overlap_out, tr))
return -1;
if (! test_points_with_ends(inp, curves, points_with_ends_out, tr)) return -1;
if (! test_points_no_ends(inp, curves, points_no_ends_out, tr)) return -1;
if (! test_curves_with_overlap(inp, curves, curves_with_overlap_out, tr))
return -1;
#endif
// Test the do_curves_intersecting method
bool do_intersect_out =
CGAL::do_curves_intersect(curves.begin(), curves.end());
bool do_intersect = ! points_no_ends_out.empty() ||
(curves_no_overlap_out.size() != curves_with_overlap_out.size());
if (do_intersect_out != do_intersect) {
std::cerr << "Error: do_intersect()\n";
return -1;
}
std::cout << "Passed\n";
return 0;
}
#endif #endif

View File

@ -1,259 +0,0 @@
#include <CGAL/config.h>
#if !defined(CGAL_USE_CORE)
#include <iostream>
int main()
{
std::cout << "CORE is not installed. Test aborted!" << std::endl;
return 0;
}
#else
#include <CGAL/Cartesian.h>
#include <CGAL/Surface_sweep_2_algorithms.h>
#include <CGAL/Arr_conic_traits_2.h>
#include <CGAL/CORE_algebraic_number_traits.h>
#include <vector>
#include <iostream>
#include <sstream>
#include <string>
#include <fstream>
#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 Rat_kernel::Point_2 Rat_point_2;
typedef Rat_kernel::Segment_2 Rat_segment_2;
typedef Rat_kernel::Circle_2 Rat_circle_2;
typedef CGAL::Cartesian<Algebraic> Alg_kernel;
typedef CGAL::Arr_conic_traits_2<Rat_kernel, Alg_kernel, Nt_traits>
Traits_2;
typedef Traits_2::Curve_2 Curve_2;
typedef Traits_2::X_monotone_curve_2 X_monotone_curve_2;
typedef Traits_2::Point_2 Point_2;
typedef std::list<Curve_2> CurveList;
typedef std::list<Point_2> PointList;
typedef PointList::iterator PointListIter;
/*! Conic reader */
template <typename Traits>
class Conic_reader {
private:
Traits_2 m_traits;
public:
int read_data(const char* filename, CurveList& curves, CGAL::Bbox_2& bbox,
const Traits& traits) {
Curve_2 cv;
char dummy[256];
std::ifstream inp(filename);
if (!inp.is_open()) {
std::cerr << "Cannot open file " << filename << "!" << std::endl;
return -1;
}
int count;
inp >> count;
inp.getline(dummy, sizeof(dummy));
for (int i = 0; i < count; ++i) {
read_curve(inp, cv);
curves.push_back(cv);
CGAL::Bbox_2 curve_bbox = traits.construct_bbox_2_object()(cv);
if (i == 0) bbox = curve_bbox;
else bbox = bbox + curve_bbox;
}
inp.close();
return 0;
}
void read_curve(std::ifstream& is, Curve_2& cv) {
auto ctr_cv = m_traits.construct_curve_2_object();
// Read a line from the input file.
char one_line[128];
skip_comments(is, one_line);
std::string stringvalues(one_line);
std::istringstream str_line(stringvalues, std::istringstream::in);
// Get the arc type.
// Supported types are: 'f' - Full ellipse (or circle).
// 'e' - Elliptic arc (or circular arc).
// 's' - Line segment.
bool is_circle(false); // Is this a circle.
Rat_circle_2 circle;
Rational r, s, t, u, v, w; // The conic coefficients.
char type;
str_line >> type;
// An ellipse (full ellipse or a partial ellipse):
if (type == 'f' || type == 'F' || type == 'e' || type == 'E') {
// Read the ellipse (using the format "a b x0 y0"):
//
// x - x0 2 y - y0 2
// ( -------- ) + ( -------- ) = 1
// a b
//
int a, b, x0, y0;
str_line >> a >> b >> x0 >> y0;
Rational a_sq = Rational(a*a);
Rational b_sq = Rational(b*b);
if (a == b) {
is_circle = true;
circle =
Rat_circle_2(Rat_point_2(Rational(x0), Rational(y0)), Rational(a*b));
}
else {
r = b_sq;
s = a_sq;
t = 0;
u = Rational(-2*x0*b_sq);
v = Rational(-2*y0*a_sq);
w = Rational(x0*x0*b_sq + y0*y0*a_sq - a_sq*b_sq);
}
if (type == 'f' || type == 'F') {
// Create a full ellipse (or circle).
cv = (is_circle) ? ctr_cv(circle) : ctr_cv(r, s, t, u, v, w);
return;
}
// Read the endpointd of the arc.
int x1, y1, x2, y2;
str_line >> x1 >> y1 >> x2 >> y2;
Point_2 source = Point_2 (Algebraic(x1), Algebraic(y1));
Point_2 target = Point_2 (Algebraic(x2), Algebraic(y2));
// Create the arc. Note that it is always clockwise oriented.
cv = (is_circle) ?
ctr_cv(circle, CGAL::CLOCKWISE, source, target) :
ctr_cv(r, s, t, u, v, w, CGAL::CLOCKWISE, source, target);
return;
}
if (type == 's' || type == 'S') {
// Read a segment, given by its endpoints (x1,y1) and (x2,y2);
int x1, y1, x2, y2;
str_line >> x1 >> y1 >> x2 >> y2;
// Create the segment.
Rat_point_2 source = Rat_point_2(Rational(x1), Rational(y1));
Rat_point_2 target = Rat_point_2(Rational(x2), Rational(y2));
cv = ctr_cv(Rat_segment_2(source, target));
return;
}
std::cerr << "Invalid type (" << type << ")" << std::endl;
}
void skip_comments( std::ifstream& is, char* one_line) {
while( !is.eof() ){
is.getline( one_line, 128 );
if( one_line[0] != '#' ){
break;
}
}
}
};
//---------------------------------------------------------------------------
// The main:
//
int main(int argc, char* argv[]) {
bool verbose = false;
// Define a test objects to read the conic arcs from it.
if (argc<2) {
std::cerr << "Usage: Conic_traits_test <filename>" << std::endl;
exit(1);
}
Traits_2 traits;
CGAL::Bbox_2 bbox;
CurveList curves;
Conic_reader<Traits_2> reader;
reader.read_data(argv[1], curves, bbox, traits);
// run the sweep
std::list<X_monotone_curve_2> mylist;
CGAL::compute_subcurves(curves.begin(), curves.end(),
std::back_inserter(mylist), false);
PointList point_list_with_ends;
CGAL::compute_intersection_points(curves.begin(), curves.end(),
std::back_inserter(point_list_with_ends),
true);
std::size_t point_count_with_ends_calculated = point_list_with_ends.size();
// generate the string for the output
std::stringstream out1;
for (auto iter = mylist.begin(); iter != mylist.end(); ++iter)
out1 << *iter << "\n";
// read the output from the file
std::stringstream out2;
char buf[1024];
int count = 0;
std::ifstream in_file(argv[1]);
in_file >> count;
in_file.getline(buf, 1024); // to get rid of the new line
for (int i = 0 ; i < count ; ++i) in_file.getline(buf, 1024);
in_file >> count;
in_file.getline(buf, 1024); // to get rid of the new line
for (int i = 0; i < count; ++i) {
in_file.getline(buf, 1024);
out2 << buf << "\n";
}
std::size_t point_count_with_ends_from_file = 0;
in_file >> point_count_with_ends_from_file;
in_file.close();
if (verbose) {
std::cout << "Result: \n" << mylist.size() << "\n";
for (auto i = mylist.begin(); i != mylist.end() ; ++i)
std::cout << *i << "\n";
}
std::string calculated = out1.str();
std::string infile = out2.str();
if (infile == calculated) {
if (point_count_with_ends_from_file != point_count_with_ends_calculated) {
std::cout << "number of intersection points (with ends):"
<< point_count_with_ends_calculated << ". Should be "
<< point_count_with_ends_from_file << "\n";
std::cout << argv[1] << " Error\n";
return -1;
}
else {
std::cout << argv[1] << " OK!\n";
}
}
else {
std::cout << argv[1] << " Error\n";
std::cout << "\ncalculated:\n";
std::cout << calculated << std::endl;
std::cout << "\nin file:\n";
std::cout << infile << std::endl;
std::cout << "--" << std::endl;
return -1;
}
return 0;
}
#endif