Из CGAL В настоящее время я использую следующий пакет: Булевы операции над полигонами
Поскольку меня интересуют полигоны, которые могут иметь, кроме отрезков линии, в качестве ребер и окружностей сегменты, я используйте следующую сборку для моих базовых c typedefs:
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, а именно Point_2, который является Kernel :: Point_2 и который я назвал Point_2t, который это Черты_2 :: Точка_2.
Разница между ними состоит в том, что Point_2 имеет рациональные координаты x (), y (), тогда как Point_2t имеет координаты в Q (альфа), где Q обозначает рациональное поле, а альфа представляет собой квадрат- root рациональное число.
Или, иначе говоря, координаты 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 (root)
с a0, a1, root из Kernel :: FT (= рациональное поле), затем преобразовать a0, a1, root в рациональные числа Gmpq, в Gmpfr с точностью до 100 десятичных дробей, затем вычислить e xpression (*) и преобразовать обратно в Gmpq, а затем Kernel :: FT. Все преобразования (более или менее) просто выполняются с помощью заданий и автоматического c преобразования с помощью CGAL.
В моих тестах это работало, казалось бы, правильно, но я все еще не уверен на 100%, если, согласно В определениях CGAL выражение sqrt (root) в (*) всегда означает положительный квадрат- root.
Я просматривал определение:
описание sqrt- расширенный тип числа в CGAL
, но даже тогда я не полностью убежден, что принимается только положительное значение sqrt (root).
Так что мой вопрос к тем, кто полностью понимает систему CGAL в этом пункте:
Правильны ли мои приведенные выше процедуры преобразования при условии, что всегда принимается положительное значение root?