From CGAL I am currently using the following package: Boolean operations on polygons
As I am interested in polygons which can have, besides line segments, as edges also circle segments, I use the following build-up for my basic typedefs:
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef Kernel::Point_2 Point_2;
typedef Kernel::Circle_2 Circle_2;
typedef Kernel::Line_2 Line_2;
typedef CGAL::Gps_circle_segment_traits_2<Kernel> Traits_2;
typedef CGAL::General_polygon_set_2<Traits_2> Polygon_set_2;
typedef Traits_2::General_polygon_2 Polygon_2;
typedef Traits_2::General_polygon_with_holes_2 Polygon_with_holes_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_2t;
typedef Traits_2::CoordNT coordnt;
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
typedef Arrangement_2::Face_handle Face_handle;
As shown in the types above, I have two Point-types namely Point_2 which is Kernel::Point_2 and what I called Point_2t which is Traits_2::Point_2.
The difference between them is, that Point_2 has rational coordinates x(), y() whereas Point_2t has coordinates in Q(alpha) where Q stands for the rational field and alpha is the square-root of a rational number.
Or, to say it otherwise, the coordinates for Point_2 are in Kernel::FT, whereas the coordinates of Point_2t are in Traits_2::CoordNT.
So converting from Point_2 to Point_2t is no problem, but I have to convert also from Point_2t to Point_2, hopefully in a way which gives control over the lost precision.
Reading through the documentation and using the autocomplete feature of eclipse, I made up the following routines:
const int use_precision = 100;
CGAL::Gmpfr convert(CGAL::Gmpq z)
{
CGAL::Gmpz num = z.numerator();
CGAL::Gmpz den = z.denominator();
CGAL::Gmpfr num_f(num);
CGAL::Gmpfr den_f(den);
return num_f/den_f;
}
CGAL::Gmpfr convert(Traits_2::CoordNT z)
{
Kernel::FT a0_val = z.a0();
Kernel::FT a1_val = z.a1();
Kernel::FT root_val = z.root();
CGAL::Gmpq a0_q = a0_val.exact();
CGAL::Gmpq a1_q = a1_val.exact();
CGAL::Gmpq root_q = root_val.exact();
CGAL::Gmpfr a0_f = convert(a0_q);
CGAL::Gmpfr a1_f = convert(a1_q);
CGAL::Gmpfr root_f = convert(root_q);
CGAL::Gmpfr res = a0_f + a1_f * root_f.sqrt(use_precision);
return res;
}
Point_2 convert(Point_2t p)
{
CGAL::Gmpfr xx = convert(p.x());
CGAL::Gmpfr yy = convert(p.y());
CGAL::Gmpq xx1 = xx;
CGAL::Gmpq yy1 = yy;
Kernel::FT xx2 = xx1;
Kernel::FT yy2 = yy1;
Point_2 pp(xx2, yy2);
return pp;
}
Essentially I convert the coordinates from Traits_2::CoordNT into the form
(*) a0 + a1 * sqrt(root)
with a0, a1, root from Kernel::FT (=rational field), then convert a0, a1, root into Gmpq rationals, these into Gmpfr with 100 decimals precision, then evaluate the expression (*) and convert back into Gmpq and then Kernel::FT. All conversions are (more or less) just done by assignments and automatic conversion by CGAL.
In my tests, this worked seemingly correct, but I am still not 100% sure, if, according to the CGAL definitions, the sqrt(root) expression in (*) always means the positive square-root.
I looked through the definition:
description of sqrt-extended Number type in CGAL
but even then I am not totally convinced, that only the positive value of sqrt(root) is taken.
So my question to those, who understand the CGAL system in this point fully:
Are my conversion routines above correct in assuming always the positive value of the root to be taken?
Yes, you are right. In CGAL Sqrt_extension
, in the expression a0+a1√(root)
, the square root is always positive or null.