【发布时间】:2021-04-17 19:06:40
【问题描述】:
在我的一个项目中,我曾经将坐标值从 Kernel::FT 转换为 CGAL::Gmpq 并返回。该代码不再使用与以前相同的内核选择进行编译,即
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
但是我尝试了另一种方法,但不确定它是否完全等同于前一种,所有编译都没有错误:
typedef CGAL::Cartesian< CGAL::Lazy_exact_nt<CGAL::Gmpq> > Kernel;
我的标题定义
// the following kernel gives no error
//typedef CGAL::Cartesian< CGAL::Lazy_exact_nt<CGAL::Gmpq> > Kernel;
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;
失败的代码
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, int use_precision)
{
Kernel::FT a0_val = z.a0();
Kernel::FT a1_val = z.a1();
Kernel::FT root_val = z.root();
//the following three lines give errors
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;
// the following two lines give errors
Kernel::FT xx2 = xx1;
Kernel::FT yy2 = yy1;
Point_2 pp(xx2, yy2);
return pp;
}
错误(前三个和后两个基本相同):
cgal.cpp:48:32: error: conversion from ‘CGAL::Lazy<CGAL::Interval_nt<false>, boost::multiprecision::number<boost::multiprecision::backends::gmp_rational>, CGAL::To_interval<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational> > >::ET {aka boost::multiprecision::number<boost::multiprecision::backends::gmp_rational>}’ to non-scalar type ‘CGAL::Gmpq’ requested
CGAL::Gmpq a0_q = a0_val.exact();
~~~~~~~~~~~~^~
cgal.cpp:49:32: error: conversion from ‘CGAL::Lazy<CGAL::Interval_nt<false>, boost::multiprecision::number<boost::multiprecision::backends::gmp_rational>, CGAL::To_interval<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational> > >::ET {aka boost::multiprecision::number<boost::multiprecision::backends::gmp_rational>}’ to non-scalar type ‘CGAL::Gmpq’ requested
CGAL::Gmpq a1_q = a1_val.exact();
~~~~~~~~~~~~^~
cgal.cpp:50:36: error: conversion from ‘CGAL::Lazy<CGAL::Interval_nt<false>, boost::multiprecision::number<boost::multiprecision::backends::gmp_rational>, CGAL::To_interval<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational> > >::ET {aka boost::multiprecision::number<boost::multiprecision::backends::gmp_rational>}’ to non-scalar type ‘CGAL::Gmpq’ requested
CGAL::Gmpq root_q = root_val.exact();
~~~~~~~~~~~~~~^~
cgal.cpp: In function ‘Point_2 convert(Point_2t)’:
cgal.cpp:71:19: error: conversion from ‘CGAL::Gmpq’ to non-scalar type ‘CGAL::Lazy_kernel_generic_base<CGAL::Simple_cartesian<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational> >, CGAL::Simple_cartesian<CGAL::Interval_nt<false> >, CGAL::Cartesian_converter<CGAL::Simple_cartesian<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational> >, CGAL::Simple_cartesian<CGAL::Interval_nt<false> > >, CGAL::Epeck>::FT {aka CGAL::Lazy_exact_nt<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational> >}’ requested
Kernel::FT xx2 = xx1;
^~~
cgal.cpp:72:19: error: conversion from ‘CGAL::Gmpq’ to non-scalar type ‘CGAL::Lazy_kernel_generic_base<CGAL::Simple_cartesian<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational> >, CGAL::Simple_cartesian<CGAL::Interval_nt<false> >, CGAL::Cartesian_converter<CGAL::Simple_cartesian<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational> >, CGAL::Simple_cartesian<CGAL::Interval_nt<false> > >, CGAL::Epeck>::FT {aka CGAL::Lazy_exact_nt<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational> >}’ requested
Kernel::FT yy2 = yy1;
似乎默认内核CGAL::Exact_predicates_exact_constructions_kernel 现在有一个与“boost-something”相关的坐标编号类型,这不再与CGAL::Gmpq 兼容。
鉴于我想使用与CGAL::Exact_predicates_exact_constructions_kernel 等效的最快内核,该问题的最佳解决方案是什么?
我应该切换到CGAL::Cartesian< CGAL::Lazy_exact_nt<CGAL::Gmpq> > 甚至是CGAL::Extended_cartesian< CGAL::Lazy_exact_nt<CGAL::Gmpq> >吗?
或者我可以设置一个特定的环境变量,以便 CGAL::Exact_predicates_exact_construction_kernel 默认使用 CGAL::Gmpq 而不是“boost-something”,前提是这不会让事情变慢?
或者我可以在 CGAL 5.2.1 中使用一些新引入的转换运算符/函数重写有问题的行。我现在不知道?
【问题讨论】:
-
为了更准确地了解 Marc 提出的最简单的解决方法,您可以在包含任何 CGAL 文件之前在 cpp 源中定义
#define CGAL_DO_NOT_USE_BOOST_MP,并在 cmake 级别设置CGAL_WITH_GMPXX=OFF。 -
感谢你们(Marc Glisse 和 sloriot)的建议 - 我可以通过提供编译标志 -DCGAL_DO_NOT_USE_BOOST_MP 使代码再次工作。我目前不知道如何设置 cmake 变量,因为我使用 qmake 项目设置(以及使用 CGAL 的仅标头设置)。 CGAL 是否从 CGAL::Gmpq 默认更改为 boost::rational 因为性能更好?
-
是的,性能更好(对于某些应用程序,不是全部),这也是未来向多线程迈出的有益一步。
标签: computational-geometry numeric cgal