I've encountered a strange thing in CGAL. I have a line and a point that is supposed to be on this line. This code
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
int main( ) {
CGAL::Line_2<Kernel> l(0.2, 1.0, -1.4);
std::cout << l.has_on(CGAL::Point_2<Kernel>(-3.0, 2.0)) << std::endl;
std::cout << l.y_at_x(-3.0).exact() << std::endl;
return 0;
}
Produces output:
0
36028797018963967/18014398509481984
OK, maybe the Exact_predicates_exact_constructions_kernel
is not good enough... (WHY?)
I tried to use kernel defined with CGAL::Quotient
instead:
typedef CGAL::Quotient<CGAL::MP_Float> NT;
typedef CGAL::Cartesian<NT> Kernel;
int main( ) {
CGAL::Line_2<Kernel> l(0.2, 1.0, -1.4);
std::cout << l.has_on(CGAL::Point_2<Kernel>(-3.0, 2.0)) << std::endl;
std::cout << l.y_at_x(-3.0) << std::endl;
return 0;
}
And the result is even more mysterious to me:
0
2/1
Am I missing something or is it a bug?
When you construct the line from 0.2, two conversions happen. The string "0.2" is converted to a double by the compiler. Then, this double is converted to the number type of the kernel (an exact rational in this case).
The problem is that the conversion of 0.2 to double is not exact, since 0.2 is a rational that is not representable by a floating-point value, so, some inexactness is introduced. CGAL cannot do anything about this.
If you need to represent 0.2 exactly, you need to use something like :
CGAL::Line_2<Kernel> l(NT(2)/NT(10), 1.0, NT(-14)/NT(10));
Alternatively, scale your problem by a power of ten so that all your coordinates becomes integers.
It is also possible that some rational number types have the ability to construct directly from a string representing a rational number without any rounding, but I don't think CGAL::Quotient<MP_Float>
can.