CGAL: Point on the line?

强颜欢笑 提交于 2019-12-08 08:13:10

问题


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?


回答1:


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.



来源:https://stackoverflow.com/questions/23938162/cgal-point-on-the-line

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!