【问题标题】:Converting coordinate values in CGAL在 CGAL 中转换坐标值
【发布时间】:2020-03-21 15:13:08
【问题描述】:

来自 CGAL,我目前正在使用以下软件包: Boolean operations on polygons

由于我对多边形感兴趣,除了线段之外,边也可以是圆段,因此我对基本 typedef 使用以下构建:

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;

如上面的类型所示,我有两种点类型,即 Point_2,即 Kernel::Point_2,以及我称之为 Point_2t,即 Traits_2::Point_2。

它们之间的区别在于,Point_2 具有有理坐标 x(), y(),而 Point_2t 具有 Q(alpha) 中的坐标,其中 Q 代表有理域,而 alpha 是有理数的平方根。

或者,换句话说,Point_2 的坐标在 Kernel::FT 中,而 Point_2t 的坐标在 Traits_2::CoordNT 中。

所以从 Point_2 转换到 Point_2t 没有问题,但我还必须从 Point_2t 转换到 Point_2,希望以一种能够控制丢失精度的方式。

阅读文档并使用eclipse的自动完成功能,我编写了以下例程:

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;
}

基本上我将坐标从 Traits_2::CoordNT 转换成表格

(*) a0 + a1 * sqrt(根)

使用 a0, a1, root from Kernel::FT (=rational field),然后将 a0, a1, root 转换为 Gmpq 有理数,这些转换为 Gmpfr,精度为 100 位小数,然后计算表达式 (*) 并转换回Gmpq 然后是 Kernel::FT。所有转换(或多或少)都是通过分配完成的,由 CGAL 自动转换。

在我的测试中,这似乎是正确的,但我仍然不能 100% 确定,根据 CGAL 定义,(*) 中的 sqrt(root) 表达式是否始终表示正平方根。

我查看了定义:

description of sqrt-extended Number type in CGAL

但即便如此,我也不完全相信,只取 sqrt(root) 的正值。

所以我想问那些在这一点上完全理解 CGAL 系统的人:

我上面的转换例程是否总是正确地假设要取的根的正值?

【问题讨论】:

  • 我看到你是个数学家,我其实很惊讶:sqrt 根函数(注明)总是非负根,不是吗?
  • 令人惊讶的是,我从来没有在我所有的数学工作中使用这个约定——做代数几何时,当看到 sqrt(z) 时,我更倾向于想到黎曼曲面,但你当然是对的。然而,在研究 CGAL 文档时,我开始认为,由于某种原因,sqrt(root) 可能被认为是负数,具体取决于存在的标志,但我在所有这些嵌套的“概念”和“特征类”中找不到和所有这一切。非常感谢您清理问题!

标签: computational-geometry numeric cgal


【解决方案1】:

是的,你是对的。在CGAL Sqrt_extension 中,在表达式a0+a1√(root) 中,平方根始终为正或空。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多