我想对正多边形进行精确计算。为此,我编写了您在下面找到的代码。但表达式cos*cos
不会编译。显然,我使用的代数类型没有定义乘法。我想我将不得不尝试其他方法。目前似乎有两个候选人:
- RS显然提供了一些更高级的代数功能,CGAL 也支持它。但我在相关标题中没有看到乘法运算符,所以我怀疑它是否会按照我想要的方式进行乘法运算。
- leda::real似乎是代数实数的一种类型。我可能不得不重写我的代码,但应该可以实现类似的结果。也许我什至可以将
cos
在 CGAL 中计算的 I 转换为这样的leda::real
. LEDA 标头至少看起来有一个operator*
. LEDA 对我来说是免费的,但仍然是封闭源代码。而leda_real.h
CGAL 4.3 看起来很奇怪:它指的是leda_real
notleda::real
,所以它可能是为 LEDA 的过时版本编写的。它显然包括自己,这看起来毫无意义。
这些替代方案中的哪一个最适合构建能够描述任意n的常规n边形的精确 CGAL 内核?这些中的任何一个都有效吗?我还有另一种选择吗?
由于我的计算机上没有安装 RS 或 LEDA,所以在开始构建它们之前,我更喜欢有根据的意见,甚至可能为我的 Gentoo linux 编写安装说明(“ebuilds”)。
#include <string>
#include <iostream>
#include <sstream>
#include <vector>
//define CGAL_USE_RS
#include <CGAL/Gmpz.h>
#include <CGAL/Algebraic_kernel_d_1.h>
#include <CGAL/Algebraic_kernel_rs_gmpz_d_1.h>
#include <CGAL/Homogeneous.h>
#include <CGAL/Arr_segment_traits_2.h>
#include <CGAL/Arrangement_2.h>
#define DBG(x) std::cerr << x << std::endl
typedef CGAL::Gmpz ZZ;
// typedef CGAL::Algebraic_kernel_rs_gmpz_d_1 AK;
typedef CGAL::Algebraic_kernel_d_1<ZZ> AK;
typedef AK::Polynomial_1 Polynomial;
typedef AK::Algebraic_real_1 AA;
typedef AK::Coefficient Coeff;
typedef AK::Bound Bound;
typedef AK::Multiplicity_type Multiplicity;
typedef CGAL::Homogeneous<AK> Kernel;
typedef CGAL::Arr_segment_traits_2<Kernel> Traits;
typedef Kernel::Point_2 Point;
typedef Kernel::Segment_2 Segment;
typedef CGAL::Arrangement_2<Traits> Arrangement;
static unsigned run(unsigned short n) {
AK ak;
AK::Construct_algebraic_real_1 to_AA = ak.construct_algebraic_real_1_object();
AK::Solve_1 solve = ak.solve_1_object();
Polynomial x{CGAL::shift(Polynomial(1), 1)}, twox{2*x};
Polynomial a{1}, b{x};
for (unsigned short i = 2; i <= n; ++i) {
Polynomial c = twox*b - a;
a = b;
b = c;
}
std::vector<std::pair<AA, Multiplicity>> roots;
solve(b - 1, std::back_inserter(roots));
AA one{1}, cos{-2};
for (auto i = roots.begin(), e = roots.end(); i != e; ++i) {
AA cur = i->first;
if (cur < one && cur > cos)
cos = cur;
}
AA sin = CGAL::sqrt(to_AA(1) - cos*cos);
//DBG("sin="<<CGAL::to_double(sin)<<", cos="<<CGAL::to_double(cos));
return 0;
}
int main(int argc, char** argv) {
for (int i = 1; i < argc; ++i) {
unsigned short n;
std::istringstream(argv[i]) >> n;
std::cout << n << ": " << run(n) << std::endl;
}
return 0;
}