From b64818cc994115d46a050a446bdc512091e22ae0 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 18 May 2022 10:08:10 +0300 Subject: [PATCH 001/105] Drawing arrangement (1st rev.) and basic cleanup conic traits --- .../Arrangement_on_surface_2/CMakeLists.txt | 6 +- .../Arrangement_on_surface_2/draw_arr.cpp | 25 + .../CGAL/Arr_geometry_traits/Conic_arc_2.h | 1658 +++++++---------- .../include/CGAL/draw_arrangement_2.h | 94 + 4 files changed, 842 insertions(+), 941 deletions(-) create mode 100644 Arrangement_on_surface_2/examples/Arrangement_on_surface_2/draw_arr.cpp create mode 100644 Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/CMakeLists.txt b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/CMakeLists.txt index 7b6e319643d..26f23e6c53a 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/CMakeLists.txt +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.1...3.23) project(Arrangement_on_surface_2_Examples) -find_package(CGAL REQUIRED COMPONENTS Core) +find_package(CGAL REQUIRED COMPONENTS Core Qt5) # create a target per cppfile file( @@ -14,3 +14,7 @@ file( foreach(cppfile ${cppfiles}) create_single_source_cgal_program("${cppfile}") endforeach() + +if(CGAL_Qt5_FOUND) + target_link_libraries(draw_arr PUBLIC CGAL::CGAL_Basic_viewer) +endif() diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/draw_arr.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/draw_arr.cpp new file mode 100644 index 00000000000..ba20b15dc92 --- /dev/null +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/draw_arr.cpp @@ -0,0 +1,25 @@ +#include +#include +#include +#include + +using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel; +using Traits = CGAL::Arr_segment_traits_2; +using Point = Traits::Point_2; +using X_monotone_curve = Traits::X_monotone_curve_2; +using Arrangement_2 = CGAL::Arrangement_2; + +int main() { + Traits traits; + Arrangement_2 arr(&traits); + auto ctr_xcv = traits.construct_x_monotone_curve_2_object(); + + CGAL::insert(arr, ctr_xcv(Point(-1,-1), Point(1,-1))); + CGAL::insert(arr, ctr_xcv(Point(1,-1), Point(1,1))); + CGAL::insert(arr, ctr_xcv(Point(1,1), Point(-1,1))); + CGAL::insert(arr, ctr_xcv(Point(-1,1), Point(-1,-1))); + + CGAL::draw(arr); + + return EXIT_SUCCESS; +} diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h index 15bee1cd34b..e02e46e700a 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h @@ -8,7 +8,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Ron Wein +// Author(s): Ron Wein #ifndef CGAL_CONIC_ARC_2_H #define CGAL_CONIC_ARC_2_H @@ -28,9 +28,7 @@ namespace CGAL { - -/*! - * Representation of a conic arc -- a bounded segment that lies on a conic +/*! Representation of a conic arc -- a bounded segment that lies on a conic * curve, the loci of all points satisfying the equation: * r*x^2 + s*y^2 + t*xy + u*x + v*y +w = 0 * @@ -44,14 +42,12 @@ namespace CGAL { * rational and algebraic types. */ -template -class _Conic_arc_2 -{ +template +class _Conic_arc_2 { public: - - typedef Rat_kernel_ Rat_kernel; - typedef Alg_kernel_ Alg_kernel; - typedef Nt_traits_ Nt_traits; + typedef RatKernel Rat_kernel; + typedef AlgKernel Alg_kernel; + typedef NtTraits Nt_traits; typedef _Conic_arc_2 Self; @@ -67,26 +63,24 @@ public: typedef _Conic_point_2 Conic_point_2; protected: + Integer m_r; // + Integer m_s; // The coefficients of the supporting conic curve: + Integer m_t; // + Integer m_u; // + Integer m_v; // r*x^2 + s*y^2 + t*xy + u*x + v*y +w = 0 . + Integer m_w; // - Integer _r; // - Integer _s; // The coefficients of the supporting conic curve: - Integer _t; // - Integer _u; // - Integer _v; // r*x^2 + s*y^2 + t*xy + u*x + v*y +w = 0 . - Integer _w; // + Orientation m_orient; // The orientation of the conic. - Orientation _orient; // The orientation of the conic. - - // Bit masks for the _info field. - enum - { + // Bit masks for the m_info field. + enum { IS_VALID = 1, IS_FULL_CONIC = 2 }; - int _info; // Does the arc represent a full conic curve. - Conic_point_2 _source; // The source of the arc (if not a full curve). - Conic_point_2 _target; // The target of the arc (if not a full curve). + int m_info; // Does the arc represent a full conic curve. + Conic_point_2 m_source; // The source of the arc (if not a full curve). + Conic_point_2 m_target; // The target of the arc (if not a full curve). /*! \struct * For arcs whose base is a hyperbola we store the axis (a*x + b*y + c = 0) @@ -96,63 +90,58 @@ protected: * structure two store the coefficients of the line supporting this segment. * In this case we set the side field to be ZERO. */ - struct Extra_data - { - Algebraic a; - Algebraic b; - Algebraic c; - Sign side; + struct Extra_data { + Algebraic a; + Algebraic b; + Algebraic c; + Sign side; }; - Extra_data *_extra_data_P; // The extra data stored with the arc - // (may be nullptr). + Extra_data* m_extra_data; // The extra data stored with the arc + // (may be nullptr). public: - /// \name Construction and destruction functions. //@{ /*! * Default constructor. */ - _Conic_arc_2 () : - _r(0), _s(0), _t(0), _u(0), _v(0), _w(0), - _orient (COLLINEAR), - _info (0), - _extra_data_P (nullptr) + _Conic_arc_2() : + m_r(0), m_s(0), m_t(0), m_u(0), m_v(0), m_w(0), + m_orient(COLLINEAR), + m_info(0), + m_extra_data(nullptr) {} - /*! - * Copy constructor. + /*! Copy constructor. * \param arc The copied arc. */ - _Conic_arc_2 (const Self& arc) : - _r(arc._r), _s(arc._s), _t(arc._t), _u(arc._u), _v(arc._v), _w(arc._w), - _orient (arc._orient), - _info (arc._info), - _source(arc._source), - _target(arc._target) + _Conic_arc_2(const Self& arc) : + m_r(arc.m_r), m_s(arc.m_s), m_t(arc.m_t), + m_u(arc.m_u), m_v(arc.m_v), m_w(arc.m_w), + m_orient(arc.m_orient), + m_info(arc.m_info), + m_source(arc.m_source), + m_target(arc.m_target) { - if (arc._extra_data_P != nullptr) - _extra_data_P = new Extra_data (*(arc._extra_data_P)); - else - _extra_data_P = nullptr; + m_extra_data = (arc.m_extra_data != nullptr) ? + new Extra_data(*(arc.m_extra_data)) : nullptr; } - /*! - * Construct a conic arc which is the full conic: + /*! Construct a conic arc which is the full conic: * C: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0 * \pre The conic C must be an ellipse (so 4rs - t^2 > 0). */ - _Conic_arc_2 (const Rational& r, const Rational& s, const Rational& t, - const Rational& u, const Rational& v, const Rational& w) : - _extra_data_P (nullptr) + _Conic_arc_2(const Rational& r, const Rational& s, const Rational& t, + const Rational& u, const Rational& v, const Rational& w) : + m_extra_data(nullptr) { // Make sure the given curve is an ellipse (4rs - t^2 should be positive). - CGAL_precondition (CGAL::sign (4*r*s - t*t) == POSITIVE); + CGAL_precondition(CGAL::sign(4*r*s - t*t) == POSITIVE); // Set the arc to be the full conic (and compute the orientation). - Rational rat_coeffs [6]; + Rational rat_coeffs[6]; rat_coeffs[0] = r; rat_coeffs[1] = s; @@ -161,11 +150,10 @@ public: rat_coeffs[4] = v; rat_coeffs[5] = w; - _set_full (rat_coeffs, true); + set_full(rat_coeffs, true); } - /*! - * Construct a conic arc which lies on the conic: + /*! Construct a conic arc which lies on the conic: * C: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0 * \param orient The orientation of the arc (clockwise or counterclockwise). * \param source The source point. @@ -173,21 +161,21 @@ public: * \pre The source and the target must be on the conic boundary and must * not be the same. */ - _Conic_arc_2 (const Rational& r, const Rational& s, const Rational& t, - const Rational& u, const Rational& v, const Rational& w, - const Orientation& orient, - const Point_2& source, const Point_2& target) : - _orient (orient), - _source (source), - _target (target), - _extra_data_P (nullptr) + _Conic_arc_2(const Rational& r, const Rational& s, const Rational& t, + const Rational& u, const Rational& v, const Rational& w, + const Orientation& orient, + const Point_2& source, const Point_2& target) : + m_orient(orient), + m_source(source), + m_target(target), + m_extra_data(nullptr) { // Make sure that the source and the taget are not the same. - CGAL_precondition (Alg_kernel().compare_xy_2_object() (source, - target) != EQUAL); + CGAL_precondition(Alg_kernel().compare_xy_2_object()(source, target) != + EQUAL); // Set the arc properties (no need to compute the orientation). - Rational rat_coeffs [6]; + Rational rat_coeffs[6]; rat_coeffs[0] = r; rat_coeffs[1] = s; @@ -196,20 +184,20 @@ public: rat_coeffs[4] = v; rat_coeffs[5] = w; - _set (rat_coeffs); + set(rat_coeffs); } /*! Construct a segment conic arc from two endpoints. * \param source the source point with rational coordinates. */ _Conic_arc_2(const Point_2& source, const Point_2& target) : - _orient (COLLINEAR), - _info(static_cast(IS_VALID)), - _source(source), - _target(target), - _extra_data_P(nullptr) + m_orient(COLLINEAR), + m_info(static_cast(IS_VALID)), + m_source(source), + m_target(target), + m_extra_data(nullptr) { - CGAL_precondition(Alg_kernel().compare_xy_2_object()(_source, _target) != + CGAL_precondition(Alg_kernel().compare_xy_2_object()(m_source, m_target) != EQUAL); // Compose the equation of the underlying line. @@ -221,57 +209,55 @@ public: // The supporting line is A*x + B*y + C = 0, where: // A = y2 - y1, B = x1 - x2, C = x2*y1 - x1*y2 // We use the extra data field to store the equation of this line. - _extra_data_P = new Extra_data; - _extra_data_P->a = y2 - y1; - _extra_data_P->b = x1 - x2; - _extra_data_P->c = x2*y1 - x1*y2; - _extra_data_P->side = ZERO; + m_extra_data = new Extra_data; + m_extra_data->a = y2 - y1; + m_extra_data->b = x1 - x2; + m_extra_data->c = x2*y1 - x1*y2; + m_extra_data->side = ZERO; } /*! * Construct a conic arc from the given line segment. * \param seg The line segment with rational endpoints. */ - _Conic_arc_2 (const Rat_segment_2& seg) : - _orient (COLLINEAR), - _extra_data_P (nullptr) + _Conic_arc_2(const Rat_segment_2& seg) : + m_orient(COLLINEAR), + m_extra_data (nullptr) { // Set the source and target. - Rat_kernel ker; - Rat_point_2 source = ker.construct_vertex_2_object() (seg, 0); - Rat_point_2 target = ker.construct_vertex_2_object() (seg, 1); - Rational x1 = source.x(); - Rational y1 = source.y(); - Rational x2 = target.x(); - Rational y2 = target.y(); - Nt_traits nt_traits; + Rat_kernel ker; + Rat_point_2 source = ker.construct_vertex_2_object()(seg, 0); + Rat_point_2 target = ker.construct_vertex_2_object()(seg, 1); + Rational x1 = source.x(); + Rational y1 = source.y(); + Rational x2 = target.x(); + Rational y2 = target.y(); + Nt_traits nt_traits; - _source = Point_2 (nt_traits.convert (x1), nt_traits.convert (y1)); - _target = Point_2 (nt_traits.convert (x2), nt_traits.convert (y2)); + m_source = Point_2(nt_traits.convert(x1), nt_traits.convert(y1)); + m_target = Point_2(nt_traits.convert(x2), nt_traits.convert(y2)); // Make sure that the source and the taget are not the same. - CGAL_precondition (Alg_kernel().compare_xy_2_object() (_source, - _target) != EQUAL); + CGAL_precondition(Alg_kernel().compare_xy_2_object()(m_source, m_target) != + EQUAL); // The supporting conic is r=s=t=0, and u*x + v*y + w = 0 should hold // for both the source (x1,y1) and the target (x2, y2). - const Rational _zero (0); - const Rational _one (1); - Rational rat_coeffs [6]; + const Rational zero(0); + const Rational one(1); + Rational rat_coeffs[6]; - rat_coeffs[0] = _zero; - rat_coeffs[1] = _zero; - rat_coeffs[2] = _zero; + rat_coeffs[0] = zero; + rat_coeffs[1] = zero; + rat_coeffs[2] = zero; - if (CGAL::compare (x1, x2) == EQUAL) - { + if (CGAL::compare(x1, x2) == EQUAL) { // The supporting conic is a vertical line, of the form x = CONST. - rat_coeffs[3] = _one; - rat_coeffs[4] = _zero; + rat_coeffs[3] = one; + rat_coeffs[4] = zero; rat_coeffs[5] = -x1; } - else - { + else { // The supporting line is A*x + B*y + C = 0, where: // // A = y2 - y1, B = x1 - x2, C = x2*y1 - x1*y2 @@ -282,47 +268,45 @@ public: } // Set the arc properties (no need to compute the orientation). - _set (rat_coeffs); + set(rat_coeffs); } - /*! - * Set a circular arc that corresponds to a full circle. + /*! Set a circular arc that corresponds to a full circle. * \param circ The circle (with rational center and rational squared radius). */ - _Conic_arc_2 (const Rat_circle_2& circ) : - _orient (CLOCKWISE), - _extra_data_P (nullptr) + _Conic_arc_2(const Rat_circle_2& circ) : + m_orient(CLOCKWISE), + m_extra_data(nullptr) { // Get the circle properties. - Rat_kernel ker; - Rat_point_2 center = ker.construct_center_2_object() (circ); - Rational x0 = center.x(); - Rational y0 = center.y(); - Rational R_sqr = ker.compute_squared_radius_2_object() (circ); + Rat_kernel ker; + Rat_point_2 center = ker.construct_center_2_object()(circ); + Rational x0 = center.x(); + Rational y0 = center.y(); + Rational R_sqr = ker.compute_squared_radius_2_object()(circ); // Produce the correponding conic: if the circle center is (x0,y0) // and its squared radius is R^2, that its equation is: // x^2 + y^2 - 2*x0*x - 2*y0*y + (x0^2 + y0^2 - R^2) = 0 // Note that this equation describes a curve with a negative (clockwise) // orientation. - const Rational _zero (0); - const Rational _one (1); - const Rational _minus_two (-2); - Rational rat_coeffs [6]; + const Rational zero(0); + const Rational one(1); + const Rational minus_two(-2); + Rational rat_coeffs[6]; - rat_coeffs[0] = _one; - rat_coeffs[1] = _one; - rat_coeffs[2] = _zero; - rat_coeffs[3] = _minus_two*x0; - rat_coeffs[4] = _minus_two*y0; + rat_coeffs[0] = one; + rat_coeffs[1] = one; + rat_coeffs[2] = zero; + rat_coeffs[3] = minus_two*x0; + rat_coeffs[4] = minus_two*y0; rat_coeffs[5] = x0*x0 + y0*y0 - R_sqr; // Set the arc to be the full conic (no need to compute the orientation). - _set_full (rat_coeffs, false); + set_full(rat_coeffs, false); } - /*! - * Set a circular arc that lies on the given circle: + /*! Set a circular arc that lies on the given circle: * C: (x - x0)^2 + (y - y0)^2 = R^2 * \param orient The orientation of the circle. * \param source The source point. @@ -330,62 +314,60 @@ public: * \pre The source and the target must be on the conic boundary and must * not be the same. */ - _Conic_arc_2 (const Rat_circle_2& circ, - const Orientation& orient, - const Point_2& source, const Point_2& target) : - _orient(orient), - _source(source), - _target(target), - _extra_data_P (nullptr) + _Conic_arc_2(const Rat_circle_2& circ, + const Orientation& orient, + const Point_2& source, const Point_2& target) : + m_orient(orient), + m_source(source), + m_target(target), + m_extra_data(nullptr) { // Make sure that the source and the taget are not the same. - CGAL_precondition (Alg_kernel().compare_xy_2_object() (source, - target) != EQUAL); - CGAL_precondition (orient != COLLINEAR); + CGAL_precondition(Alg_kernel().compare_xy_2_object()(source, target) != + EQUAL); + CGAL_precondition(orient != COLLINEAR); // Get the circle properties. - Rat_kernel ker; - Rat_point_2 center = ker.construct_center_2_object() (circ); - Rational x0 = center.x(); - Rational y0 = center.y(); - Rational R_sqr = ker.compute_squared_radius_2_object() (circ); + Rat_kernel ker; + Rat_point_2 center = ker.construct_center_2_object()(circ); + Rational x0 = center.x(); + Rational y0 = center.y(); + Rational R_sqr = ker.compute_squared_radius_2_object()(circ); // Produce the correponding conic: if the circle center is (x0,y0) // and it squared radius is R^2, that its equation is: // x^2 + y^2 - 2*x0*x - 2*y0*y + (x0^2 + y0^2 - R^2) = 0 // Since this equation describes a curve with a negative (clockwise) - // orientation, we multiply it by -1 if nece_Conic_arc_2 ssary to obtain a positive - // (counterclockwise) orientation. - const Rational _zero (0); - Rational rat_coeffs[6]; + // orientation, we multiply it by -1 if nece_Conic_arc_2 ssary to obtain a + // positive (counterclockwise) orientation. + const Rational zero(0); + Rational rat_coeffs[6]; - if (_orient == COUNTERCLOCKWISE) - { - const Rational _minus_one (-1); - const Rational _two (2); + if (m_orient == COUNTERCLOCKWISE) { + const Rational _minus_one(-1); + const Rational two(2); rat_coeffs[0] = _minus_one; rat_coeffs[1] = _minus_one; - rat_coeffs[2] = _zero; - rat_coeffs[3] = _two*x0; - rat_coeffs[4] = _two*y0; + rat_coeffs[2] = zero; + rat_coeffs[3] = two*x0; + rat_coeffs[4] = two*y0; rat_coeffs[5] = R_sqr - x0*x0 - y0*y0; } - else - { - const Rational _one (1); - const Rational _minus_two (-2); + else { + const Rational one(1); + const Rational minus_two(-2); - rat_coeffs[0] = _one; - rat_coeffs[1] = _one; - rat_coeffs[2] = _zero; - rat_coeffs[3] = _minus_two*x0; - rat_coeffs[4] = _minus_two*y0; + rat_coeffs[0] = one; + rat_coeffs[1] = one; + rat_coeffs[2] = zero; + rat_coeffs[3] = minus_two*x0; + rat_coeffs[4] = minus_two*y0; rat_coeffs[5] = x0*x0 + y0*y0 - R_sqr; } // Set the arc properties (no need to compute the orientation). - _set (rat_coeffs); + set(rat_coeffs); } /*! @@ -395,63 +377,61 @@ public: * \param p3 The arc target. * \pre The three points must not be collinear. */ - _Conic_arc_2 (const Rat_point_2& p1, - const Rat_point_2& p2, - const Rat_point_2& p3): - _extra_data_P (nullptr) + _Conic_arc_2(const Rat_point_2& p1, const Rat_point_2& p2, + const Rat_point_2& p3): + m_extra_data(nullptr) { // Set the source and target. - Rational x1 = p1.x(); - Rational y1 = p1.y(); - Rational x2 = p2.x(); - Rational y2 = p2.y(); - Rational x3 = p3.x(); - Rational y3 = p3.y(); - Nt_traits nt_traits; + Rational x1 = p1.x(); + Rational y1 = p1.y(); + Rational x2 = p2.x(); + Rational y2 = p2.y(); + Rational x3 = p3.x(); + Rational y3 = p3.y(); + Nt_traits nt_traits; - _source = Point_2 (nt_traits.convert (x1), nt_traits.convert (y1)); - _target = Point_2 (nt_traits.convert (x3), nt_traits.convert (y3)); + m_source = Point_2(nt_traits.convert (x1), nt_traits.convert(y1)); + m_target = Point_2(nt_traits.convert (x3), nt_traits.convert(y3)); // Make sure that the source and the taget are not the same. - CGAL_precondition (Alg_kernel().compare_xy_2_object() (_source, - _target) != EQUAL); + CGAL_precondition(Alg_kernel().compare_xy_2_object()(m_source, m_target) != + EQUAL); // Compute the lines: A1*x + B1*y + C1 = 0, // and: A2*x + B2*y + C2 = 0, // where: - const Rational _two = 2; + const Rational two = 2; - const Rational A1 = _two*(x1 - x2); - const Rational B1 = _two*(y1 - y2); - const Rational C1 = y2*y2 - y1*y1 + x2*x2 - x1*x1; + const Rational A1 = two*(x1 - x2); + const Rational B1 = two*(y1 - y2); + const Rational C1 = y2*y2 - y1*y1 + x2*x2 - x1*x1; - const Rational A2 = _two*(x2 - x3); - const Rational B2 = _two*(y2 - y3); - const Rational C2 = y3*y3 - y2*y2 + x3*x3 - x2*x2; + const Rational A2 = two*(x2 - x3); + const Rational B2 = two*(y2 - y3); + const Rational C2 = y3*y3 - y2*y2 + x3*x3 - x2*x2; // Compute the coordinates of the intersection point between the // two lines, given by (Nx / D, Ny / D), where: - const Rational Nx = B1*C2 - B2*C1; - const Rational Ny = A2*C1 - A1*C2; - const Rational D = A1*B2 - A2*B1; + const Rational Nx = B1*C2 - B2*C1; + const Rational Ny = A2*C1 - A1*C2; + const Rational D = A1*B2 - A2*B1; // Make sure the three points are not collinear. - const bool points_collinear = (CGAL::sign (D) == ZERO); + const bool points_collinear = (CGAL::sign(D) == ZERO); - if (points_collinear) - { - _info = 0; // Inavlid arc. + if (points_collinear) { + m_info = 0; // Inavlid arc. return; } // The equation of the underlying circle is given by: - Rational rat_coeffs[6]; + Rational rat_coeffs[6]; rat_coeffs[0] = D*D; rat_coeffs[1] = D*D; rat_coeffs[2] = 0; - rat_coeffs[3] = -_two*D*Nx; - rat_coeffs[4] = -_two*D*Ny; + rat_coeffs[3] = -two*D*Nx; + rat_coeffs[4] = -two*D*Ny; rat_coeffs[5] = Nx*Nx + Ny*Ny - ((D*x2 - Nx)*(D*x2 - Nx) + (D*y2 - Ny)*(D*y2 - Ny)); @@ -459,72 +439,65 @@ public: // the source and the target points, the orientation is positive (going // counterclockwise). // Otherwise, it is negative (going clockwise). - Alg_kernel ker; + Alg_kernel ker; typename Alg_kernel::Orientation_2 orient_f = ker.orientation_2_object(); + Point_2 p_mid = Point_2(nt_traits.convert(x2), nt_traits.convert(y2)); - Point_2 p_mid = Point_2 (nt_traits.convert (x2), nt_traits.convert (y2)); - - if (orient_f(_source, p_mid, _target) == LEFT_TURN) - _orient = COUNTERCLOCKWISE; - else - _orient = CLOCKWISE; + m_orient = (orient_f(m_source, p_mid, m_target) == LEFT_TURN) ? + COUNTERCLOCKWISE : CLOCKWISE; // Set the arc properties (no need to compute the orientation). - _set (rat_coeffs); + set(rat_coeffs); } - /*! - * Construct a conic arc from the given five points, specified by the + /*! Construct a conic arc from the given five points, specified by the * points p1, p2, p3, p4 and p5. * \param p1 The source point of the given arc. * \param p2,p3,p4 Points lying on the conic arc, between p1 and p5. * \param p5 The target point of the given arc. * \pre No three points are collinear. */ - _Conic_arc_2 (const Rat_point_2& p1, - const Rat_point_2& p2, - const Rat_point_2& p3, - const Rat_point_2& p4, - const Rat_point_2& p5) : - _extra_data_P(nullptr) + _Conic_arc_2(const Rat_point_2& p1, const Rat_point_2& p2, + const Rat_point_2& p3, const Rat_point_2& p4, + const Rat_point_2& p5) : + m_extra_data(nullptr) { // Make sure that no three points are collinear. - Rat_kernel ker; + Rat_kernel ker; typename Rat_kernel::Orientation_2 orient_f = ker.orientation_2_object(); - const bool point_collinear = - (orient_f (p1, p2, p3) == COLLINEAR || - orient_f (p1, p2, p4) == COLLINEAR || - orient_f (p1, p2, p5) == COLLINEAR || - orient_f (p1, p3, p4) == COLLINEAR || - orient_f (p1, p3, p5) == COLLINEAR || - orient_f (p1, p4, p5) == COLLINEAR || - orient_f (p2, p3, p4) == COLLINEAR || - orient_f (p2, p3, p5) == COLLINEAR || - orient_f (p2, p4, p5) == COLLINEAR || - orient_f (p3, p4, p5) == COLLINEAR); + const bool point_collinear = + (orient_f(p1, p2, p3) == COLLINEAR || + orient_f(p1, p2, p4) == COLLINEAR || + orient_f(p1, p2, p5) == COLLINEAR || + orient_f(p1, p3, p4) == COLLINEAR || + orient_f(p1, p3, p5) == COLLINEAR || + orient_f(p1, p4, p5) == COLLINEAR || + orient_f(p2, p3, p4) == COLLINEAR || + orient_f(p2, p3, p5) == COLLINEAR || + orient_f(p2, p4, p5) == COLLINEAR || + orient_f(p3, p4, p5) == COLLINEAR); - if (point_collinear) - { - _info = 0; // Inavlid arc. + if (point_collinear) { + m_info = 0; // Inavlid arc. return; } // Set the source and target. - Rational x1 = p1.x(); - Rational y1 = p1.y(); - Rational x5 = p5.x(); - Rational y5 = p5.y(); - Nt_traits nt_traits; + Rational x1 = p1.x(); + Rational y1 = p1.y(); + Rational x5 = p5.x(); + Rational y5 = p5.y(); + Nt_traits nt_traits; - _source = Point_2 (nt_traits.convert (x1), nt_traits.convert (y1)); - _target = Point_2 (nt_traits.convert (x5), nt_traits.convert (y5)); + m_source = Point_2(nt_traits.convert(x1), nt_traits.convert(y1)); + m_target = Point_2(nt_traits.convert(x5), nt_traits.convert(y5)); // Set a conic curve that passes through the five given point. - typename Rat_kernel::Conic_2 temp_conic; - Rational rat_coeffs [6]; + typename Rat_kernel::Conic_2 temp_conic; + Rational rat_coeffs[6]; - temp_conic.set (p1, p2, p3, p4, p5); + temp_conic.set(p1, p2, p3, p4, p5); // Get the conic coefficients. rat_coeffs[0] = temp_conic.r(); @@ -538,43 +511,37 @@ public: // with the source and the target points, the orientation is positive // (going counterclockwise). // Otherwise, it is negative (going clockwise). - const Orientation turn = orient_f(p1, p2, p5); + const Orientation turn = orient_f(p1, p2, p5); - if (turn == LEFT_TURN) - { - _orient = COUNTERCLOCKWISE; - CGAL_precondition (orient_f(p1, p3, p5) == LEFT_TURN && - orient_f(p1, p4, p5) == LEFT_TURN); + if (turn == LEFT_TURN) { + m_orient = COUNTERCLOCKWISE; + CGAL_precondition(orient_f(p1, p3, p5) == LEFT_TURN && + orient_f(p1, p4, p5) == LEFT_TURN); } - else - { - _orient = CLOCKWISE; - CGAL_precondition (orient_f(p1, p3, p5) != LEFT_TURN && - orient_f(p1, p4, p5) != LEFT_TURN); + else { + m_orient = CLOCKWISE; + CGAL_precondition(orient_f(p1, p3, p5) != LEFT_TURN && + orient_f(p1, p4, p5) != LEFT_TURN); } // Set the arc properties (no need to compute the orientation). - _set (rat_coeffs); + set(rat_coeffs); // Make sure that all midpoints are strictly between the // source and the target. - Point_2 mp2 = Point_2 (nt_traits.convert (p2.x()), - nt_traits.convert (p2.y())); - Point_2 mp3 = Point_2 (nt_traits.convert (p3.x()), - nt_traits.convert (p3.y())); - Point_2 mp4 = Point_2 (nt_traits.convert (p4.x()), - nt_traits.convert (p4.y())); + Point_2 mp2 = Point_2(nt_traits.convert(p2.x()), nt_traits.convert(p2.y())); + Point_2 mp3 = Point_2(nt_traits.convert(p3.x()), nt_traits.convert(p3.y())); + Point_2 mp4 = Point_2(nt_traits.convert(p4.x()), nt_traits.convert(p4.y())); - if (! _is_strictly_between_endpoints (mp2) || - ! _is_strictly_between_endpoints (mp3) || - ! _is_strictly_between_endpoints (mp4)) + if (! is_strictly_between_endpoints(mp2) || + ! is_strictly_between_endpoints(mp3) || + ! is_strictly_between_endpoints(mp4)) { - _info = 0; // Inalvid arc. + m_info = 0; // Inalvid arc. } } - /*! - * Construct a conic arc which lies on the conic: + /*! Construct a conic arc which lies on the conic: * C: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0 * The source and the target are specified by the intersection of the * conic with: @@ -584,23 +551,23 @@ public: * coordinates. The actual intersection points that best fits the source * (or the target) will be selected. */ - _Conic_arc_2 (const Rational& r, const Rational& s, const Rational& t, - const Rational& u, const Rational& v, const Rational& w, - const Orientation& orient, - const Point_2& app_source, - const Rational& r_1, const Rational& s_1, const Rational& t_1, - const Rational& u_1, const Rational& v_1, const Rational& w_1, - const Point_2& app_target, - const Rational& r_2, const Rational& s_2, const Rational& t_2, - const Rational& u_2, const Rational& v_2, const Rational& w_2): - _orient(orient), - _extra_data_P(nullptr) + _Conic_arc_2(const Rational& r, const Rational& s, const Rational& t, + const Rational& u, const Rational& v, const Rational& w, + const Orientation& orient, + const Point_2& app_source, + const Rational& r_1, const Rational& s_1, const Rational& t_1, + const Rational& u_1, const Rational& v_1, const Rational& w_1, + const Point_2& app_target, + const Rational& r_2, const Rational& s_2, const Rational& t_2, + const Rational& u_2, const Rational& v_2, const Rational& w_2): + m_orient(orient), + m_extra_data(nullptr) { // Create the integer coefficients of the base conic. - Rational rat_coeffs [6]; - Nt_traits nt_traits; - Integer base_coeffs[6]; - int deg_base; + Rational rat_coeffs [6]; + Nt_traits nt_traits; + Integer base_coeffs[6]; + int deg_base; rat_coeffs[0] = r; rat_coeffs[1] = s; @@ -609,38 +576,35 @@ public: rat_coeffs[4] = v; rat_coeffs[5] = w; - nt_traits.convert_coefficients (rat_coeffs, rat_coeffs + 6, - base_coeffs); + nt_traits.convert_coefficients(rat_coeffs, rat_coeffs + 6, base_coeffs); - if (CGAL::sign (base_coeffs[0]) == ZERO && - CGAL::sign (base_coeffs[1]) == ZERO && - CGAL::sign (base_coeffs[2]) == ZERO) + if (CGAL::sign(base_coeffs[0]) == ZERO && + CGAL::sign(base_coeffs[1]) == ZERO && + CGAL::sign(base_coeffs[2]) == ZERO) { deg_base = 1; } - else - { + else { deg_base = 2; } // Compute the endpoints. - Rational aux_rat_coeffs [6]; - Integer aux_coeffs[6]; - int deg_aux; - Algebraic xs[4]; - int n_xs; - Algebraic ys[4]; - int n_ys; - int i, j; - Algebraic val; - bool found; - double dx, dy; - double curr_dist; - double min_dist = -1; - int k; + Rational aux_rat_coeffs [6]; + Integer aux_coeffs[6]; + int deg_aux; + Algebraic xs[4]; + int n_xs; + Algebraic ys[4]; + int n_ys; + int i, j; + Algebraic val; + bool found; + double dx, dy; + double curr_dist; + double min_dist = -1; + int k; - for (k = 1; k <= 2; k++) - { + for (k = 1; k <= 2; ++k) { // Get the integer coefficients of the k'th auxiliary conic curve. aux_rat_coeffs[0] = (k == 1) ? r_1 : r_2; aux_rat_coeffs[1] = (k == 1) ? s_1 : s_2; @@ -649,55 +613,52 @@ public: aux_rat_coeffs[4] = (k == 1) ? v_1 : v_2; aux_rat_coeffs[5] = (k == 1) ? w_1 : w_2; - nt_traits.convert_coefficients (aux_rat_coeffs, aux_rat_coeffs + 6, - aux_coeffs); + nt_traits.convert_coefficients(aux_rat_coeffs, aux_rat_coeffs + 6, + aux_coeffs); - if (CGAL::sign (aux_coeffs[0]) == ZERO && - CGAL::sign (aux_coeffs[1]) == ZERO && - CGAL::sign (aux_coeffs[2]) == ZERO) + if (CGAL::sign(aux_coeffs[0]) == ZERO && + CGAL::sign(aux_coeffs[1]) == ZERO && + CGAL::sign(aux_coeffs[2]) == ZERO) { deg_aux = 1; } - else - { + else { deg_aux = 2; } // Compute the x- and y-coordinates of intersection points of the base // conic and the k'th auxiliary conic. - n_xs = _compute_resultant_roots (nt_traits, - base_coeffs[0], base_coeffs[1], - base_coeffs[2], - base_coeffs[3], base_coeffs[4], - base_coeffs[5], - deg_base, - aux_coeffs[0], aux_coeffs[1], - aux_coeffs[2], - aux_coeffs[3], aux_coeffs[4], - aux_coeffs[5], - deg_aux, - xs); + n_xs = _compute_resultant_roots(nt_traits, + base_coeffs[0], base_coeffs[1], + base_coeffs[2], + base_coeffs[3], base_coeffs[4], + base_coeffs[5], + deg_base, + aux_coeffs[0], aux_coeffs[1], + aux_coeffs[2], + aux_coeffs[3], aux_coeffs[4], + aux_coeffs[5], + deg_aux, + xs); - n_ys = _compute_resultant_roots (nt_traits, - base_coeffs[1], base_coeffs[0], - base_coeffs[2], - base_coeffs[4], base_coeffs[3], - base_coeffs[5], - deg_base, - aux_coeffs[1], aux_coeffs[0], - aux_coeffs[2], - aux_coeffs[4], aux_coeffs[3], - aux_coeffs[5], - deg_aux, - ys); + n_ys = _compute_resultant_roots(nt_traits, + base_coeffs[1], base_coeffs[0], + base_coeffs[2], + base_coeffs[4], base_coeffs[3], + base_coeffs[5], + deg_base, + aux_coeffs[1], aux_coeffs[0], + aux_coeffs[2], + aux_coeffs[4], aux_coeffs[3], + aux_coeffs[5], + deg_aux, + ys); // Find the intersection point which is nearest the given approximation // and set it as the endpoint. found = false; - for (i = 0; i < n_xs; i++) - { - for (j = 0; j < n_ys; j++) - { + for (i = 0; i < n_xs; ++i) { + for (j = 0; j < n_ys; ++j) { // Check if the point (xs[i], ys[j]) lies on both conics. val = nt_traits.convert(base_coeffs[0]) * xs[i]*xs[i] + nt_traits.convert(base_coeffs[1]) * ys[j]*ys[j] + @@ -706,7 +667,7 @@ public: nt_traits.convert(base_coeffs[4]) * ys[j] + nt_traits.convert(base_coeffs[5]); - if (CGAL::sign (val) != ZERO) + if (CGAL::sign(val) != ZERO) continue; val = nt_traits.convert(aux_coeffs[0]) * xs[i]*xs[i] + @@ -716,17 +677,14 @@ public: nt_traits.convert(aux_coeffs[4]) * ys[j] + nt_traits.convert(aux_coeffs[5]); - if (CGAL::sign (val) == ZERO) - { + if (CGAL::sign(val) == ZERO) { // Compute the distance of (xs[i], ys[j]) from the approximated // endpoint. - if (k == 1) - { + if (k == 1) { dx = CGAL::to_double (xs[i] - app_source.x()); dy = CGAL::to_double (ys[j] - app_source.y()); } - else - { + else { dx = CGAL::to_double (xs[i] - app_target.x()); dy = CGAL::to_double (ys[j] - app_target.y()); } @@ -735,12 +693,9 @@ public: // Update the endpoint if (xs[i], ys[j]) is the nearest pair so // far. - if (! found || curr_dist < min_dist) - { - if (k == 1) - _source = Point_2 (xs[i], ys[j]); - else - _target = Point_2 (xs[i], ys[j]); + if (! found || curr_dist < min_dist) { + if (k == 1) m_source = Point_2 (xs[i], ys[j]); + else m_target = Point_2 (xs[i], ys[j]); min_dist = curr_dist; found = true; @@ -749,65 +704,52 @@ public: } } - if (! found) - { - _info = 0; // Invalid arc. + if (! found) { + m_info = 0; // Invalid arc. return; } } // Make sure that the source and the target are not the same. - if (Alg_kernel().compare_xy_2_object() (_source, - _target) == EQUAL) - { - _info = 0; // Invalid arc. + if (Alg_kernel().compare_xy_2_object()(m_source, m_target) == EQUAL) { + m_info = 0; // Invalid arc. return; } // Set the arc properties (no need to compute the orientation). - _set (rat_coeffs); + set(rat_coeffs); } - /*! - * Destructor. + /*! Destructor. */ - virtual ~_Conic_arc_2 () - { - if (_extra_data_P != nullptr) - delete _extra_data_P; - } + virtual ~_Conic_arc_2() + { if (m_extra_data != nullptr) delete m_extra_data; } - /*! - * Assignment operator. + /*! Assignment operator. * \param arc The copied arc. */ - const Self& operator= (const Self& arc) - { - if (this == &arc) - return (*this); + const Self& operator=(const Self& arc) { + if (this == &arc) return (*this); // Free any existing data. - if (_extra_data_P != nullptr) - delete _extra_data_P; + if (m_extra_data != nullptr) delete m_extra_data; // Copy the arc's attributes. - _r = arc._r; - _s = arc._s; - _t = arc._t; - _u = arc._u; - _v = arc._v; - _w = arc._w; + m_r = arc.m_r; + m_s = arc.m_s; + m_t = arc.m_t; + m_u = arc.m_u; + m_v = arc.m_v; + m_w = arc.m_w; - _orient = arc._orient; - _info = arc._info; - _source = arc._source; - _target = arc._target; + m_orient = arc.m_orient; + m_info = arc.m_info; + m_source = arc.m_source; + m_target = arc.m_target; // Duplicate the extra data, if necessary. - if (arc._extra_data_P != nullptr) - _extra_data_P = new Extra_data (*(arc._extra_data_P)); - else - _extra_data_P = nullptr; + m_extra_data = (arc.m_extra_data != nullptr) ? + new Extra_data(*(arc.m_extra_data)) ? nullptr; return (*this); } @@ -816,98 +758,73 @@ public: /// \name Get the arc properties. //@{ - /*! - * Check if the arc is valid. + /*! Check if the arc is valid. */ - bool is_valid () const - { - return ((_info & IS_VALID) != 0); - } + bool is_valid() const { return ((m_info & IS_VALID) != 0); } - /*! - * Get the coefficients of the underlying conic. + /*! Get the coefficients of the underlying conic. */ - const Integer& r () const {return (_r);} - const Integer& s () const {return (_s);} - const Integer& t () const {return (_t);} - const Integer& u () const {return (_u);} - const Integer& v () const {return (_v);} - const Integer& w () const {return (_w);} + const Integer& r() const {return (m_r);} + const Integer& s() const {return (m_s);} + const Integer& t() const {return (m_t);} + const Integer& u() const {return (m_u);} + const Integer& v() const {return (m_v);} + const Integer& w() const {return (m_w);} - /*! - * Check whether the arc is x-monotone. + /*! Check whether the arc is x-monotone. */ - bool is_x_monotone () const - { + bool is_x_monotone() const { // Check if the arc contains no vertical tangency points. - Point_2 vtan_ps[2]; - return (vertical_tangency_points (vtan_ps) == 0); + Point_2 vtan_ps[2]; + return (vertical_tangency_points(vtan_ps) == 0); } - /*! - * Check whether the arc is y-monotone. + /*! Check whether the arc is y-monotone. */ - bool is_y_monotone () const - { + bool is_y_monotone() const { // Check if the arc contains no horizontal tangency points. - Point_2 htan_ps[2]; - return (horizontal_tangency_points (htan_ps) == 0); + Point_2 htan_ps[2]; + return (horizontal_tangency_points(htan_ps) == 0); } - /*! - * Check whether the arc represents a full conic curve. + /*! Check whether the arc represents a full conic curve. */ - bool is_full_conic () const - { - return ((_info & IS_FULL_CONIC) != 0); - } + bool is_full_conic() const { return ((m_info & IS_FULL_CONIC) != 0); } - /*! - * Get the arc's source. + /*! Get the arc's source. * \return The source point. * \pre The arc does not represent a full conic curve. */ - const Point_2& source () const - { - CGAL_precondition (! is_full_conic()); - - return (_source); + const Point_2& source() const { + CGAL_precondition(! is_full_conic()); + return m_source; } - /*! - * Get the arc's target. + /*! Get the arc's target. * \return The target point. * \pre The arc does not represent a full conic curve. */ - const Point_2& target () const + const Point_2& target() const { - CGAL_precondition (! is_full_conic()); - - return (_target); + CGAL_precondition(! is_full_conic()); + return m_target; } - /*! - * Get the orientation of the arc. + /*! Get the orientation of the arc. * \return The orientation. */ - Orientation orientation () const - { - return (_orient); - } + Orientation orientation() const { return m_orient; } - /*! - * Get a bounding box for the conic arc. + /*! Get a bounding box for the conic arc. * \return The bounding box. */ - Bbox_2 bbox () const - { + Bbox_2 bbox() const { CGAL_precondition (is_valid()); - double x_min = 0, y_min = 0; - double x_max = 0, y_max = 0; + double x_min = 0, y_min = 0; + double x_max = 0, y_max = 0; - if (is_full_conic()) - { + if (is_full_conic()) { // In case of a full conic (an ellipse or a circle), compute the // horizontal and vertical tangency points and use them to bound the arc. Point_2 tan_ps[2]; @@ -916,13 +833,11 @@ public: CGAL_assertion_code(n_tan_ps = vertical_tangency_points(tan_ps)); CGAL_assertion(n_tan_ps == 2); - if (CGAL::to_double(tan_ps[0].x()) < CGAL::to_double(tan_ps[1].x())) - { + if (CGAL::to_double(tan_ps[0].x()) < CGAL::to_double(tan_ps[1].x())) { x_min = CGAL::to_double(tan_ps[0].x()); x_max = CGAL::to_double(tan_ps[1].x()); } - else - { + else { x_min = CGAL::to_double(tan_ps[1].x()); x_max = CGAL::to_double(tan_ps[0].x()); } @@ -930,42 +845,37 @@ public: CGAL_assertion_code(n_tan_ps = horizontal_tangency_points(tan_ps)); CGAL_assertion(n_tan_ps == 2); - if (CGAL::to_double(tan_ps[0].y()) < CGAL::to_double(tan_ps[1].y())) - { + if (CGAL::to_double(tan_ps[0].y()) < CGAL::to_double(tan_ps[1].y())) { y_min = CGAL::to_double(tan_ps[0].y()); y_max = CGAL::to_double(tan_ps[1].y()); } - else - { + else { y_min = CGAL::to_double(tan_ps[1].y()); y_max = CGAL::to_double(tan_ps[0].y()); } } - else - { + else { // Use the source and target to initialize the exterme points. - bool source_left = - CGAL::to_double(_source.x()) < CGAL::to_double(_target.x()); + bool source_left = + CGAL::to_double(m_source.x()) < CGAL::to_double(m_target.x()); x_min = source_left ? - CGAL::to_double(_source.x()) : CGAL::to_double(_target.x()); + CGAL::to_double(m_source.x()) : CGAL::to_double(m_target.x()); x_max = source_left ? - CGAL::to_double(_target.x()) : CGAL::to_double(_source.x()); + CGAL::to_double(m_target.x()) : CGAL::to_double(m_source.x()); - bool source_down = - CGAL::to_double(_source.y()) < CGAL::to_double(_target.y()); + bool source_down = + CGAL::to_double(m_source.y()) < CGAL::to_double(m_target.y()); y_min = source_down ? - CGAL::to_double(_source.y()) : CGAL::to_double(_target.y()); + CGAL::to_double(m_source.y()) : CGAL::to_double(m_target.y()); y_max = source_down ? - CGAL::to_double(_target.y()) : CGAL::to_double(_source.y()); + CGAL::to_double(m_target.y()) : CGAL::to_double(m_source.y()); // Go over the vertical tangency points and try to update the x-points. - Point_2 tan_ps[2]; - int n_tan_ps; - int i; + Point_2 tan_ps[2]; + int n_tan_ps; - n_tan_ps = vertical_tangency_points (tan_ps); - for (i = 0; i < n_tan_ps; i++) - { + n_tan_ps = vertical_tangency_points(tan_ps); + for (int i = 0; i < n_tan_ps; ++i) { if (CGAL::to_double(tan_ps[i].x()) < x_min) x_min = CGAL::to_double(tan_ps[i].x()); if (CGAL::to_double(tan_ps[i].x()) > x_max) @@ -973,9 +883,8 @@ public: } // Go over the horizontal tangency points and try to update the y-points. - n_tan_ps = horizontal_tangency_points (tan_ps); - for (i = 0; i < n_tan_ps; i++) - { + n_tan_ps = horizontal_tangency_points(tan_ps); + for (int i = 0; i < n_tan_ps; ++i) { if (CGAL::to_double(tan_ps[i].y()) < y_min) y_min = CGAL::to_double(tan_ps[i].y()); if (CGAL::to_double(tan_ps[i].y()) > y_max) @@ -984,49 +893,45 @@ public: } // Return the resulting bounding box. - return (Bbox_2 (x_min, y_min, x_max, y_max)); + return Bbox_2(x_min, y_min, x_max, y_max); } //@} /// \name Modifying functions. //@{ - /*! - * Set the source point of the conic arc. + /*! Set the source point of the conic arc. * \param ps The new source point. * \pre The arc is not a full conic curve. * ps must lie on the supporting conic curve. */ - void set_source (const Point_2& ps) + void set_source(const Point_2& ps) { - CGAL_precondition (! is_full_conic()); - CGAL_precondition (_is_on_supporting_conic (ps)); - CGAL_precondition (Alg_kernel().orientation_2_object() - (_source, ps, _target) == _orient || - Alg_kernel().orientation_2_object() - (ps, _source, _target) == _orient); + CGAL_precondition(! is_full_conic()); + CGAL_precondition(is_on_supporting_conic(ps)); + CGAL_precondition(Alg_kernel().orientation_2_object() + (m_source, ps, m_target) == m_orient || + Alg_kernel().orientation_2_object() + (ps, m_source, m_target) == m_orient); - _source = ps; - return; + m_source = ps; } - /*! - * Set the target point of the conic arc. + /*! Set the target point of the conic arc. * \param pt The new source point. * \pre The arc is not a full conic curve. * pt must lie on the supporting conic curve. */ - void set_target (const Point_2& pt) + void set_target(const Point_2& pt) { - CGAL_precondition (! is_full_conic()); - CGAL_precondition (_is_on_supporting_conic (pt)); - CGAL_precondition (Alg_kernel().orientation_2_object() - (_source, pt, _target) == _orient || - Alg_kernel().orientation_2_object() - (_source, _target, pt) == _orient); + CGAL_precondition(! is_full_conic()); + CGAL_precondition(is_on_supporting_conic(pt)); + CGAL_precondition(Alg_kernel().orientation_2_object() + (m_source, pt, m_target) == m_orient || + Alg_kernel().orientation_2_object() + (m_source, m_target, pt) == m_orient); - _target = pt; - return; + m_target = pt; } //@} @@ -1034,74 +939,60 @@ public: /// \name Compute points on the arc. //@{ - /*! - * Calculate the vertical tangency points of the arc. + /*! Calculate the vertical tangency points of the arc. * \param vpts The vertical tangency points. * \pre The vpts vector should be allocated at the size of 2. * \return The number of vertical tangency points. */ - int vertical_tangency_points (Point_2* vpts) const - { + int vertical_tangency_points(Point_2* vpts) const { // No vertical tangency points for line segments: - if (_orient == COLLINEAR) - return (0); + if (m_orient == COLLINEAR) return 0; // Calculate the vertical tangency points of the supporting conic. Point_2 ps[2]; - int n; - - n = _conic_vertical_tangency_points (ps); + int n = conic_vertical_tangency_points(ps); // Return only the points that are contained in the arc interior. - int m = 0; + int m = 0; - for (int i = 0; i < n; i++) - { - if (is_full_conic() || _is_strictly_between_endpoints(ps[i])) - { + for (int i = 0; i < n; ++i) { + if (is_full_conic() || is_strictly_between_endpoints(ps[i])) { vpts[m] = ps[i]; - m++; + ++m; } } // Return the number of vertical tangency points found. - CGAL_assertion (m <= 2); - return (m); + CGAL_assertion(m <= 2); + return m; } - /*! - * Calculate the horizontal tangency points of the arc. + /*! Calculate the horizontal tangency points of the arc. * \param hpts The horizontal tangency points. * \pre The hpts vector should be allocated at the size of 2. * \return The number of horizontal tangency points. */ - int horizontal_tangency_points (Point_2* hpts) const - { + int horizontal_tangency_points(Point_2* hpts) const { // No horizontal tangency points for line segments: - if (_orient == COLLINEAR) - return (0); + if (m_orient == COLLINEAR) return 0; // Calculate the horizontal tangency points of the conic. - Point_2 ps[2]; - int n; - - n = _conic_horizontal_tangency_points (ps); + Point_2 ps[2]; + int n = conic_horizontal_tangency_points(ps); // Return only the points that are contained in the arc interior. - int m = 0; + int m = 0; - for (int i = 0; i < n; i++) - { - if (is_full_conic() || _is_strictly_between_endpoints(ps[i])) - { + for (int i = 0; i < n; ++i) { + if (is_full_conic() || is_strictly_between_endpoints(ps[i])) { hpts[m] = ps[i]; - m++; + ++m; } } // Return the number of horizontal tangency points found. - CGAL_assertion (m <= 2); - return (m); + CGAL_assertion(m <= 2); + return m; } /*! @@ -1111,189 +1002,162 @@ public: * \pre The vector ps should be allocated at the size of 2. * \return The number of points found. */ - int points_at_x (const Point_2& p, - Point_2 *ps) const - { + int points_at_x(const Point_2& p, Point_2* ps) const { // Get the y coordinates of the points on the conic. - Algebraic ys[2]; - int n; - - n = _conic_get_y_coordinates (p.x(), ys); + Algebraic ys[2]; + int n = conic_get_y_coordinates(p.x(), ys); // Find all the points that are contained in the arc. - int m = 0; + int m = 0; - for (int i = 0; i < n; i++) - { - ps[m] = Point_2 (p.x(), ys[i]); + for (int i = 0; i < n; ++i) { + ps[m] = Point_2(p.x(), ys[i]); - if (is_full_conic() || _is_between_endpoints(ps[m])) - m++; + if (is_full_conic() || is_between_endpoints(ps[m])) ++m; } // Return the number of points on the arc. - CGAL_assertion (m <= 2); - return (m); + CGAL_assertion(m <= 2); + return m; } - /*! - * Find all points on the arc with a given y-coordinate. + /*! Find all points on the arc with a given y-coordinate. * \param p A placeholder for the y-coordinate. * \param ps The point on the arc at x(p). * \pre The vector ps should be allocated at the size of 2. * \return The number of points found. */ - int points_at_y (const Point_2& p, - Point_2 *ps) const - { + int points_at_y(const Point_2& p, Point_2* ps) const { // Get the y coordinates of the points on the conic. - Algebraic xs[2]; - int n; - - n = _conic_get_x_coordinates (p.y(), xs); + Algebraic xs[2]; + int n = conic_get_x_coordinates(p.y(), xs); // Find all the points that are contained in the arc. - int m = 0; + int m = 0; - for (int i = 0; i < n; i++) - { - ps[m] = Point_2 (xs[i], p.y()); - - if (is_full_conic() || _is_between_endpoints(ps[m])) - m++; + for (int i = 0; i < n; ++i) { + ps[m] = Point_2(xs[i], p.y()); + if (is_full_conic() || is_between_endpoints(ps[m])) ++m; } // Return the number of points on the arc. - CGAL_assertion (m <= 2); - return (m); + CGAL_assertion(m <= 2); + return m; } //@} private: - /// \name Auxiliary construction functions. //@{ - /*! - * Set the properties of a conic arc (for the usage of the constructors). + /*! Set the properties of a conic arc (for the usage of the constructors). * \param rat_coeffs A vector of size 6, storing the rational coefficients * of x^2, y^2, xy, x, y and the free coefficient resp. */ - void _set (const Rational* rat_coeffs) - { - _info = IS_VALID; + void set(const Rational* rat_coeffs) { + m_info = IS_VALID; // Convert the coefficients vector to an equivalent vector of integer // coefficients. - Nt_traits nt_traits; - Integer int_coeffs[6]; + Nt_traits nt_traits; + Integer int_coeffs[6]; - nt_traits.convert_coefficients (rat_coeffs, rat_coeffs + 6, - int_coeffs); + nt_traits.convert_coefficients(rat_coeffs, rat_coeffs + 6, int_coeffs); // Check the orientation of conic curve, and negate the conic coefficients // if its given orientation. - typename Rat_kernel::Conic_2 temp_conic (rat_coeffs[0], rat_coeffs[1], - rat_coeffs[2], rat_coeffs[3], - rat_coeffs[4], rat_coeffs[5]); + typename Rat_kernel::Conic_2 temp_conic(rat_coeffs[0], rat_coeffs[1], + rat_coeffs[2], rat_coeffs[3], + rat_coeffs[4], rat_coeffs[5]); - if (_orient == temp_conic.orientation()) - { - _r = int_coeffs[0]; - _s = int_coeffs[1]; - _t = int_coeffs[2]; - _u = int_coeffs[3]; - _v = int_coeffs[4]; - _w = int_coeffs[5]; + if (m_orient == temp_conic.orientation()) { + m_r = int_coeffs[0]; + m_s = int_coeffs[1]; + m_t = int_coeffs[2]; + m_u = int_coeffs[3]; + m_v = int_coeffs[4]; + m_w = int_coeffs[5]; } - else - { - _r = -int_coeffs[0]; - _s = -int_coeffs[1]; - _t = -int_coeffs[2]; - _u = -int_coeffs[3]; - _v = -int_coeffs[4]; - _w = -int_coeffs[5]; + else { + m_r = -int_coeffs[0]; + m_s = -int_coeffs[1]; + m_t = -int_coeffs[2]; + m_u = -int_coeffs[3]; + m_v = -int_coeffs[4]; + m_w = -int_coeffs[5]; } // Make sure both endpoint lie on the supporting conic. - if (! _is_on_supporting_conic (_source) || - ! _is_on_supporting_conic (_target)) + if (! is_on_supporting_conic(m_source) || + ! is_on_supporting_conic(m_target)) { - _info = 0; // Invalid arc. + m_info = 0; // Invalid arc. return; } - _extra_data_P = nullptr; + m_extra_data = nullptr; // Check whether we have a degree 2 curve. - if ((CGAL::sign (_r) != ZERO || - CGAL::sign (_s) != ZERO || - CGAL::sign (_t) != ZERO)) + if ((CGAL::sign(m_r) != ZERO) || (CGAL::sign(m_s) != ZERO) || + (CGAL::sign(m_t) != ZERO)) { - if (_orient == COLLINEAR) - { + if (m_orient == COLLINEAR) { // We have a segment of a line pair with rational coefficients. // Compose the equation of the underlying line // (with algebraic coefficients). - const Algebraic x1 = _source.x(), y1 = _source.y(); - const Algebraic x2 = _target.x(), y2 = _target.y(); + const Algebraic x1 = m_source.x(), y1 = m_source.y(); + const Algebraic x2 = m_target.x(), y2 = m_target.y(); // The supporting line is A*x + B*y + C = 0, where: // // A = y2 - y1, B = x1 - x2, C = x2*y1 - x1*y2 // // We use the extra dat field to store the equation of this line. - _extra_data_P = new Extra_data; - _extra_data_P->a = y2 - y1; - _extra_data_P->b = x1 - x2; - _extra_data_P->c = x2*y1 - x1*y2; - _extra_data_P->side = ZERO; + m_extra_data = new Extra_data; + m_extra_data->a = y2 - y1; + m_extra_data->b = x1 - x2; + m_extra_data->c = x2*y1 - x1*y2; + m_extra_data->side = ZERO; // Make sure the midpoint is on the line pair (thus making sure that // the two points are not taken from different lines). - Alg_kernel ker; - Point_2 p_mid = ker.construct_midpoint_2_object() (_source, - _target); + Alg_kernel ker; + Point_2 p_mid = ker.construct_midpoint_2_object()(m_source, m_target); - if (CGAL::sign ((nt_traits.convert(_r)*p_mid.x() + - nt_traits.convert(_t)*p_mid.y() + - nt_traits.convert(_u)) * p_mid.x() + - (nt_traits.convert(_s)*p_mid.y() + - nt_traits.convert(_v)) * p_mid.y() + - nt_traits.convert(_w)) != ZERO) + if (CGAL::sign((nt_traits.convert(m_r)*p_mid.x() + + nt_traits.convert(m_t)*p_mid.y() + + nt_traits.convert(m_u)) * p_mid.x() + + (nt_traits.convert(m_s)*p_mid.y() + + nt_traits.convert(m_v)) * p_mid.y() + + nt_traits.convert(m_w)) != ZERO) { - _info = 0; // Invalid arc. + m_info = 0; // Invalid arc. return; } } - else - { + else { // The sign of (4rs - t^2) detetmines the conic type: // - if it is possitive, the conic is an ellipse, // - if it is negative, the conic is a hyperbola, // - if it is zero, the conic is a parabola. - CGAL::Sign sign_conic = CGAL::sign (4*_r*_s - _t*_t); + CGAL::Sign sign_conic = CGAL::sign(4*m_r*m_s - m_t*m_t); if (sign_conic == NEGATIVE) // Build the extra hyperbolic data - _build_hyperbolic_arc_data (); + build_hyperbolic_arc_data(); - if (sign_conic != POSITIVE) - { + if (sign_conic != POSITIVE) { // In case of a non-degenerate parabola or a hyperbola, make sure // the arc is not infinite. - Alg_kernel ker; - Point_2 p_mid = ker.construct_midpoint_2_object() (_source, - _target); - Point_2 ps[2]; + Alg_kernel ker; + Point_2 p_mid = ker.construct_midpoint_2_object()(m_source, m_target); + Point_2 ps[2]; - bool finite_at_x = (points_at_x(p_mid, ps) > 0); - bool finite_at_y = (points_at_y(p_mid, ps) > 0); + bool finite_at_x = (points_at_x(p_mid, ps) > 0); + bool finite_at_y = (points_at_y(p_mid, ps) > 0); - if (! finite_at_x && ! finite_at_y) - { - _info = 0; // Invalid arc. + if (! finite_at_x && ! finite_at_y) { + m_info = 0; // Invalid arc. return; } } @@ -1301,81 +1165,67 @@ private: } // Mark that this arc valid and is not a full conic curve. - _info = IS_VALID; - - return; + m_info = IS_VALID; } - /*! - * Set the properties of a conic arc that is really a full curve + /*! Set the properties of a conic arc that is really a full curve * (that is, an ellipse). * \param rat_coeffs A vector of size 6, storing the rational coefficients * of x^2, y^2, xy, x, y and the free coefficient resp. * \param comp_orient Should we compute the orientation of the given curve. */ - void _set_full (const Rational* rat_coeffs, - const bool& comp_orient) - { + void set_full(const Rational* rat_coeffs, const bool& comp_orient) { // Convert the coefficients vector to an equivalent vector of integer // coefficients. - Nt_traits nt_traits; - Integer int_coeffs[6]; + Nt_traits nt_traits; + Integer int_coeffs[6]; - nt_traits.convert_coefficients (rat_coeffs, rat_coeffs + 6, - int_coeffs); + nt_traits.convert_coefficients(rat_coeffs, rat_coeffs + 6, int_coeffs); // Check the orientation of conic curve, and negate the conic coefficients // if its given orientation. - typename Rat_kernel::Conic_2 temp_conic (rat_coeffs[0], rat_coeffs[1], - rat_coeffs[2], rat_coeffs[3], - rat_coeffs[4], rat_coeffs[5]); - const Orientation temp_orient = temp_conic.orientation(); + typename Rat_kernel::Conic_2 temp_conic(rat_coeffs[0], rat_coeffs[1], + rat_coeffs[2], rat_coeffs[3], + rat_coeffs[4], rat_coeffs[5]); + const Orientation temp_orient = temp_conic.orientation(); - if (comp_orient) - _orient = temp_orient; + if (comp_orient) m_orient = temp_orient; - if (_orient == temp_orient) - { - _r = int_coeffs[0]; - _s = int_coeffs[1]; - _t = int_coeffs[2]; - _u = int_coeffs[3]; - _v = int_coeffs[4]; - _w = int_coeffs[5]; + if (m_orient == temp_orient) { + m_r = int_coeffs[0]; + m_s = int_coeffs[1]; + m_t = int_coeffs[2]; + m_u = int_coeffs[3]; + m_v = int_coeffs[4]; + m_w = int_coeffs[5]; } - else - { - _r = -int_coeffs[0]; - _s = -int_coeffs[1]; - _t = -int_coeffs[2]; - _u = -int_coeffs[3]; - _v = -int_coeffs[4]; - _w = -int_coeffs[5]; + else { + m_r = -int_coeffs[0]; + m_s = -int_coeffs[1]; + m_t = -int_coeffs[2]; + m_u = -int_coeffs[3]; + m_v = -int_coeffs[4]; + m_w = -int_coeffs[5]; } // Make sure the conic is a non-degenerate ellipse: // The coefficients should satisfy (4rs - t^2) > 0. - const bool is_ellipse = (CGAL::sign (4*_r*_s - _t*_t) == POSITIVE); - CGAL_assertion (is_ellipse); + const bool is_ellipse = (CGAL::sign(4*m_r*m_s - m_t*m_t) == POSITIVE); + CGAL_assertion(is_ellipse); // We do not have to store any extra data with the arc. - _extra_data_P = nullptr; + m_extra_data = nullptr; // Mark that this arc is a full conic curve. - if (is_ellipse) - _info = IS_VALID | IS_FULL_CONIC; - else - _info = 0; - - return; + if (is_ellipse) m_info = IS_VALID | IS_FULL_CONIC; + else m_info = 0; } /*! * Build the data for hyperbolic arc, contaning the characterization of the * hyperbolic branch the arc is placed on. */ - void _build_hyperbolic_arc_data () - { + void build_hyperbolic_arc_data() { // Let phi be the rotation angle of the conic from its canonic form. // We can write: // @@ -1387,51 +1237,46 @@ private: // cos(2*phi) = ----------------------- // sqrt((r - s)^2 + t^2) // - Nt_traits nt_traits; - const int or_fact = (_orient == CLOCKWISE) ? -1 : 1; - const Algebraic r = nt_traits.convert (or_fact * _r); - const Algebraic s = nt_traits.convert (or_fact * _s); - const Algebraic t = nt_traits.convert (or_fact * _t); - const Algebraic cos_2phi = (r - s) / nt_traits.sqrt((r-s)*(r-s) + t*t); - const Algebraic _zero = 0; - const Algebraic _one = 1; - const Algebraic _two = 2; - Algebraic sin_phi; - Algebraic cos_phi; + Nt_traits nt_traits; + const int or_fact = (m_orient == CLOCKWISE) ? -1 : 1; + const Algebraic r = nt_traits.convert(or_fact * m_r); + const Algebraic s = nt_traits.convert(or_fact * m_s); + const Algebraic t = nt_traits.convert(or_fact * m_t); + const Algebraic cos_2phi = (r - s) / nt_traits.sqrt((r-s)*(r-s) + t*t); + const Algebraic zero = 0; + const Algebraic one = 1; + const Algebraic two = 2; + Algebraic sin_phi; + Algebraic cos_phi; // Calculate sin(phi) and cos(phi) according to the half-angle formulae: // // sin(phi)^2 = 0.5 * (1 - cos(2*phi)) // cos(phi)^2 = 0.5 * (1 + cos(2*phi)) - Sign sign_t = CGAL::sign (t); + Sign sign_t = CGAL::sign(t); - if (sign_t == ZERO) - { + if (sign_t == ZERO) { // sin(2*phi) == 0, so phi = 0 or phi = PI/2 - if (CGAL::sign (cos_2phi) == POSITIVE) - { + if (CGAL::sign(cos_2phi) == POSITIVE) { // phi = 0. - sin_phi = _zero; - cos_phi = _one; + sin_phi = zero; + cos_phi = one; } - else - { + else { // phi = PI/2. - sin_phi = _one; - cos_phi = _zero; + sin_phi = one; + cos_phi = zero; } } - else if (sign_t == POSITIVE) - { + else if (sign_t == POSITIVE) { // sin(2*phi) > 0 so 0 < phi < PI/2. - sin_phi = nt_traits.sqrt((_one + cos_2phi) / _two); - cos_phi = nt_traits.sqrt((_one - cos_2phi) / _two); + sin_phi = nt_traits.sqrt((one + cos_2phi) / two); + cos_phi = nt_traits.sqrt((one - cos_2phi) / two); } - else - { + else { // sin(2*phi) < 0 so PI/2 < phi < PI. - sin_phi = nt_traits.sqrt((_one + cos_2phi) / _two); - cos_phi = -nt_traits.sqrt((_one - cos_2phi) / _two); + sin_phi = nt_traits.sqrt((one + cos_2phi) / two); + cos_phi = -nt_traits.sqrt((one - cos_2phi) / two); } // Calculate the center (x0, y0) of the conic, given by the formulae: @@ -1441,15 +1286,15 @@ private: // 4*r*s - t^2 4*r*s - t^2 // // The denominator (4*r*s - t^2) must be negative for hyperbolas. - const Algebraic u = nt_traits.convert (or_fact * _u); - const Algebraic v = nt_traits.convert (or_fact * _v); - const Algebraic det = 4*r*s - t*t; - Algebraic x0, y0; + const Algebraic u = nt_traits.convert(or_fact * m_u); + const Algebraic v = nt_traits.convert(or_fact * m_v); + const Algebraic det = 4*r*s - t*t; + Algebraic x0, y0; - CGAL_assertion (CGAL::sign (det) == NEGATIVE); + CGAL_assertion(CGAL::sign(det) == NEGATIVE); - x0 = (t*v - _two*s*u) / det; - y0 = (t*u - _two*r*v) / det; + x0 = (t*v - two*s*u) / det; + y0 = (t*u - two*r*v) / det; // The axis separating the two branches of the hyperbola is now given by: // @@ -1457,246 +1302,207 @@ private: // // We store the equation of this line in the extra data structure and also // the sign (side of half-plane) our arc occupies with respect to the line. - _extra_data_P = new Extra_data; + m_extra_data = new Extra_data; - _extra_data_P->a = cos_phi; - _extra_data_P->b = sin_phi; - _extra_data_P->c = - (cos_phi*x0 + sin_phi*y0); + m_extra_data->a = cos_phi; + m_extra_data->b = sin_phi; + m_extra_data->c = - (cos_phi*x0 + sin_phi*y0); // Make sure that the two endpoints are located on the same branch // of the hyperbola. - _extra_data_P->side = _sign_of_extra_data (_source.x(), _source.y()); + m_extra_data->side = sign_of_extra_data(m_source.x(), m_source.y()); - CGAL_assertion (_extra_data_P->side != ZERO); - CGAL_assertion (_extra_data_P->side == _sign_of_extra_data(_target.x(), - _target.y())); - - return; + CGAL_assertion(m_extra_data->side != ZERO); + CGAL_assertion(m_extra_data->side == + sign_of_extra_data(m_target.x(), m_target.y())); } //@} protected: - /// \name Auxiliary functions. //@{ - /*! - * Evaluate the sign of (a*x + b*y + c) stored with the extra data field + /*! Evaluate the sign of (a*x + b*y + c) stored with the extra data field * at a given point. * \param px The x-coordinate of query point. * \param py The y-coordinate of query point. * \return The sign of (a*x + b*y + c). */ - Sign _sign_of_extra_data (const Algebraic& px, - const Algebraic& py) const - { - CGAL_assertion (_extra_data_P != nullptr); + Sign sign_of_extra_data(const Algebraic& px, const Algebraic& py) const { + CGAL_assertion(m_extra_data != nullptr); - if (_extra_data_P == nullptr) - return (ZERO); + if (m_extra_data == nullptr) return ZERO; - Algebraic val = (_extra_data_P->a*px + _extra_data_P->b*py + - _extra_data_P->c); + Algebraic val = (m_extra_data->a*px + m_extra_data->b*py + + m_extra_data->c); - return (CGAL::sign (val)); + return CGAL::sign(val); } - /*! - * Check whether the given point lies on the supporting conic of the arc. + /*! Check whether the given point lies on the supporting conic of the arc. * \param p The query point. - * \return (true) if p lies on the supporting conic; (false) otherwise. + * \return true if p lies on the supporting conic; (false) otherwise. */ - bool _is_on_supporting_conic (const Point_2& p) const - { + bool is_on_supporting_conic(const Point_2& p) const { // Check whether p satisfies the conic equation. // The point must satisfy: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0. - Nt_traits nt_traits; - const Algebraic val = (nt_traits.convert(_r)*p.x() + - nt_traits.convert(_t)*p.y() + - nt_traits.convert(_u)) * p.x() + - (nt_traits.convert(_s)*p.y() + - nt_traits.convert(_v)) * p.y() + - nt_traits.convert(_w); + Nt_traits nt_traits; + const Algebraic val = (nt_traits.convert(m_r)*p.x() + + nt_traits.convert(m_t)*p.y() + + nt_traits.convert(m_u)) * p.x() + + (nt_traits.convert(m_s) * p.y() + nt_traits.convert(m_v)) * p.y() + + nt_traits.convert(m_w); - return (CGAL::sign (val) == ZERO); + return (CGAL::sign(val) == ZERO); } - /*! - * Check whether the given point is between the source and the target. + /*! Check whether the given point is between the source and the target. * The point is assumed to be on the conic's boundary. * \param p The query point. - * \return (true) if the point is between the two endpoints, + * \return true if the point is between the two endpoints, * (false) if it is not. */ - bool _is_between_endpoints (const Point_2& p) const - { - CGAL_precondition (! is_full_conic()); + bool is_between_endpoints(const Point_2& p) const { + CGAL_precondition(! is_full_conic()); // Check if p is one of the endpoints. - Alg_kernel ker; + Alg_kernel ker; - if (ker.equal_2_object() (p, _source) || - ker.equal_2_object() (p, _target)) - { - return (true); - } - else - { - return (_is_strictly_between_endpoints(p)); - } + if (ker.equal_2_object()(p, m_source) || ker.equal_2_object()(p, m_target)) + return true; + else return (is_strictly_between_endpoints(p)); } - /*! - * Check whether the given point is strictly between the source and the + /*! Check whether the given point is strictly between the source and the * target (but not any of them). * The point is assumed to be on the conic's boundary. * \param p The query point. - * \return (true) if the point is strictly between the two endpoints, + * \return true if the point is strictly between the two endpoints, * (false) if it is not. */ - bool _is_strictly_between_endpoints (const Point_2& p) const - { + bool is_strictly_between_endpoints(const Point_2& p) const { // In case this is a full conic, any point on its boundary is between // its end points. - if (is_full_conic()) - return (true); + if (is_full_conic()) return true; // Check if we have extra data available. - if (_extra_data_P != nullptr) - { - if (_extra_data_P->side != ZERO) - { + if (m_extra_data != nullptr) { + if (m_extra_data->side != ZERO) { // In case of a hyperbolic arc, make sure the point is located on the // same branch as the arc. - if (_sign_of_extra_data(p.x(), p.y()) != _extra_data_P->side) - return (false); + if (sign_of_extra_data(p.x(), p.y()) != m_extra_data->side) + return false; } - else - { + else { // In case we have a segment of a line pair, make sure that p really // satisfies the equation of the line. - if (_sign_of_extra_data(p.x(), p.y()) != ZERO) - return (false); + if (sign_of_extra_data(p.x(), p.y()) != ZERO) return false; } } // Act according to the conic degree. - Alg_kernel ker; + Alg_kernel ker; - if (_orient == COLLINEAR) - { - Comparison_result res1; - Comparison_result res2; + if (m_orient == COLLINEAR) { + Comparison_result res1; + Comparison_result res2; - if (ker.compare_x_2_object() (_source, _target) == EQUAL) - { + if (ker.compare_x_2_object()(m_source, m_target) == EQUAL) { // In case of a vertical segment - just check whether the y coordinate // of p is between those of the source's and of the target's. - res1 = ker.compare_y_2_object() (p, _source); - res2 = ker.compare_y_2_object() (p, _target); + res1 = ker.compare_y_2_object()(p, m_source); + res2 = ker.compare_y_2_object()(p, m_target); } - else - { + else { // Otherwise, since the segment is x-monotone, just check whether the // x coordinate of p is between those of the source's and of the // target's. - res1 = ker.compare_x_2_object() (p, _source); - res2 = ker.compare_x_2_object() (p, _target); + res1 = ker.compare_x_2_object()(p, m_source); + res2 = ker.compare_x_2_object()(p, m_target); } // If p is not in the (open) x-range (or y-range) of the segment, it // cannot be contained in the segment. - if (res1 == EQUAL || res2 == EQUAL || res1 == res2) - return (false); + if ((res1 == EQUAL) || (res2 == EQUAL) || (res1 == res2)) return false; // Perform an orientation test: This is crucial for segment of line // pairs, as we want to make sure that p lies on the same line as the // source and the target. - return (ker.orientation_2_object()(_source, p, _target) == COLLINEAR); + return (ker.orientation_2_object()(m_source, p, m_target) == COLLINEAR); } - else - { + else { // In case of a conic of degree 2, make a decision based on the conic's // orientation and whether (source,p,target) is a right or a left turn. - if (_orient == COUNTERCLOCKWISE) - return (ker.orientation_2_object()(_source, p, _target) == LEFT_TURN); + if (m_orient == COUNTERCLOCKWISE) + return (ker.orientation_2_object()(m_source, p, m_target) == LEFT_TURN); else - return (ker.orientation_2_object()(_source, p, _target) == RIGHT_TURN); + return (ker.orientation_2_object()(m_source, p, m_target) == RIGHT_TURN); } } - /*! - * Find the vertical tangency points of the undelying conic. + /*! Find the vertical tangency points of the undelying conic. * \param ps The output points of vertical tangency. * This area must be allocated at the size of 2. * \return The number of vertical tangency points. */ - int _conic_vertical_tangency_points (Point_2* ps) const - { + int conic_vertical_tangency_points(Point_2* ps) const { // In case the base conic is of degree 1 (and not 2), the arc has no // vertical tangency points. - if (CGAL::sign (_s) == ZERO) - return (0); + if (CGAL::sign(m_s) == ZERO) return 0; // We are interested in the x coordinates where the quadratic equation: // s*y^2 + (t*x + v)*y + (r*x^2 + u*x + w) = 0 // has a single solution (obviously if s = 0, there are no such points). // We therefore demand that the discriminant of this equation is zero: // (t*x + v)^2 - 4*s*(r*x^2 + u*x + w) = 0 - const Integer _two = 2; - const Integer _four = 4; - Algebraic xs[2]; - Algebraic *xs_end; - int n_xs; - Nt_traits nt_traits; + const Integer two = 2; + const Integer four = 4; + Algebraic xs[2]; + Algebraic* xs_end; + int n_xs; + Nt_traits nt_traits; - xs_end = nt_traits.solve_quadratic_equation (_t*_t - _four*_r*_s, - _two*_t*_v - _four*_s*_u, - _v*_v - _four*_s*_w, - xs); + xs_end = nt_traits.solve_quadratic_equation(m_t*m_t - four*m_r*m_s, + two*m_t*m_v - four*m_s*m_u, + m_v*m_v - four*m_s*m_w, + xs); n_xs = static_cast(xs_end - xs); // Find the y-coordinates of the vertical tangency points. - Algebraic ys[2]; - Algebraic *ys_end; - int n_ys; + Algebraic ys[2]; + Algebraic* ys_end; + int n_ys; - if (CGAL::sign (_t) == ZERO) - { + if (CGAL::sign(m_t) == ZERO) { // The two vertical tangency points have the same y coordinate: - ys[0] = nt_traits.convert (-_v) /nt_traits.convert (_two*_s); + ys[0] = nt_traits.convert(-m_v) / nt_traits.convert(two*m_s); n_ys = 1; } - else - { + else { ys_end = - nt_traits.solve_quadratic_equation (_four*_r*_s*_s - _s*_t*_t, - _four*_r*_s*_v - _two*_s*_t*_u, - _r*_v*_v - _t*_u*_v + _t*_t*_w, - ys); + nt_traits.solve_quadratic_equation(four*m_r*m_s*m_s - m_s*m_t*m_t, + four*m_r*m_s*m_v - two*m_s*m_t*m_u, + m_r*m_v*m_v - m_t*m_u*m_v + m_t*m_t*m_w, + ys); n_ys = static_cast(ys_end - ys); } // Pair the x and y coordinates and obtain the vertical tangency points. - int n = 0; - int i, j; + int n = 0; + int i, j; - for (i = 0; i < n_xs; i++) - { - if (n_ys == 1) - { - ps[n] = Point_2 (xs[i], ys[0]); + for (i = 0; i < n_xs; ++i) { + if (n_ys == 1) { + ps[n] = Point_2(xs[i], ys[0]); n++; } - else - { - for (j = 0; j < n_ys; j++) - { - if (CGAL::compare (nt_traits.convert(_two*_s) * ys[j], - -(nt_traits.convert(_t) * xs[i] + - nt_traits.convert(_v))) == EQUAL) + else { + for (j = 0; j < n_ys; j++) { + if (CGAL::compare(nt_traits.convert(two*m_s) * ys[j], + -(nt_traits.convert(m_t) * xs[i] + + nt_traits.convert(m_v))) == EQUAL) { - ps[n] = Point_2 (xs[i], ys[j]); + ps[n] = Point_2(xs[i], ys[j]); n++; break; } @@ -1704,160 +1510,136 @@ protected: } } - CGAL_assertion (n <= 2); - return (n); + CGAL_assertion(n <= 2); + return n; } - /*! - * Find the horizontal tangency points of the undelying conic. + /*! Find the horizontal tangency points of the undelying conic. * \param ps The output points of horizontal tangency. * This area must be allocated at the size of 2. * \return The number of horizontal tangency points. */ - int _conic_horizontal_tangency_points (Point_2* ps) const - { - const Integer _zero = 0; + int conic_horizontal_tangency_points(Point_2* ps) const { + const Integer zero = 0; // In case the base conic is of degree 1 (and not 2), the arc has no // vertical tangency points. - if (CGAL::sign (_r) == ZERO) - return (0); + if (CGAL::sign(m_r) == ZERO) return 0; // We are interested in the y coordinates were the quadratic equation: // r*x^2 + (t*y + u)*x + (s*y^2 + v*y + w) = 0 // has a single solution (obviously if r = 0, there are no such points). // We therefore demand that the discriminant of this equation is zero: // (t*y + u)^2 - 4*r*(s*y^2 + v*y + w) = 0 - const Integer _two = 2; - const Integer _four = 4; - int n; - Algebraic ys[2]; - Algebraic *ys_end; - Nt_traits nt_traits; + const Integer two = 2; + const Integer four = 4; + int n; + Algebraic ys[2]; + Algebraic *ys_end; + Nt_traits nt_traits; - ys_end = nt_traits.solve_quadratic_equation (_t*_t - _four*_r*_s, - _two*_t*_u - _four*_r*_v, - _u*_u - _four*_r*_w, - ys); + ys_end = nt_traits.solve_quadratic_equation(m_t*m_t - four*m_r*m_s, + two*m_t*m_u - four*m_r*m_v, + m_u*m_u - four*m_r*m_w, + ys); n = static_cast(ys_end - ys); // Compute the x coordinates and construct the horizontal tangency points. - Algebraic x; - int i; - - for (i = 0; i < n; i++) - { + for (int i = 0; i < n; ++i) { // Having computed y, x is the single solution to the quadratic equation // above, and since its discriminant is 0, x is simply given by: - x = -(nt_traits.convert(_t)*ys[i] + nt_traits.convert(_u)) / - nt_traits.convert(_two*_r); - - ps[i] = Point_2 (x, ys[i]); + Algebraic x = -(nt_traits.convert(m_t)*ys[i] + nt_traits.convert(m_u)) / + nt_traits.convert(two*m_r); + ps[i] = Point_2(x, ys[i]); } - CGAL_assertion (n <= 2); - return (n); + CGAL_assertion(n <= 2); + return n; } - /*! - * Find the y coordinates of the underlying conic at a given x coordinate. + /*! Find the y coordinates of the underlying conic at a given x coordinate. * \param x The x coordinate. * \param ys The output y coordinates. * \pre The vector ys must be allocated at the size of 2. * \return The number of y coordinates computed (either 0, 1 or 2). */ - int _conic_get_y_coordinates (const Algebraic& x, - Algebraic *ys) const - { + int conic_get_y_coordinates(const Algebraic& x, Algebraic* ys) const { // Solve the quadratic equation for a given x and find the y values: // s*y^2 + (t*x + v)*y + (r*x^2 + u*x + w) = 0 - Nt_traits nt_traits; - Algebraic A = nt_traits.convert(_s); - Algebraic B = nt_traits.convert(_t)*x + nt_traits.convert(_v); - Algebraic C = (nt_traits.convert(_r)*x + - nt_traits.convert(_u))*x + nt_traits.convert(_w); + Nt_traits nt_traits; + Algebraic A = nt_traits.convert(m_s); + Algebraic B = nt_traits.convert(m_t)*x + nt_traits.convert(m_v); + Algebraic C = (nt_traits.convert(m_r)*x + nt_traits.convert(m_u))*x + + nt_traits.convert(m_w); - return (_solve_quadratic_equation (A, B, C, ys[0], ys[1])); + return (solve_quadratic_equation(A, B, C, ys[0], ys[1])); } - /*! - * Find the x coordinates of the underlying conic at a given y coordinate. + /*! Find the x coordinates of the underlying conic at a given y coordinate. * \param y The y coordinate. * \param xs The output x coordinates. * \pre The vector xs must be allocated at the size of 2. * \return The number of x coordinates computed (either 0, 1 or 2). */ - int _conic_get_x_coordinates (const Algebraic& y, - Algebraic *xs) const - { + int conic_get_x_coordinates(const Algebraic& y, Algebraic* xs) const { // Solve the quadratic equation for a given y and find the x values: // r*x^2 + (t*y + u)*x + (s*y^2 + v*y + w) = 0 - Nt_traits nt_traits; - Algebraic A = nt_traits.convert(_r); - Algebraic B = nt_traits.convert(_t)*y + nt_traits.convert(_u); - Algebraic C = (nt_traits.convert(_s)*y + - nt_traits.convert(_v))*y + nt_traits.convert(_w); + Nt_traits nt_traits; + Algebraic A = nt_traits.convert(m_r); + Algebraic B = nt_traits.convert(m_t)*y + nt_traits.convert(m_u); + Algebraic C = (nt_traits.convert(m_s)*y + nt_traits.convert(m_v))*y + + nt_traits.convert(m_w); - return (_solve_quadratic_equation (A, B, C, xs[0], xs[1])); + return (solve_quadratic_equation(A, B, C, xs[0], xs[1])); } - /*! - * Solve the given quadratic equation: Ax^2 + B*x + C = 0. + /*! Solve the given quadratic equation: Ax^2 + B*x + C = 0. * \param x_minus The root obtained from taking -sqrt(discriminant). * \param x_plus The root obtained from taking -sqrt(discriminant). * \return The number of disticnt solutions to the equation. */ - int _solve_quadratic_equation (const Algebraic& A, - const Algebraic& B, - const Algebraic& C, - Algebraic& x_minus, Algebraic& x_plus) const - { + int solve_quadratic_equation(const Algebraic& A, + const Algebraic& B, + const Algebraic& C, + Algebraic& x_minus, Algebraic& x_plus) const { // Check if we actually have a linear equation. - if (CGAL::sign(A) == ZERO) - { - if (CGAL::sign(B) == ZERO) - return (0); - + if (CGAL::sign(A) == ZERO) { + if (CGAL::sign(B) == ZERO) return 0; x_minus = x_plus = -C / B; - return (1); + return 1; } // Compute the discriminant and act according to its sign. - const Algebraic disc = B*B - 4*A*C; - Sign sign_disc = CGAL::sign (disc); + const Algebraic disc = B*B - 4*A*C; + Sign sign_disc = CGAL::sign(disc); - if (sign_disc == NEGATIVE) - { - // No real-valued solutions: - return (0); - } - else if (sign_disc == ZERO) - { + // Check whether there are no real-valued solutions: + if (sign_disc == NEGATIVE) return 0; + else if (sign_disc == ZERO) { // One distinct solution: x_minus = x_plus = -B / (2*A); - return (1); + return 1; } // Compute the two distinct solutions: - Algebraic _2A = 2*A; - Nt_traits nt_traits; - Algebraic sqrt_disc = nt_traits.sqrt (disc); + Algebraic _2A = 2*A; + Nt_traits nt_traits; + Algebraic sqrt_disc = nt_traits.sqrt (disc); x_minus = -(B + sqrt_disc) / _2A; x_plus = (sqrt_disc - B) / _2A; - return (2); + return 2; } //@} }; -/*! - * Exporter for conic arcs. +/*! Exporter for conic arcs. */ -template +template std::ostream& operator<< (std::ostream& os, - const _Conic_arc_2 & arc) + const _Conic_arc_2& arc) { os << "{" << CGAL::to_double(arc.r()) << "*x^2 + " << CGAL::to_double(arc.s()) << "*y^2 + " @@ -1866,12 +1648,8 @@ operator<< (std::ostream& os, << CGAL::to_double(arc.v()) << "*y + " << CGAL::to_double(arc.w()) << "}"; - if (arc.is_full_conic()) - { - os << " - Full curve"; - } - else - { + if (arc.is_full_conic()) os << " - Full curve"; + else { os << " : (" << CGAL::to_double(arc.source().x()) << "," << CGAL::to_double(arc.source().y()) << ") "; diff --git a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h new file mode 100644 index 00000000000..9e89e4223b4 --- /dev/null +++ b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h @@ -0,0 +1,94 @@ +#ifndef CGAL_DRAW_ARRANGEMENT_2_H +#define CGAL_DRAW_ARRANGEMENT_2_H + +#include +#include +#include + +namespace CGAL { + +// Viewer class for Polygon_2 +template +class Arr_2_viewer_qt : public Basic_viewer_qt { + typedef Basic_viewer_qt Base; + typedef Arrangement_2 Arr; + typedef typename Arr::Point_2 Point; + +public: + /// Construct the viewer. + /// @param arr the arrangement to view + /// @param title the title of the window + Arr_2_viewer_qt(QWidget* parent, const Arr& arr, + const char* title = "2D Arrangement Basic Viewer") : + // First draw: vertices; edges, faces; multi-color; no inverse normal + Base(parent, title, true, true, true, false, false), + m_arr(arr) + { add_elements(); } + +protected: + void add_ccb(typename Arr::Ccb_halfedge_const_circulator circ) { + typename Arr::Ccb_halfedge_const_circulator curr = circ; + do { + typename Arr::Halfedge_const_handle e = curr; + add_segment(e->source()->point(), e->target()->point()); + add_point(e->source()->point()); + add_point_in_face(e->source()->point()); + } while (++curr != circ); + } + + void add_face(typename Arr::Face_const_handle f, CGAL::IO::Color c) { + if (f->is_unbounded()) return; + face_begin(c); + add_ccb(f->outer_ccb()); + for (auto iv = f->isolated_vertices_begin(); + iv != f->isolated_vertices_end(); ++iv) + add_point(iv->point()); + face_end(); + } + + void add_elements() { + clear(); + if (m_arr.is_empty()) return; + CGAL::IO::Color c(75,160,255); + for (auto fit = m_arr.faces_begin(); fit != m_arr.faces_end(); ++fit) + add_face(fit, c); + } + + virtual void keyPressEvent(QKeyEvent* e) { + // Test key pressed: + // const ::Qt::KeyboardModifiers modifiers = e->modifiers(); + // if ((e->key()==Qt::Key_PageUp) && (modifiers==Qt::NoButton)) { ... } + + // Call: * add_elements() if the model changed, followed by + // * redraw() if some viewing parameters changed that implies some + // modifications of the buffers + // (eg. type of normal, color/mono) + // * update() just to update the drawing + + // Call the base method to process others/classicals key + Base::keyPressEvent(e); + } + +protected: + const Arrangement_2& m_arr; +}; + +template +void draw(const CGAL::Arrangement_2& arr, + const char* title = "2D Arrangement Basic Viewer") { + typedef GeometryTraits_2 Gt; + typedef CGAL::Arrangement_2 Arr; + + CGAL::Qt::init_ogl_context(4,3); + + int argc = 1; + const char* argv[2] = {"t2_viewer", nullptr}; + QApplication app(argc, const_cast(argv)); + Arr_2_viewer_qtmainwindow(app.activeWindow(), arr, title); + mainwindow.show(); + app.exec(); +} + +} + +#endif From 418e2b0c6b15f724f080682f891c195cc431697f Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 18 May 2022 13:25:18 +0300 Subject: [PATCH 002/105] descended to inner ccbs --- .../include/CGAL/draw_arrangement_2.h | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h index 9e89e4223b4..9feb18a9a28 100644 --- a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h +++ b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h @@ -37,13 +37,23 @@ protected: } void add_face(typename Arr::Face_const_handle f, CGAL::IO::Color c) { - if (f->is_unbounded()) return; - face_begin(c); - add_ccb(f->outer_ccb()); - for (auto iv = f->isolated_vertices_begin(); - iv != f->isolated_vertices_end(); ++iv) - add_point(iv->point()); - face_end(); + if (! f->is_unbounded()) { + face_begin(c); + add_ccb(f->outer_ccb()); + for (auto iv = f->isolated_vertices_begin(); + iv != f->isolated_vertices_end(); ++iv) + add_point(iv->point()); + face_end(); + } + + for (auto it = f->inner_ccbs_begin(); it != f->inner_ccbs_end(); ++it) { + face_begin(c); + add_ccb(*it); + for (auto iv = f->isolated_vertices_begin(); + iv != f->isolated_vertices_end(); ++iv) + add_point(iv->point()); + face_end(); + } } void add_elements() { From d1b05fd14446eec16d881b9b5b0b36866ebeff8b Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 18 May 2022 13:37:17 +0300 Subject: [PATCH 003/105] Cleaned up --- .../Arrangement_on_surface_2/CMakeLists.txt | 1 + .../Arrangement_on_surface_2/conics.cpp | 16 +- .../CGAL/Arr_geometry_traits/Conic_arc_2.h | 65 +- .../Conic_intersections_2.h | 180 ++- .../Conic_x_monotone_arc_2.h | 1271 +++++++---------- 5 files changed, 683 insertions(+), 850 deletions(-) diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/CMakeLists.txt b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/CMakeLists.txt index 26f23e6c53a..d3536801663 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/CMakeLists.txt +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/CMakeLists.txt @@ -17,4 +17,5 @@ endforeach() if(CGAL_Qt5_FOUND) target_link_libraries(draw_arr PUBLIC CGAL::CGAL_Basic_viewer) + target_link_libraries(conics PUBLIC CGAL::CGAL_Basic_viewer) endif() diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conics.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conics.cpp index a8688f55a98..6720bb7a8d2 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conics.cpp +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conics.cpp @@ -2,6 +2,7 @@ // Constructing an arrangement of various conic arcs. #include +#include #ifdef CGAL_USE_CORE @@ -11,6 +12,7 @@ int main() { Arrangement arr; +#if 0 // Insert a hyperbolic arc (C1), supported by the hyperbola y = 1/x // (or: xy - 1 = 0) with the endpoints (1/4, 4) and (2, 1/2). // The arc is counterclockwise oriented. @@ -20,21 +22,24 @@ int main() { // Insert a full ellipse (C2), which is (x/4)^2 + (y/2)^2 = 0 rotated by // phi = 36.87 degrees (such that sin(phi) = 0.6, cos(phi) = 0.8), // yielding: 58x^2 + 72y^2 - 48xy - 360 = 0. - insert(arr, Conic_arc (58, 72, -48, 0, 0, -360)); + insert(arr, Conic_arc(58, 72, -48, 0, 0, -360)); +#endif // Insert the segment (C3) (1, 1) -- (0, -3). insert(arr, Conic_arc(Rat_segment(Rat_point(1, 1), Rat_point(0, -3)))); +#if 0 // Insert a circular arc (C4) supported by the circle x^2 + y^2 = 5^2, // with (-3, 4) and (4, 3) as its endpoints. We want the arc to be // clockwise-oriented, so it passes through (0, 5) as well. Conic_arc c4(Rat_point(-3, 4), Rat_point(0, 5), Rat_point(4, 3)); - insert(arr, c4); +#endif // Insert a full unit circle (C5) that is centered at (0, 4). insert(arr, Conic_arc(Rat_circle(Rat_point(0,4), 1))); +#if 0 // Insert a parabolic arc (C6) supported by the parabola y = -x^2 with // endpoints (-sqrt(3),-3) (~(-1.73,-3)) and (sqrt(2),-2) (~(1.41,-2)). // Since the x-coordinates of the endpoints cannot be acccurately represented, @@ -53,8 +58,12 @@ int main() { // is 1/2 (therefore its squared radius is 1/4) (C7). Rat_circle circ7(Rat_point(4, Rational(5,2)), Rational(1,4)); insert(arr, Conic_arc(circ7, CGAL::CLOCKWISE, Point(4, 3), Point(4, 2))); +#endif + print_arrangement_size(arr); + CGAL::draw(arr); + return 0; } @@ -62,8 +71,7 @@ int main() { #include -int main () -{ +int main() { std::cout << "Sorry, this example needs GMP and CORE\n"; return 0; } diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h index e02e46e700a..a2fb69131fb 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h @@ -628,31 +628,31 @@ public: // Compute the x- and y-coordinates of intersection points of the base // conic and the k'th auxiliary conic. - n_xs = _compute_resultant_roots(nt_traits, - base_coeffs[0], base_coeffs[1], - base_coeffs[2], - base_coeffs[3], base_coeffs[4], - base_coeffs[5], - deg_base, - aux_coeffs[0], aux_coeffs[1], - aux_coeffs[2], - aux_coeffs[3], aux_coeffs[4], - aux_coeffs[5], - deg_aux, - xs); + n_xs = compute_resultant_roots(nt_traits, + base_coeffs[0], base_coeffs[1], + base_coeffs[2], + base_coeffs[3], base_coeffs[4], + base_coeffs[5], + deg_base, + aux_coeffs[0], aux_coeffs[1], + aux_coeffs[2], + aux_coeffs[3], aux_coeffs[4], + aux_coeffs[5], + deg_aux, + xs); - n_ys = _compute_resultant_roots(nt_traits, - base_coeffs[1], base_coeffs[0], - base_coeffs[2], - base_coeffs[4], base_coeffs[3], - base_coeffs[5], - deg_base, - aux_coeffs[1], aux_coeffs[0], - aux_coeffs[2], - aux_coeffs[4], aux_coeffs[3], - aux_coeffs[5], - deg_aux, - ys); + n_ys = compute_resultant_roots(nt_traits, + base_coeffs[1], base_coeffs[0], + base_coeffs[2], + base_coeffs[4], base_coeffs[3], + base_coeffs[5], + deg_base, + aux_coeffs[1], aux_coeffs[0], + aux_coeffs[2], + aux_coeffs[4], aux_coeffs[3], + aux_coeffs[5], + deg_aux, + ys); // Find the intersection point which is nearest the given approximation // and set it as the endpoint. @@ -667,8 +667,7 @@ public: nt_traits.convert(base_coeffs[4]) * ys[j] + nt_traits.convert(base_coeffs[5]); - if (CGAL::sign(val) != ZERO) - continue; + if (CGAL::sign(val) != ZERO) continue; val = nt_traits.convert(aux_coeffs[0]) * xs[i]*xs[i] + nt_traits.convert(aux_coeffs[1]) * ys[j]*ys[j] + @@ -749,7 +748,7 @@ public: // Duplicate the extra data, if necessary. m_extra_data = (arc.m_extra_data != nullptr) ? - new Extra_data(*(arc.m_extra_data)) ? nullptr; + new Extra_data(*(arc.m_extra_data)) : nullptr; return (*this); } @@ -764,12 +763,12 @@ public: /*! Get the coefficients of the underlying conic. */ - const Integer& r() const {return (m_r);} - const Integer& s() const {return (m_s);} - const Integer& t() const {return (m_t);} - const Integer& u() const {return (m_u);} - const Integer& v() const {return (m_v);} - const Integer& w() const {return (m_w);} + const Integer& r() const { return (m_r); } + const Integer& s() const { return (m_s); } + const Integer& t() const { return (m_t); } + const Integer& u() const { return (m_u); } + const Integer& v() const { return (m_v); } + const Integer& w() const { return (m_w); } /*! Check whether the arc is x-monotone. */ diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_intersections_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_intersections_2.h index 79049ca3977..1ea27a61b22 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_intersections_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_intersections_2.h @@ -8,7 +8,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Ron Wein +// Author(s): Ron Wein #ifndef CGAL_CONIC_INTERSECTIONS_2_H #define CGAL_CONIC_INTERSECTIONS_2_H @@ -24,8 +24,7 @@ namespace CGAL { -/*! - * Compute the roots of the resultants of the two bivariate polynomials: +/*! Compute the roots of the resultants of the two bivariate polynomials: * C1: r1*x^2 + s1*y^2 + t1*xy + u1*x + v1*y + w1 = 0 * C2: r2*x^2 + s2*y^2 + t2*xy + u2*x + v2*y + w2 = 0 * \param deg1 The degree of the first curve. @@ -35,84 +34,76 @@ namespace CGAL { * \pre xs must be a vector of size 4. * \return The number of distinct roots found. */ -template -int - _compute_resultant_roots (Nt_traits& nt_traits, - const typename Nt_traits::Integer& r1, - const typename Nt_traits::Integer& s1, - const typename Nt_traits::Integer& t1, - const typename Nt_traits::Integer& u1, - const typename Nt_traits::Integer& v1, - const typename Nt_traits::Integer& w1, - const int& deg1, - const typename Nt_traits::Integer& r2, - const typename Nt_traits::Integer& s2, - const typename Nt_traits::Integer& t2, - const typename Nt_traits::Integer& u2, - const typename Nt_traits::Integer& v2, - const typename Nt_traits::Integer& w2, - const int& deg2, - typename Nt_traits::Algebraic *xs) +template +int compute_resultant_roots(Nt_traits& nt_traits, + const typename Nt_traits::Integer& r1, + const typename Nt_traits::Integer& s1, + const typename Nt_traits::Integer& t1, + const typename Nt_traits::Integer& u1, + const typename Nt_traits::Integer& v1, + const typename Nt_traits::Integer& w1, + const int& deg1, + const typename Nt_traits::Integer& r2, + const typename Nt_traits::Integer& s2, + const typename Nt_traits::Integer& t2, + const typename Nt_traits::Integer& u2, + const typename Nt_traits::Integer& v2, + const typename Nt_traits::Integer& w2, + const int& deg2, + typename Nt_traits::Algebraic* xs) { - if (deg1 == 2 && deg2 == 1) - { + if ((deg1 == 2) && (deg2 == 1)) { // If necessary, swap roles between the two curves, so that the first // curve always has the minimal degree. - return (_compute_resultant_roots (nt_traits, - r2, s2, t2, u2, v2, w2, - deg2, - r1, s1, t1, u1, v1, w1, - deg1, - xs)); + return (compute_resultant_roots(nt_traits, + r2, s2, t2, u2, v2, w2, + deg2, + r1, s1, t1, u1, v1, w1, + deg1, + xs)); } // Act according to the degree of the first conic curve. - const typename Nt_traits::Integer _two = 2; - typename Nt_traits::Integer c[5]; - unsigned int degree = 4; - typename Nt_traits::Algebraic *xs_end; + const typename Nt_traits::Integer two = 2; + typename Nt_traits::Integer c[5]; + unsigned int degree = 4; + typename Nt_traits::Algebraic* xs_end; - if (deg1 == 1) - { + if (deg1 == 1) { // The first curve has no quadratic coefficients, and represents a line. - if (CGAL::sign (v1) == ZERO) - { + if (CGAL::sign (v1) == ZERO) { // The first line is u1*x + w1 = 0, therefore: xs[0] = nt_traits.convert(-w1) / nt_traits.convert(u1); - return (1); + return 1; } // We can write the first curve as: y = -(u1*x + w1) / v1. - if (deg2 == 1) - { + if (deg2 == 1) { // The second curve is also a line. We therefore get the linear // equation c[1]*x + c[0] = 0: c[1] = v1*u2 - u1*v2; c[0] = v1*w2 - w1*v2; - if (CGAL::sign (c[1]) == ZERO) - // The two lines are parallel: - return (0); + // Return if the two lines are parallel + if (CGAL::sign (c[1]) == ZERO) return 0; - xs[0] = nt_traits.convert(-c[0]) / nt_traits.convert(c[1]); - return (1); + xs[0] = nt_traits.convert(-c[0]) / nt_traits.convert(c[1]); + return 1; } // We substitute this expression into the equation of the second // conic, and get the quadratic equation c[2]*x^2 + c[1]*x + c[0] = 0: c[2] = u1*u1*s2 - u1*v1*t2 + v1*v1*r2; - c[1] = _two*u1*w1*s2 - u1*v1*v2 - v1*w1*t2 + v1*v1*u2; + c[1] = two*u1*w1*s2 - u1*v1*v2 - v1*w1*t2 + v1*v1*u2; c[0] = w1*w1*s2 - v1*w1*v2 + v1*v1*w2; - xs_end = nt_traits.solve_quadratic_equation (c[2], c[1], c[0], - xs); + xs_end = nt_traits.solve_quadratic_equation(c[2], c[1], c[0], xs); return static_cast(xs_end - xs); } // At this stage, both curves have degree 2. We obtain a qaurtic polynomial // whose roots are the x-coordinates of the intersection points. - if (CGAL::sign (s1) == ZERO && CGAL::sign (s2) == ZERO) - { + if (CGAL::sign (s1) == ZERO && CGAL::sign (s2) == ZERO) { // If both s1 and s2 are zero, we can write the two curves as: // C1: (t1*x + v1)*y + (r1*x^2 + u1*x + w1) = 0 // C2: (t2*x + v2)*y + (r2*x^2 + u2*x + w2) = 0 @@ -125,41 +116,40 @@ int degree = 3; } - else - { + else { // We can write the two curves as: // C1: (s1)*y^2 + (t1*x + v1)*y + (r1*x^2 + u1*x + w1) = 0 // C2: (s2)*y^2 + (t2*x + v2)*y + (r2*x^2 + u2*x + w2) = 0 // By writing the resultant of these two polynomials we get a quartic // polynomial, whose coefficients are given by: - c[4] = -_two*s1*s2*r1*r2 + s1*t2*t2*r1 - s1*t2*t1*r2 + + c[4] = -two*s1*s2*r1*r2 + s1*t2*t2*r1 - s1*t2*t1*r2 + s1*s1*r2*r2 - s2*t1*r1*t2 + s2*t1*t1*r2 + s2*s2*r1*r1; c[3] = -t2*r1*v1*s2 - u2*t1*t2*s1 - v2*r1*t1*s2 - - r2*t1*v2*s1 - _two*s1*s2*r1*u2 - t2*u1*t1*s2 + u2*t1*t1*s2 - - r2*v1*t2*s1 + u1*t2*t2*s1 + _two*v2*r1*t2*s1 + _two*u2*r2*s1*s1 + - _two*r2*v1*t1*s2 + _two*u1*r1*s2*s2 - _two*s1*s2*u1*r2; + r2*t1*v2*s1 - two*s1*s2*r1*u2 - t2*u1*t1*s2 + u2*t1*t1*s2 - + r2*v1*t2*s1 + u1*t2*t2*s1 + two*v2*r1*t2*s1 + two*u2*r2*s1*s1 + + two*r2*v1*t1*s2 + two*u1*r1*s2*s2 - two*s1*s2*u1*r2; - c[2] = -r2*v1*v2*s1 + u2*u2*s1*s1 + _two*w2*r2*s1*s1 + - _two*u2*v1*t1*s2 - u2*v1*t2*s1 + w2*t1*t1*s2 - _two*s1*s2*u1*u2 - + c[2] = -r2*v1*v2*s1 + u2*u2*s1*s1 + two*w2*r2*s1*s1 + + two*u2*v1*t1*s2 - u2*v1*t2*s1 + w2*t1*t1*s2 - two*s1*s2*u1*u2 - w2*t1*t2*s1 + v2*v2*r1*s1 + u1*u1*s2*s2 - v2*r1*v1*s2 + - _two*w1*r1*s2*s2 - u2*t1*v2*s1 - t2*u1*v1*s2 - _two*s1*s2*r1*w2 - - _two*s1*s2*w1*r2 + r2*v1*v1*s2 + w1*t2*t2*s1 - v2*u1*t1*s2 - - t2*w1*t1*s2 + _two*v2*u1*t2*s1; + two*w1*r1*s2*s2 - u2*t1*v2*s1 - t2*u1*v1*s2 - two*s1*s2*r1*w2 - + two*s1*s2*w1*r2 + r2*v1*v1*s2 + w1*t2*t2*s1 - v2*u1*t1*s2 - + t2*w1*t1*s2 + two*v2*u1*t2*s1; - c[1] = _two*w2*u2*s1*s1 + _two*w2*v1*t1*s2 - w2*v1*t2*s1 + - _two*v2*w1*t2*s1 + _two*w1*u1*s2*s2 - v2*u1*v1*s2 - _two*s1*s2*u1*w2 - + c[1] = two*w2*u2*s1*s1 + two*w2*v1*t1*s2 - w2*v1*t2*s1 + + two*v2*w1*t2*s1 + two*w1*u1*s2*s2 - v2*u1*v1*s2 - two*s1*s2*u1*w2 - v2*w1*t1*s2 + u2*v1*v1*s2 - t2*w1*v1*s2 - w2*t1*v2*s1 + - v2*v2*u1*s1 - u2*v1*v2*s1 - _two*s1*s2*w1*u2; + v2*v2*u1*s1 - u2*v1*v2*s1 - two*s1*s2*w1*u2; c[0] = s2*v1*v1*w2 - s1*v2*v1*w2 - s2*v1*w1*v2 + s2*s2*w1*w1 - - _two*s1*s2*w1*w2 + s1*w1*v2*v2 + s1*s1*w2*w2; + two*s1*s2*w1*w2 + s1*w1*v2*v2 + s1*s1*w2*w2; degree = 4; } // Compute the roots of the resultant polynomial. - typename Nt_traits::Polynomial poly = + typename Nt_traits::Polynomial poly = nt_traits.construct_polynomial (c, degree); xs_end = nt_traits.compute_polynomial_roots (poly, @@ -167,8 +157,7 @@ int return static_cast(xs_end - xs); } -/*! - * Compute the roots of the resultants of the two bivariate polynomials: +/*! Compute the roots of the resultants of the two bivariate polynomials: * C1: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0 * C2: A*x + B*y + C = 0 * \param deg1 The degree of the first curve. @@ -177,55 +166,50 @@ int * \pre xs must be a vector of size 4. * \return The number of distinct roots found. */ -template -int -_compute_resultant_roots (Nt_traits& nt_traits, - const typename Nt_traits::Algebraic& r, - const typename Nt_traits::Algebraic& s, - const typename Nt_traits::Algebraic& t, - const typename Nt_traits::Algebraic& u, - const typename Nt_traits::Algebraic& v, - const typename Nt_traits::Algebraic& w, - const int& deg1, - const typename Nt_traits::Algebraic& A, - const typename Nt_traits::Algebraic& B, - const typename Nt_traits::Algebraic& C, - typename Nt_traits::Algebraic *xs) +template +int compute_resultant_roots(Nt_traits& nt_traits, + const typename Nt_traits::Algebraic& r, + const typename Nt_traits::Algebraic& s, + const typename Nt_traits::Algebraic& t, + const typename Nt_traits::Algebraic& u, + const typename Nt_traits::Algebraic& v, + const typename Nt_traits::Algebraic& w, + const int& deg1, + const typename Nt_traits::Algebraic& A, + const typename Nt_traits::Algebraic& B, + const typename Nt_traits::Algebraic& C, + typename Nt_traits::Algebraic* xs) { - if (deg1 == 1) - { + if (deg1 == 1) { // We should actually compute the intersection of two line: // (u*x + v*y + w = 0) and (A*x + B*y + C = 0): - const typename Nt_traits::Algebraic denom = A*v - B*u; + const typename Nt_traits::Algebraic denom = A*v - B*u; - if (CGAL::sign (denom) == CGAL::ZERO) - // The two lines are parallel and do not intersect. - return (0); + // Return if the two lines are parallel and do not intersect. + if (CGAL::sign(denom) == CGAL::ZERO) return 0; xs[0] = (B*w - C*v) / denom; - return (1); + return 1; } - if (CGAL::sign (B) == CGAL::ZERO) - { + if (CGAL::sign(B) == CGAL::ZERO) { // The first line is A*x + C = 0, therefore: xs[0] = -C / A; - return (1); + return 1; } // We can write the first curve as: y = -(A*x + C) / B. // We substitute this expression into the equation of the conic, and get // the quadratic equation c[2]*x^2 + c[1]*x + c[0] = 0: - const typename Nt_traits::Algebraic _two = 2; - typename Nt_traits::Algebraic c[3]; - typename Nt_traits::Algebraic *xs_end; + const typename Nt_traits::Algebraic two = 2; + typename Nt_traits::Algebraic c[3]; + typename Nt_traits::Algebraic* xs_end; c[2] = A*A*s - A*B*t + B*B*r; - c[1] = _two*A*C*s - A*B*v - B*C*t + B*B*u; + c[1] = two*A*C*s - A*B*v - B*C*t + B*B*u; c[0] = C*C*s - B*C*v + B*B*w; - xs_end = nt_traits.solve_quadratic_equation (c[2], c[1], c[0], - xs); + xs_end = nt_traits.solve_quadratic_equation(c[2], c[1], c[0], xs); return static_cast(xs_end - xs); } diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h index ad13fe00427..ecd98ee490f 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h @@ -50,37 +50,34 @@ public: typedef std::pair Intersection_point; typedef std::list Intersection_list; - using Conic_arc_2::_sign_of_extra_data; - using Conic_arc_2::_is_between_endpoints; - using Conic_arc_2::_is_strictly_between_endpoints; - using Conic_arc_2::_conic_get_y_coordinates; + using Conic_arc_2::sign_of_extra_data; + using Conic_arc_2::is_between_endpoints; + using Conic_arc_2::is_strictly_between_endpoints; + using Conic_arc_2::conic_get_y_coordinates; /*! * \struct Less functor for Conic_pair. */ struct Less_conic_pair { - bool operator()(const Conic_pair& cp1, const Conic_pair& cp2) const - { + bool operator()(const Conic_pair& cp1, const Conic_pair& cp2) const { // Compare the pairs of IDs lexicographically. return ((cp1.first < cp2.first) || ((cp1.first == cp2.first) && (cp1.second < cp2.second))); } }; - typedef std::map Intersection_map; + typedef std::map + Intersection_map; typedef typename Intersection_map::value_type Intersection_map_entry; typedef typename Intersection_map::iterator Intersection_map_iterator; protected: - typedef Conic_arc_2 Base; typedef typename Conic_arc_2::Integer Integer; typedef typename Conic_arc_2::Nt_traits Nt_traits; typedef typename Conic_arc_2::Rat_kernel Rat_kernel; - // Bit masks for the _info field (the two least significant bits are already + // Bit masks for the m_info field (the two least significant bits are already // used by the base class). enum { IS_VERTICAL_SEGMENT = 4, @@ -102,7 +99,7 @@ protected: Algebraic alg_v; // converted to algebraic numbers. Algebraic alg_w; // - Conic_id _id; // The ID number of the supporting conic curve. + Conic_id m_id; // The ID number of the supporting conic curve. public: @@ -114,7 +111,7 @@ public: */ _Conic_x_monotone_arc_2 () : Base(), - _id() + m_id() {} /*! @@ -129,7 +126,7 @@ public: alg_u(arc.alg_u), alg_v(arc.alg_v), alg_w(arc.alg_w), - _id(arc._id) + m_id(arc.m_id) {} /*! Construct an x-monotone arc from a conic arc. @@ -138,10 +135,10 @@ public: */ _Conic_x_monotone_arc_2(const Base& arc) : Base(arc), - _id() + m_id() { CGAL_precondition(arc.is_valid() && arc.is_x_monotone()); - _set (); + set(); } /*! Construct an x-monotone arc from a conic arc. @@ -150,10 +147,10 @@ public: */ _Conic_x_monotone_arc_2(const Base& arc, const Conic_id& id) : Base(arc), - _id(id) + m_id(id) { CGAL_precondition(arc.is_valid() && id.is_valid()); - _set (); + set(); } /*! Construct an x-monotone sub-arc from a conic arc. @@ -166,15 +163,15 @@ public: const Point_2& source, const Point_2& target, const Conic_id& id) : Base(arc), - _id(id) + m_id(id) { CGAL_precondition(arc.is_valid() && id.is_valid()); // Set the two endpoints. - this->_source = source; - this->_target = target; + this->m_source = source; + this->m_target = target; - _set(); + set(); } /*! Construct a special segment connecting to given endpoints (for the usage @@ -185,23 +182,22 @@ public: _Conic_x_monotone_arc_2(const Point_2& source, const Point_2& target) : Base(source, target) { - this->_info |= static_cast(DEGREE_1); + this->m_info |= static_cast(DEGREE_1); Alg_kernel ker; auto cmp_xy = ker.compare_xy_2_object(); - Comparison_result dir_res = cmp_xy(this->_source, this->_target); - if (dir_res == SMALLER) this->_info |= IS_DIRECTED_RIGHT; + Comparison_result dir_res = cmp_xy(this->m_source, this->m_target); + if (dir_res == SMALLER) this->m_info |= IS_DIRECTED_RIGHT; // Check if the segment is vertical. - if (CGAL::sign(this->_extra_data_P->b) == ZERO) - this->_info |= IS_VERTICAL_SEGMENT; + if (CGAL::sign(this->m_extra_data->b) == ZERO) + this->m_info |= IS_VERTICAL_SEGMENT; // Mark that this is a special segment. - this->_info |= IS_SPECIAL_SEGMENT; + this->m_info |= IS_SPECIAL_SEGMENT; } - /*! - * Construct a special segment of a given line connecting to given + /*! Construct a special segment of a given line connecting to given * endpoints. * \param a, b, c The coefficients of the supporting line (ax + by + c = 0). * \param source The source point. @@ -214,52 +210,53 @@ public: Base() { // Make sure the two endpoints lie on the supporting line. - CGAL_precondition(CGAL::sign(a * source.x() + - b * source.y() + c) == CGAL::ZERO); + CGAL_precondition + (CGAL::sign(a * source.x() + b * source.y() + c) == CGAL::ZERO); - CGAL_precondition(CGAL::sign(a * target.x() + - b * target.y() + c) == CGAL::ZERO); + CGAL_precondition + (CGAL::sign(a * target.x() + b * target.y() + c) == CGAL::ZERO); - // Set the basic properties and clear the _info bits. - this->_source = source; - this->_target = target; - this->_orient = COLLINEAR; - this->_info = 0; + // Set the basic properties and clear the m_info bits. + this->m_source = source; + this->m_target = target; + this->m_orient = COLLINEAR; + this->m_info = 0; // Check if the arc is directed right (the target is lexicographically // greater than the source point), or to the left. Alg_kernel ker; Comparison_result res = - ker.compare_x_2_object()(this->_source, this->_target); + ker.compare_x_2_object()(this->m_source, this->m_target); - this->_info = (static_cast(Conic_arc_2::IS_VALID) | static_cast(DEGREE_1)); + this->m_info = + (static_cast(Conic_arc_2::IS_VALID) | static_cast(DEGREE_1)); if (res == EQUAL) { // Mark that the segment is vertical. - this->_info = (this->_info | IS_VERTICAL_SEGMENT); + this->m_info = (this->m_info | IS_VERTICAL_SEGMENT); // Compare the endpoints lexicographically. - res = ker.compare_y_2_object()(this->_source, this->_target); + res = ker.compare_y_2_object()(this->m_source, this->m_target); CGAL_precondition (res != EQUAL); if (res == EQUAL) { // Invalid arc: - this->_info = 0; + this->m_info = 0; return; } } if (res == SMALLER) - this->_info = (this->_info | IS_DIRECTED_RIGHT); + this->m_info = (this->m_info | IS_DIRECTED_RIGHT); // Store the coefficients of the line. - this->_extra_data_P = new typename Base::Extra_data; - this->_extra_data_P->a = a; - this->_extra_data_P->b = b; - this->_extra_data_P->c = c; - this->_extra_data_P->side = ZERO; + this->m_extra_data = new typename Base::Extra_data; + this->m_extra_data->a = a; + this->m_extra_data->b = b; + this->m_extra_data->c = c; + this->m_extra_data->side = ZERO; // Mark that this is a special segment. - this->_info = (this->_info | IS_SPECIAL_SEGMENT); + this->m_info = (this->m_info | IS_SPECIAL_SEGMENT); return; } @@ -268,8 +265,7 @@ public: * Assignment operator. * \param arc The copied arc. */ - const Self& operator=(const Self& arc) - { + const Self& operator=(const Self& arc) { CGAL_precondition (arc.is_valid()); if (this == &arc) return (*this); @@ -285,7 +281,7 @@ public: alg_v = arc.alg_v; alg_w = arc.alg_w; - _id = arc._id; + m_id = arc.m_id; return (*this); } @@ -297,51 +293,49 @@ public: /*! * Get the coefficients of the underlying conic. */ - const Integer& r() const { return (this->_r); } - const Integer& s() const { return (this->_s); } - const Integer& t() const { return (this->_t); } - const Integer& u() const { return (this->_u); } - const Integer& v() const { return (this->_v); } - const Integer& w() const { return (this->_w); } + const Integer& r() const { return (this->m_r); } + const Integer& s() const { return (this->m_s); } + const Integer& t() const { return (this->m_t); } + const Integer& u() const { return (this->m_u); } + const Integer& v() const { return (this->m_v); } + const Integer& w() const { return (this->m_w); } /*! * Get the arc's source. * \return The source point. */ - const Conic_point_2& source() const { return (this->_source); } + const Conic_point_2& source() const { return (this->m_source); } /*! Get the arc's target. * \return The target point. */ - const Conic_point_2& target() const { return (this->_target); } + const Conic_point_2& target() const { return (this->m_target); } /*! Get the orientation of the arc. * \return The orientation. */ - Orientation orientation() const { return (this->_orient); } + Orientation orientation() const { return (this->m_orient); } /*! Get the left endpoint of the arc. */ - const Conic_point_2& left () const - { - if ((this->_info & IS_DIRECTED_RIGHT) != 0) return (this->_source); - else return (this->_target); + const Conic_point_2& left() const { + if ((this->m_info & IS_DIRECTED_RIGHT) != 0) return (this->m_source); + else return (this->m_target); } - /*! - * Get the right endpoint of the arc. + /*! Get the right endpoint of the arc. */ - const Conic_point_2& right () const + const Conic_point_2& right() const { - if ((this->_info & IS_DIRECTED_RIGHT) != 0) return (this->_target); - else return (this->_source); + if ((this->m_info & IS_DIRECTED_RIGHT) != 0) return (this->m_target); + else return (this->m_source); } /*! * Return true iff the conic arc is directed right iexicographically. */ bool is_directed_right() const - { return ((this->_info & IS_DIRECTED_RIGHT) != 0); } + { return ((this->m_info & IS_DIRECTED_RIGHT) != 0); } /*! * Get a bounding box for the conic arc. @@ -356,76 +350,67 @@ public: /*! * Check if the conic arc is a vertical segment. */ - bool is_vertical () const - { - return ((this->_info & IS_VERTICAL_SEGMENT) != 0); - } + bool is_vertical() const + { return ((this->m_info & IS_VERTICAL_SEGMENT) != 0); } /*! * Check whether the given point lies on the arc. * \param p The qury point. * \param (true) if p lies on the arc; (false) otherwise. */ - bool contains_point(const Conic_point_2& p) const - { + bool contains_point(const Conic_point_2& p) const { // First check if p lies on the supporting conic. We first check whether // it is one of p's generating conic curves. - bool p_on_conic = false; + bool p_on_conic = false; - if (p.is_generating_conic(_id)) { + if (p.is_generating_conic(m_id)) { p_on_conic = true; } else { // Check whether p satisfies the supporting conic equation. - p_on_conic = _is_on_supporting_conic(p.x(), p.y()); + p_on_conic = is_on_supporting_conic(p.x(), p.y()); if (p_on_conic) { // As p lies on the supporting conic of our arc, add its ID to // the list of generating conics for p. - Conic_point_2& p_non_const = const_cast (p); - p_non_const.set_generating_conic (_id); + Conic_point_2& p_non_const = const_cast(p); + p_non_const.set_generating_conic(m_id); } } - if (! p_on_conic) - return (false); + if (! p_on_conic) return (false); // Check if p is between the endpoints of the arc. - return (_is_between_endpoints (p)); + return is_between_endpoints(p); } //@} /// \name Constructing points on the arc. //@{ - /*! - * Compute a point on the arc with the same x-coordiante as the given point. + /*! Compute a point on the arc with the same x-coordiante as the given point. * \param p The given point. * \pre The arc is not vertical and p is in the x-range of the arc. * \return A point on the arc with the same x-coordiante as p. */ - Point_2 point_at_x (const Point_2& p) const - { + Point_2 point_at_x(const Point_2& p) const { // Make sure that p is in the x-range of the arc. - CGAL_precondition ((this->_info & IS_VERTICAL_SEGMENT) == 0); + CGAL_precondition((this->m_info & IS_VERTICAL_SEGMENT) == 0); - CGAL_precondition_code ( - Alg_kernel ker; - ); + CGAL_precondition_code(Alg_kernel ker;); CGAL_precondition(ker.compare_x_2_object() (p, left()) != SMALLER && ker.compare_x_2_object() (p, right()) != LARGER); - if (_is_special_segment()) { + if (is_special_segment()) { // In case of a special segment, the equation of the supported line // (a*x + b*y + c) = 0 is stored with the extra data field, and we // simply have: - Algebraic _y = -(this->_extra_data_P->a*p.x() + - this->_extra_data_P->c) / - this->_extra_data_P->b; + Algebraic _y = -(this->m_extra_data->a*p.x() + this->m_extra_data->c) / + this->m_extra_data->b; // Return the computed point. - return (Point_2 (p.x(), _y)); + return Point_2 (p.x(), _y); } // Compute the y-coordinate according to the degree of the supporting @@ -433,22 +418,22 @@ public: Nt_traits nt_traits; Algebraic y; - if ((this->_info & DEGREE_MASK) == DEGREE_1) { + if ((this->m_info & DEGREE_MASK) == DEGREE_1) { // In case of a linear curve, the y-coordinate is a simple linear // expression of x(p) (note that v is not 0 as the arc is not vertical): // y = -(u*x(p) + w) / v y = -(alg_u*p.x() + alg_w) / alg_v; } - else if (this->_orient == COLLINEAR) { - CGAL_assertion (this->_extra_data_P != nullptr); + else if (this->m_orient == COLLINEAR) { + CGAL_assertion (this->m_extra_data != nullptr); // In this case the equation of the supporting line is given by the // extra data structure. - y = -(this->_extra_data_P->a * p.x() + - this->_extra_data_P->c) / this->_extra_data_P->b; + y = -(this->m_extra_data->a * p.x() + + this->m_extra_data->c) / this->m_extra_data->b; } else { - CGAL_assertion((this->_info & DEGREE_MASK) == DEGREE_2); + CGAL_assertion((this->m_info & DEGREE_MASK) == DEGREE_2); // In this case the y-coordinate is one of solutions to the quadratic // equation: @@ -457,7 +442,7 @@ public: Algebraic B = alg_t*p.x() + alg_v; Algebraic C = (alg_r*p.x() + alg_u)*p.x() + alg_w; - if (CGAL::sign(this->_s) == ZERO) { + if (CGAL::sign(this->m_s) == ZERO) { // In this case A is 0 and we have a linear equation. CGAL_assertion (CGAL::sign (B) != ZERO); @@ -471,7 +456,7 @@ public: // We take either the root involving -sqrt(disc) or +sqrt(disc) // based on the information flags. - if ((this->_info & PLUS_SQRT_DISC_ROOT) != 0) { + if ((this->m_info & PLUS_SQRT_DISC_ROOT) != 0) { y = (nt_traits.sqrt (disc) - B) / (2*A); } else { @@ -481,11 +466,10 @@ public: } // Return the computed point. - return (Point_2 (p.x(), y)); + return Point_2(p.x(), y); } - /*! - * Get a polyline approximating the conic arc. + /*! Get a polyline approximating the conic arc. * \param n The maximal number of sample points. * \param oi An output iterator, whose value-type is pair * (representing an approximated point). @@ -494,10 +478,8 @@ public: * (p_0, p_1, ..., p_n), where p_0 and p_n are the left and right * endpoints of the arc, respectively. */ - template - OutputIterator polyline_approximation (size_t n, - OutputIterator oi) const - { + template + OutputIterator polyline_approximation(size_t n, OutputIterator oi) const { CGAL_precondition (n != 0); const double x_left = CGAL::to_double (left().x()); @@ -505,7 +487,7 @@ public: const double x_right = CGAL::to_double (right().x()); const double y_right = CGAL::to_double (right().y()); - if (this->_orient == COLLINEAR) { + if (this->m_orient == COLLINEAR) { // In case of a line segment, return the two endpoints. *oi++ = std::pair (x_left, y_left); *oi++ = std::pair (x_right, y_right); @@ -513,46 +495,37 @@ public: } // Otherwise, sample (n - 1) equally-spaced points in between. - const double app_r = CGAL::to_double (this->_r); - const double app_s = CGAL::to_double (this->_s); - const double app_t = CGAL::to_double (this->_t); - const double app_u = CGAL::to_double (this->_u); - const double app_v = CGAL::to_double (this->_v); - const double app_w = CGAL::to_double (this->_w); + const double app_r = CGAL::to_double (this->m_r); + const double app_s = CGAL::to_double (this->m_s); + const double app_t = CGAL::to_double (this->m_t); + const double app_u = CGAL::to_double (this->m_u); + const double app_v = CGAL::to_double (this->m_v); + const double app_w = CGAL::to_double (this->m_w); const double x_jump = (x_right - x_left) / n; - double x, y; - const bool A_is_zero = (CGAL::sign(this->_s) == ZERO); - double A = app_s, B, C; - double disc; - size_t i; + double x, y; + const bool A_is_zero = (CGAL::sign(this->m_s) == ZERO); + double A = app_s, B, C; + double disc; + size_t i; - *oi = std::pair(x_left, y_left); // The left point. - ++oi; - for (i = 1; i < n; i++) { + *oi++ = std::pair(x_left, y_left); // The left point. + for (i = 1; i < n; ++i) { x = x_left + x_jump*i; // Solve the quadratic equation: A*x^2 + B*x + C = 0: B = app_t*x + app_v; C = (app_r*x + app_u)*x + app_w; - if (A_is_zero) { - y = -C / B; - } + if (A_is_zero) y = -C / B; else { disc = B*B - 4*A*C; - if (disc < 0) disc = 0; // We take either the root involving -sqrt(disc) or +sqrt(disc) // based on the information flags. - if ((this->_info & PLUS_SQRT_DISC_ROOT) != 0) { - y = (std::sqrt(disc) - B) / (2*A); - } - else { - y = -(B + std::sqrt (disc)) / (2*A); - } + y = ((this->m_info & PLUS_SQRT_DISC_ROOT) != 0) ? + (std::sqrt(disc) - B) / (2*A) : -(B + std::sqrt (disc)) / (2*A); } - *oi++ = std::pair (x, y); } *oi++ = std::pair (x_right, y_right); // The right point. @@ -566,23 +539,23 @@ public: * \return The relative position of the arcs to the right of p. * \pre Both arcs we compare are not vertical segments. */ - Comparison_result compare_to_right(const Self& arc, - const Conic_point_2& p) const + Comparison_result compare_to_right(const Self& arc, const Conic_point_2& p) + const { - CGAL_precondition((this->_info & IS_VERTICAL_SEGMENT) == 0 && - (arc._info & IS_VERTICAL_SEGMENT) == 0); + CGAL_precondition((this->m_info & IS_VERTICAL_SEGMENT) == 0 && + (arc.m_info & IS_VERTICAL_SEGMENT) == 0); // In case one arc is facing upwards and another facing downwards, it is // clear that the one facing upward is above the one facing downwards. - if (_has_same_supporting_conic (arc)) { - if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_DOWN) != 0) + if (has_same_supporting_conic (arc)) { + if ((this->m_info & FACING_UP) != 0 && (arc.m_info & FACING_DOWN) != 0) return LARGER; - else if ((this->_info & FACING_DOWN) != 0 && (arc._info & FACING_UP) != 0) + else if ((this->m_info & FACING_DOWN) != 0 && (arc.m_info & FACING_UP) != + 0) return SMALLER; // In this case the two arcs overlap. - CGAL_assertion((this->_info & FACING_MASK) == (arc._info & FACING_MASK)); - + CGAL_assertion((this->m_info & FACING_MASK) == (arc.m_info & FACING_MASK)); return EQUAL; } @@ -591,14 +564,14 @@ public: Algebraic slope1_numer, slope1_denom; Algebraic slope2_numer, slope2_denom; - _derive_by_x_at (p, 1, slope1_numer, slope1_denom); - arc._derive_by_x_at (p, 1, slope2_numer, slope2_denom); + derive_by_x_at(p, 1, slope1_numer, slope1_denom); + arc.derive_by_x_at(p, 1, slope2_numer, slope2_denom); // Check if any of the slopes is vertical. const bool is_vertical_slope1 = (CGAL::sign(slope1_denom) == ZERO); const bool is_vertical_slope2 = (CGAL::sign(slope2_denom) == ZERO); - if (!is_vertical_slope1 && !is_vertical_slope2) { + if (! is_vertical_slope1 && !is_vertical_slope2) { // The two derivatives at p are well-defined: use them to determine // which arc is above the other (the one with a larger slope is below). Comparison_result slope_res = @@ -607,8 +580,8 @@ public: if (slope_res != EQUAL) return (slope_res); // Use the second-order derivative. - _derive_by_x_at(p, 2, slope1_numer, slope1_denom); - arc._derive_by_x_at(p, 2, slope2_numer, slope2_denom); + derive_by_x_at(p, 2, slope1_numer, slope1_denom); + arc.derive_by_x_at(p, 2, slope2_numer, slope2_denom); slope_res = CGAL::compare(slope1_numer*slope2_denom, slope2_numer*slope1_denom); @@ -616,45 +589,45 @@ public: if (slope_res != EQUAL) return (slope_res); // Use the third-order derivative. - _derive_by_x_at(p, 3, slope1_numer, slope1_denom); - arc._derive_by_x_at(p, 3, slope2_numer, slope2_denom); + derive_by_x_at(p, 3, slope1_numer, slope1_denom); + arc.derive_by_x_at(p, 3, slope2_numer, slope2_denom); slope_res = CGAL::compare(slope1_numer*slope2_denom, slope2_numer*slope1_denom); // \todo Handle higher-order derivatives: - CGAL_assertion (slope_res != EQUAL); + CGAL_assertion(slope_res != EQUAL); - return (slope_res); + return slope_res; } - else if (!is_vertical_slope2) { + else if ( !is_vertical_slope2) { // The first arc has a vertical slope at p: check whether it is // facing upwards or downwards and decide accordingly. - CGAL_assertion ((this->_info & FACING_MASK) != 0); + CGAL_assertion ((this->m_info & FACING_MASK) != 0); - if ((this->_info & FACING_UP) != 0) return (LARGER); + if ((this->m_info & FACING_UP) != 0) return LARGER; return SMALLER; } - else if (!is_vertical_slope1) { + else if (! is_vertical_slope1) { // The second arc has a vertical slope at p_int: check whether it is // facing upwards or downwards and decide accordingly. - CGAL_assertion ((arc._info & FACING_MASK) != 0); + CGAL_assertion ((arc.m_info & FACING_MASK) != 0); - if ((arc._info & FACING_UP) != 0) return (SMALLER); + if ((arc.m_info & FACING_UP) != 0) return SMALLER; return LARGER; } // The two arcs have vertical slopes at p_int: // First check whether one is facing up and one down. In this case the // comparison result is trivial. - if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_DOWN) != 0) + if ((this->m_info & FACING_UP) != 0 && (arc.m_info & FACING_DOWN) != 0) return (LARGER); - else if ((this->_info & FACING_DOWN) != 0 && (arc._info & FACING_UP) != 0) + else if ((this->m_info & FACING_DOWN) != 0 && (arc.m_info & FACING_UP) != 0) return SMALLER; // Compute the second-order derivative by y and act according to it. - _derive_by_y_at (p, 2, slope1_numer, slope1_denom); - arc._derive_by_y_at (p, 2, slope2_numer, slope2_denom); + derive_by_y_at (p, 2, slope1_numer, slope1_denom); + arc.derive_by_y_at (p, 2, slope2_numer, slope2_denom); Comparison_result slope_res = CGAL::compare(slope1_numer*slope2_denom, slope2_numer*slope1_denom); @@ -662,8 +635,8 @@ public: // If necessary, use the third-order derivative by y. if (slope_res == EQUAL) { // \todo Check this! - _derive_by_y_at(p, 3, slope1_numer, slope1_denom); - arc._derive_by_y_at(p, 3, slope2_numer, slope2_denom); + derive_by_y_at(p, 3, slope1_numer, slope1_denom); + arc.derive_by_y_at(p, 3, slope2_numer, slope2_denom); slope_res = CGAL::compare(slope2_numer*slope1_denom, slope1_numer*slope2_denom); @@ -672,37 +645,37 @@ public: // \todo Handle higher-order derivatives: CGAL_assertion(slope_res != EQUAL); - if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_UP) != 0) { + if ((this->m_info & FACING_UP) != 0 && (arc.m_info & FACING_UP) != 0) { // Both are facing up. return ((slope_res == LARGER) ? SMALLER : LARGER); } // Both are facing down. - return (slope_res); + return slope_res; } - /*! - * Compare to arcs immediately to the leftt of their intersection point. + /*! Compare to arcs immediately to the leftt of their intersection point. * \param arc The compared arc. * \param p The reference intersection point. * \return The relative position of the arcs to the left of p. * \pre Both arcs we compare are not vertical segments. */ - Comparison_result compare_to_left(const Self& arc, - const Conic_point_2& p) const + Comparison_result compare_to_left(const Self& arc, const Conic_point_2& p) + const { - CGAL_precondition((this->_info & IS_VERTICAL_SEGMENT) == 0 && - (arc._info & IS_VERTICAL_SEGMENT) == 0); + CGAL_precondition((this->m_info & IS_VERTICAL_SEGMENT) == 0 && + (arc.m_info & IS_VERTICAL_SEGMENT) == 0); // In case one arc is facing upwards and another facing downwards, it is // clear that the one facing upward is above the one facing downwards. - if (_has_same_supporting_conic (arc)) { - if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_DOWN) != 0) + if (has_same_supporting_conic (arc)) { + if ((this->m_info & FACING_UP) != 0 && (arc.m_info & FACING_DOWN) != 0) return LARGER; - else if ((this->_info & FACING_DOWN) != 0 && (arc._info & FACING_UP) != 0) + else if ((this->m_info & FACING_DOWN) != 0 && (arc.m_info & FACING_UP) != + 0) return SMALLER; // In this case the two arcs overlap. - CGAL_assertion((this->_info & FACING_MASK) == (arc._info & FACING_MASK)); + CGAL_assertion((this->m_info & FACING_MASK) == (arc.m_info & FACING_MASK)); return EQUAL; } @@ -712,70 +685,70 @@ public: Algebraic slope1_numer, slope1_denom; Algebraic slope2_numer, slope2_denom; - _derive_by_x_at(p, 1, slope1_numer, slope1_denom); - arc._derive_by_x_at(p, 1, slope2_numer, slope2_denom); + derive_by_x_at(p, 1, slope1_numer, slope1_denom); + arc.derive_by_x_at(p, 1, slope2_numer, slope2_denom); // Check if any of the slopes is vertical. const bool is_vertical_slope1 = (CGAL::sign (slope1_denom) == ZERO); const bool is_vertical_slope2 = (CGAL::sign (slope2_denom) == ZERO); - if (!is_vertical_slope1 && !is_vertical_slope2) { + if (! is_vertical_slope1 && !is_vertical_slope2) { // The two derivatives at p are well-defined: use them to determine // which arc is above the other (the one with a larger slope is below). - Comparison_result slope_res = CGAL::compare(slope2_numer*slope1_denom, - slope1_numer*slope2_denom); + Comparison_result slope_res = CGAL::compare(slope2_numer*slope1_denom, + slope1_numer*slope2_denom); if (slope_res != EQUAL) return (slope_res); // Use the second-order derivative. - _derive_by_x_at (p, 2, slope1_numer, slope1_denom); - arc._derive_by_x_at (p, 2, slope2_numer, slope2_denom); + derive_by_x_at (p, 2, slope1_numer, slope1_denom); + arc.derive_by_x_at (p, 2, slope2_numer, slope2_denom); - slope_res = CGAL::compare (slope1_numer*slope2_denom, - slope2_numer*slope1_denom); + slope_res = CGAL::compare(slope1_numer*slope2_denom, + slope2_numer*slope1_denom); if (slope_res != EQUAL) return (slope_res); // Use the third-order derivative. - _derive_by_x_at(p, 3, slope1_numer, slope1_denom); - arc._derive_by_x_at(p, 3, slope2_numer, slope2_denom); + derive_by_x_at(p, 3, slope1_numer, slope1_denom); + arc.derive_by_x_at(p, 3, slope2_numer, slope2_denom); slope_res = CGAL::compare(slope2_numer*slope1_denom, slope1_numer*slope2_denom); // \todo Handle higher-order derivatives: - CGAL_assertion (slope_res != EQUAL); + CGAL_assertion(slope_res != EQUAL); return (slope_res); } - else if (!is_vertical_slope2) { + else if (! is_vertical_slope2) { // The first arc has a vertical slope at p: check whether it is // facing upwards or downwards and decide accordingly. - CGAL_assertion ((this->_info & FACING_MASK) != 0); + CGAL_assertion ((this->m_info & FACING_MASK) != 0); - if ((this->_info & FACING_UP) != 0) return (LARGER); + if ((this->m_info & FACING_UP) != 0) return LARGER; return SMALLER; } - else if (!is_vertical_slope1) { + else if (! is_vertical_slope1) { // The second arc has a vertical slope at p_int: check whether it is // facing upwards or downwards and decide accordingly. - CGAL_assertion ((arc._info & FACING_MASK) != 0); + CGAL_assertion((arc.m_info & FACING_MASK) != 0); - if ((arc._info & FACING_UP) != 0) return (SMALLER); + if ((arc.m_info & FACING_UP) != 0) return SMALLER; return LARGER; } // The two arcs have vertical slopes at p_int: // First check whether one is facing up and one down. In this case the // comparison result is trivial. - if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_DOWN) != 0) + if ((this->m_info & FACING_UP) != 0 && (arc.m_info & FACING_DOWN) != 0) return LARGER; - else if ((this->_info & FACING_DOWN) != 0 && (arc._info & FACING_UP) != 0) + else if ((this->m_info & FACING_DOWN) != 0 && (arc.m_info & FACING_UP) != 0) return SMALLER; // Compute the second-order derivative by y and act according to it. - _derive_by_y_at(p, 2, slope1_numer, slope1_denom); - arc._derive_by_y_at(p, 2, slope2_numer, slope2_denom); + derive_by_y_at(p, 2, slope1_numer, slope1_denom); + arc.derive_by_y_at(p, 2, slope2_numer, slope2_denom); Comparison_result slope_res = CGAL::compare(slope2_numer*slope1_denom, slope1_numer*slope2_denom); @@ -783,8 +756,8 @@ public: // If necessary, use the third-order derivative by y. if (slope_res == EQUAL) { // \todo Check this! - _derive_by_y_at(p, 3, slope1_numer, slope1_denom); - arc._derive_by_y_at(p, 3, slope2_numer, slope2_denom); + derive_by_y_at(p, 3, slope1_numer, slope1_denom); + arc.derive_by_y_at(p, 3, slope2_numer, slope2_denom); slope_res = CGAL::compare(slope2_numer*slope1_denom, slope1_numer*slope2_denom); @@ -793,7 +766,7 @@ public: // \todo Handle higher-order derivatives: CGAL_assertion(slope_res != EQUAL); - if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_UP) != 0) { + if ((this->m_info & FACING_UP) != 0 && (arc.m_info & FACING_UP) != 0) { // Both are facing up. return ((slope_res == LARGER) ? SMALLER : LARGER); } @@ -801,25 +774,23 @@ public: return (slope_res); } - /*! - * Compute the intersections with the given arc. + /*! Compute the intersections with the given arc. * \param arc The given intersecting arc. * \param inter_map Maps conic pairs to lists of their intersection points. * \param oi The output iterator. * \return The past-the-end iterator. */ template - OutputIterator intersect(const Self& arc, - Intersection_map& inter_map, + OutputIterator intersect(const Self& arc, Intersection_map& inter_map, OutputIterator oi) const { typedef boost::variant Intersection_result; - if (_has_same_supporting_conic(arc)) { + if (has_same_supporting_conic(arc)) { // Check for overlaps between the two arcs. Self overlap; - if (_compute_overlap(arc, overlap)) { + if (compute_overlap(arc, overlap)) { // There can be just a single overlap between two x-monotone arcs: *oi++ = Intersection_result(overlap); return oi; @@ -830,7 +801,7 @@ public: // an end point. // Note that in this case we do not define the multiplicity of the // intersection points we report. - Alg_kernel ker; + Alg_kernel ker; if (ker.equal_2_object()(left(), arc.left())) { Intersection_point ip(left(), 0); @@ -853,10 +824,10 @@ public: Intersection_list inter_list; bool invalid_ids = false; - if (_id.is_valid() && arc._id.is_valid()) { - if (_id < arc._id) conic_pair = Conic_pair (_id, arc._id); - else conic_pair = Conic_pair (arc._id, _id); - map_iter = inter_map.find (conic_pair); + if (m_id.is_valid() && arc.m_id.is_valid()) { + if (m_id < arc.m_id) conic_pair = Conic_pair(m_id, arc.m_id); + else conic_pair = Conic_pair(arc.m_id, m_id); + map_iter = inter_map.find(conic_pair); } else { // In case one of the IDs is invalid, we do not look in the map neither @@ -868,7 +839,7 @@ public: if (map_iter == inter_map.end()) { // In case the intersection points between the supporting conics have // not been computed before, compute them now and store them in the map. - _intersect_supporting_conics(arc, inter_list); + intersect_supporting_conics(arc, inter_list); if (! invalid_ids) inter_map[conic_pair] = inter_list; } @@ -880,8 +851,8 @@ public: // Go over the list of intersection points and report those that lie on // both x-monotone arcs. for (auto iter = inter_list.begin(); iter != inter_list.end(); ++iter) { - if (_is_between_endpoints((*iter).first) && - arc._is_between_endpoints((*iter).first)) + if (is_between_endpoints((*iter).first) && + arc.is_between_endpoints((*iter).first)) { *oi++ = Intersection_result(*iter); } @@ -894,156 +865,142 @@ public: /// \name Constructing x-monotone arcs. //@{ - /*! - * Split the arc into two at a given split point. + /*! Split the arc into two at a given split point. * \param p The split point. * \param c1 Output: The first resulting arc, lying to the left of p. * \param c2 Output: The first resulting arc, lying to the right of p. * \pre p lies in the interior of the arc (not one of its endpoints). */ - void split(const Conic_point_2& p, Self& c1, Self& c2) const - { + void split(const Conic_point_2& p, Self& c1, Self& c2) const { // Make sure that p lies on the interior of the arc. CGAL_precondition_code(Alg_kernel ker); - CGAL_precondition (this->contains_point (p) && - ! ker.equal_2_object() (p, this->_source) && - ! ker.equal_2_object() (p, this->_target)); + CGAL_precondition(this->contains_point (p) && + ! ker.equal_2_object()(p, this->m_source) && + ! ker.equal_2_object()(p, this->m_target)); // Make copies of the current arc. c1 = *this; c2 = *this; // Assign the endpoints of the arc. - if ((this->_info & IS_DIRECTED_RIGHT) != 0) - { + if ((this->m_info & IS_DIRECTED_RIGHT) != 0) { // The arc is directed from left to right, so p becomes c1's target // and c2's source. - c1._target = p; - c2._source = p; + c1.m_target = p; + c2.m_source = p; - if (! p.is_generating_conic (_id)) { - c1._target.set_generating_conic (_id); - c2._source.set_generating_conic (_id); + if (! p.is_generating_conic(m_id)) { + c1.m_target.set_generating_conic(m_id); + c2.m_source.set_generating_conic(m_id); } } - else - { + else { // The arc is directed from right to left, so p becomes c2's target // and c1's source. - c1._source = p; - c2._target = p; + c1.m_source = p; + c2.m_target = p; - if (! p.is_generating_conic (_id)) { - c1._source.set_generating_conic (_id); - c2._target.set_generating_conic (_id); + if (! p.is_generating_conic(m_id)) { + c1.m_source.set_generating_conic(m_id); + c2.m_target.set_generating_conic(m_id); } } - - return; } - /*! - * Flip the arc. + /*! Flip the arc. * \return An arc with swapped source and target and a reverse orienation. */ - Self flip() const - { + Self flip() const { // Make a copy of the current arc. Self arc = *this; // Reverse the orientation. - if (this->_orient == CLOCKWISE) arc._orient = COUNTERCLOCKWISE; - else if (this->_orient == COUNTERCLOCKWISE) arc._orient = CLOCKWISE; + if (this->m_orient == CLOCKWISE) arc.m_orient = COUNTERCLOCKWISE; + else if (this->m_orient == COUNTERCLOCKWISE) arc.m_orient = CLOCKWISE; // Swap the source and the target. - arc._source = this->_target; - arc._target = this->_source; + arc.m_source = this->m_target; + arc.m_target = this->m_source; // Change the direction bit among the information flags. - arc._info = (this->_info ^ IS_DIRECTED_RIGHT); + arc.m_info = (this->m_info ^ IS_DIRECTED_RIGHT); return arc; } - /*! - * Trim the arc given its new endpoints. + /*! Trim the arc given its new endpoints. * \param ps The new source point. * \param pt The new target point. * \return The new trimmed arc. * \pre Both ps and pt lies on the arc and must conform with the current * direction of the arc. */ - Self trim(const Conic_point_2& ps, const Conic_point_2& pt) const - { + Self trim(const Conic_point_2& ps, const Conic_point_2& pt) const { // Make sure that both ps and pt lie on the arc. CGAL_precondition(this->contains_point (ps) && this->contains_point (pt)); // Make sure that the endpoints conform with the direction of the arc. - Self arc = *this; - Alg_kernel ker; + Self arc = *this; + Alg_kernel ker; - if (! ((((this->_info & IS_DIRECTED_RIGHT) != 0) && + if (! ((((this->m_info & IS_DIRECTED_RIGHT) != 0) && ker.compare_xy_2_object() (ps, pt) == SMALLER) || - (((this->_info & IS_DIRECTED_RIGHT) == 0) && + (((this->m_info & IS_DIRECTED_RIGHT) == 0) && ker.compare_xy_2_object() (ps, pt) == LARGER))) { // We are allowed to change the direction only in case of a segment. - CGAL_assertion (this->_orient == COLLINEAR); - arc._info = (this->_info ^ IS_DIRECTED_RIGHT); + CGAL_assertion (this->m_orient == COLLINEAR); + arc.m_info = (this->m_info ^ IS_DIRECTED_RIGHT); } // Make a copy of the current arc and assign its endpoints. - if (! ker.equal_2_object() (ps, this->_source)) { - arc._source = ps; + if (! ker.equal_2_object()(ps, this->m_source)) { + arc.m_source = ps; - if (! ps.is_generating_conic (_id)) - arc._source.set_generating_conic (_id); + if (! ps.is_generating_conic(m_id)) + arc.m_source.set_generating_conic(m_id); } - if (! ker.equal_2_object() (pt, this->_target)) - { - arc._target = pt; + if (! ker.equal_2_object()(pt, this->m_target)) { + arc.m_target = pt; - if (! pt.is_generating_conic (_id)) - arc._target.set_generating_conic (_id); + if (! pt.is_generating_conic(m_id)) + arc.m_target.set_generating_conic(m_id); } - return (arc); + return arc; } - /*! - * Check whether the two arcs are equal (have the same graph). + /*! Check whether the two arcs are equal (have the same graph). * \param arc The compared arc. * \return (true) if the two arcs have the same graph; (false) otherwise. */ - bool equals (const Self& arc) const - { + bool equals(const Self& arc) const { // The two arc must have the same supporting conic curves. - if (! _has_same_supporting_conic (arc)) - return false; + if (! has_same_supporting_conic (arc)) return false; // Check that the arc endpoints are the same. Alg_kernel ker; - if (this->_orient == COLLINEAR) { - CGAL_assertion(arc._orient == COLLINEAR); - return((ker.equal_2_object()(this->_source, arc._source) && - ker.equal_2_object()(this->_target, arc._target)) || - (ker.equal_2_object()(this->_source, arc._target) && - ker.equal_2_object()(this->_target, arc._source))); + if (this->m_orient == COLLINEAR) { + CGAL_assertion(arc.m_orient == COLLINEAR); + return((ker.equal_2_object()(this->m_source, arc.m_source) && + ker.equal_2_object()(this->m_target, arc.m_target)) || + (ker.equal_2_object()(this->m_source, arc.m_target) && + ker.equal_2_object()(this->m_target, arc.m_source))); } - if (this->_orient == arc._orient) { + if (this->m_orient == arc.m_orient) { // Same orientation - the source and target points must be the same. - return (ker.equal_2_object()(this->_source, arc._source) && - ker.equal_2_object()(this->_target, arc._target)); + return (ker.equal_2_object()(this->m_source, arc.m_source) && + ker.equal_2_object()(this->m_target, arc.m_target)); } else { // Reverse orientation - the source and target points must be swapped. - return (ker.equal_2_object()(this->_source, arc._target) && - ker.equal_2_object()(this->_target, arc._source)); + return (ker.equal_2_object()(this->m_source, arc.m_target) && + ker.equal_2_object()(this->m_target, arc.m_source)); } } @@ -1052,16 +1009,14 @@ public: * \return (true) if it is possible to merge the two arcs; * (false) otherwise. */ - bool can_merge_with(const Self& arc) const - { + bool can_merge_with(const Self& arc) const { // In order to merge the two arcs, they should have the same supporting // conic. - if (! _has_same_supporting_conic(arc)) return false; + if (! has_same_supporting_conic(arc)) return false; // Check if the left endpoint of one curve is the right endpoint of the // other. - Alg_kernel ker; - + Alg_kernel ker; return (ker.equal_2_object() (right(), arc.left()) || ker.equal_2_object() (left(), arc.right())); } @@ -1070,40 +1025,31 @@ public: * \param arc The arc to merge with. * \pre The two arcs are mergeable. */ - void merge(const Self& arc) - { + void merge(const Self& arc) { CGAL_precondition (this->can_merge_with (arc)); // Check if we should extend the arc to the left or to the right. - Alg_kernel ker; + Alg_kernel ker; if (ker.equal_2_object() (right(), arc.left())) { // Extend the arc to the right. - if ((this->_info & IS_DIRECTED_RIGHT) != 0) this->_target = arc.right(); - else this->_source = arc.right(); + if ((this->m_info & IS_DIRECTED_RIGHT) != 0) this->m_target = arc.right(); + else this->m_source = arc.right(); } else { CGAL_precondition (ker.equal_2_object() (left(), arc.right())); // Extend the arc to the left. - if ((this->_info & IS_DIRECTED_RIGHT) != 0) - this->_source = arc.left(); + if ((this->m_info & IS_DIRECTED_RIGHT) != 0) + this->m_source = arc.left(); else - this->_target = arc.left(); + this->m_target = arc.left(); } - - return; } - bool is_upper() const - { - return ((this->_info & FACING_UP) != 0); - } + bool is_upper() const { return ((this->m_info & FACING_UP) != 0); } - bool is_lower() const - { - return ((this->_info & FACING_DOWN) != 0); - } + bool is_lower() const { return ((this->m_info & FACING_DOWN) != 0); } //@} private: @@ -1115,105 +1061,96 @@ private: * Set the properties of the x-monotone conic arc (for the usage of the * constructors). */ - void _set () - { + void set() { // Convert the coefficients of the supporting conic to algebraic numbers. - Nt_traits nt_traits; + Nt_traits nt_traits; - alg_r = nt_traits.convert (this->_r); - alg_s = nt_traits.convert (this->_s); - alg_t = nt_traits.convert (this->_t); - alg_u = nt_traits.convert (this->_u); - alg_v = nt_traits.convert (this->_v); - alg_w = nt_traits.convert (this->_w); + alg_r = nt_traits.convert(this->m_r); + alg_s = nt_traits.convert(this->m_s); + alg_t = nt_traits.convert(this->m_t); + alg_u = nt_traits.convert(this->m_u); + alg_v = nt_traits.convert(this->m_v); + alg_w = nt_traits.convert(this->m_w); // Set the generating conic ID for the source and target points. - this->_source.set_generating_conic (_id); - this->_target.set_generating_conic (_id); + this->m_source.set_generating_conic(m_id); + this->m_target.set_generating_conic(m_id); - // Clear the _info bits. - this->_info = Conic_arc_2::IS_VALID; + // Clear the m_info bits. + this->m_info = Conic_arc_2::IS_VALID; // Check if the arc is directed right (the target is lexicographically // greater than the source point), or to the left. - Alg_kernel ker; - Comparison_result dir_res = ker.compare_xy_2_object() (this->_source, - this->_target); + Alg_kernel ker; + Comparison_result dir_res = + ker.compare_xy_2_object()(this->m_source, this->m_target); CGAL_assertion (dir_res != EQUAL); - if (dir_res == SMALLER) - this->_info = (this->_info | IS_DIRECTED_RIGHT); + if (dir_res == SMALLER) this->m_info = (this->m_info | IS_DIRECTED_RIGHT); // Compute the degree of the underlying conic. - if (CGAL::sign (this->_r) != ZERO || - CGAL::sign (this->_s) != ZERO || - CGAL::sign (this->_t) != ZERO) + if ((CGAL::sign(this->m_r) != ZERO) || + (CGAL::sign(this->m_s) != ZERO) || + (CGAL::sign(this->m_t) != ZERO)) { - this->_info = (this->_info | DEGREE_2); + this->m_info = (this->m_info | DEGREE_2); - if (this->_orient == COLLINEAR) - { - this->_info = (this->_info | IS_SPECIAL_SEGMENT); + if (this->m_orient == COLLINEAR) { + this->m_info = (this->m_info | IS_SPECIAL_SEGMENT); - if (ker.compare_x_2_object() (this->_source, this->_target) == EQUAL) - { + if (ker.compare_x_2_object()(this->m_source, this->m_target) == EQUAL) { // The arc is a vertical segment: - this->_info = (this->_info | IS_VERTICAL_SEGMENT); + this->m_info = (this->m_info | IS_VERTICAL_SEGMENT); } return; } } - else - { - CGAL_assertion (CGAL::sign (this->_u) != ZERO || - CGAL::sign (this->_v) != ZERO); + else { + CGAL_assertion(CGAL::sign(this->m_u) != ZERO || + CGAL::sign(this->m_v) != ZERO); - if (CGAL::sign (this->_v) == ZERO) - { + if (CGAL::sign (this->m_v) == ZERO) { // The supporting curve is of the form: _u*x + _w = 0 - this->_info = (this->_info | IS_VERTICAL_SEGMENT); + this->m_info = (this->m_info | IS_VERTICAL_SEGMENT); } - this->_info = (this->_info | DEGREE_1); + this->m_info = (this->m_info | DEGREE_1); return; } - if (this->_orient == COLLINEAR) - return; + if (this->m_orient == COLLINEAR) return; // Compute a midpoint between the source and the target and get the y-value // of the arc at its x-coordiante. - Point_2 p_mid = ker.construct_midpoint_2_object() (this->_source, - this->_target); - Algebraic ys[2]; - CGAL_assertion_code(int n_ys = ) - _conic_get_y_coordinates (p_mid.x(), ys); + Point_2 p_mid = + ker.construct_midpoint_2_object()(this->m_source, this->m_target); + Algebraic ys[2]; + CGAL_assertion_code(int n_ys = ) + conic_get_y_coordinates(p_mid.x(), ys); - CGAL_assertion (n_ys != 0); + CGAL_assertion(n_ys != 0); // Check which solution lies on the x-monotone arc. - Point_2 p_arc_mid (p_mid.x(), ys[0]); + Point_2 p_arc_mid(p_mid.x(), ys[0]); - if (_is_strictly_between_endpoints (p_arc_mid)) - { + if (is_strictly_between_endpoints (p_arc_mid)) { // Mark that we should use the -sqrt(disc) root for points on this // x-monotone arc. - this->_info = (this->_info & ~PLUS_SQRT_DISC_ROOT); + this->m_info = (this->m_info & ~PLUS_SQRT_DISC_ROOT); } - else - { + else { CGAL_assertion (n_ys == 2); p_arc_mid = Point_2 (p_mid.x(), ys[1]); - CGAL_assertion (_is_strictly_between_endpoints (p_arc_mid)); + CGAL_assertion (is_strictly_between_endpoints (p_arc_mid)); // Mark that we should use the +sqrt(disc) root for points on this // x-monotone arc. - this->_info = (this->_info | PLUS_SQRT_DISC_ROOT); + this->m_info = (this->m_info | PLUS_SQRT_DISC_ROOT); } // Check whether the conic is facing up or facing down: @@ -1223,169 +1160,129 @@ private: // coordinate is (x1+x2)/2 and compare it to (y1+y2)/2. Comparison_result res = ker.compare_y_2_object() (p_arc_mid, p_mid); - if (res == LARGER) - { + if (res == LARGER) { // The arc is above the connecting segment, so it is facing upwards. - this->_info = (this->_info | FACING_UP); + this->m_info = (this->m_info | FACING_UP); } - else if (res == SMALLER) - { + else if (res == SMALLER) { // The arc is below the connecting segment, so it is facing downwards. - this->_info = (this->_info | FACING_DOWN); + this->m_info = (this->m_info | FACING_DOWN); } - - return; } - /*! - * Check if the arc is a special segment connecting two algebraic endpoints + /*! Check if the arc is a special segment connecting two algebraic endpoints * (and has no undelying integer conic coefficients). */ - bool _is_special_segment () const - { - return ((this->_info & IS_SPECIAL_SEGMENT) != 0); - } + bool is_special_segment() const + { return ((this->m_info & IS_SPECIAL_SEGMENT) != 0); } - /*! - * Check whether the given point lies on the supporting conic of the arc. + /*! Check whether the given point lies on the supporting conic of the arc. * \param px The x-coordinate of query point. * \param py The y-coordinate of query point. * \return (true) if p lies on the supporting conic; (false) otherwise. */ - bool _is_on_supporting_conic (const Algebraic& px, - const Algebraic& py) const - { - CGAL::Sign _sign; + bool is_on_supporting_conic(const Algebraic& px, const Algebraic& py) const { + CGAL::Sign _sign; - if (! _is_special_segment()) - { + if (! is_special_segment()) { // Check whether p satisfies the conic equation. // The point must satisfy: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0. - _sign = CGAL::sign ((alg_r*px + alg_t*py + alg_u) * px + - (alg_s*py + alg_v) * py + - alg_w); + _sign = CGAL::sign((alg_r*px + alg_t*py + alg_u) * px + + (alg_s*py + alg_v) * py + alg_w); } - else - { + else { // Check whether p satisfies the equation of the line stored with the // extra data. - _sign = _sign_of_extra_data (px, py); + _sign = sign_of_extra_data(px, py); } return (_sign == ZERO); } - /*! - * Check whether the two arcs have the same supporting conic. + /*! Check whether the two arcs have the same supporting conic. * \param arc The compared arc. * \return (true) if the two supporting conics are the same. */ - bool _has_same_supporting_conic (const Self& arc) const - { + bool has_same_supporting_conic(const Self& arc) const { // Check if the two arcs originate from the same conic: - if (_id == arc._id && _id.is_valid() && arc._id.is_valid()) - return (true); + if (m_id == arc.m_id && m_id.is_valid() && arc.m_id.is_valid()) return true; // In case both arcs are collinear, check if they have the same // supporting lines. - if (this->_orient == COLLINEAR && arc._orient == COLLINEAR) - { + if ((this->m_orient == COLLINEAR) && (arc.m_orient == COLLINEAR)) { // Construct the two supporting lines and compare them. - Alg_kernel ker; - typename Alg_kernel::Construct_line_2 construct_line = - ker.construct_line_2_object(); - typename Alg_kernel::Line_2 l1 = construct_line (this->_source, - this->_target); - typename Alg_kernel::Line_2 l2 = construct_line (arc._source, - arc._target); - typename Alg_kernel::Equal_2 equal = ker.equal_2_object(); + Alg_kernel ker; + auto construct_line = ker.construct_line_2_object(); + typename Alg_kernel::Line_2 l1 = + construct_line(this->m_source, this->m_target); + typename Alg_kernel::Line_2 l2 = + construct_line(arc.m_source, arc.m_target); + auto equal = ker.equal_2_object(); - if (equal (l1, l2)) - return (true); + if (equal(l1, l2)) return true; // Try to compare l1 with the opposite of l2. - l2 = construct_line (arc._target, arc._source); + l2 = construct_line(arc.m_target, arc.m_source); - return (equal (l1, l2)); + return equal(l1, l2); } - else if (this->_orient == COLLINEAR || arc._orient == COLLINEAR) - { + else if ((this->m_orient == COLLINEAR) || (arc.m_orient == COLLINEAR)) { // Only one arc is collinear, so the supporting curves cannot be the // same: - return (false); + return false; } // Check whether the coefficients of the two supporting conics are equal // up to a constant factor. - Integer factor1 = 1; - Integer factor2 = 1; + Integer factor1 = 1; + Integer factor2 = 1; - if (CGAL::sign (this->_r) != ZERO) - factor1 = this->_r; - else if (CGAL::sign (this->_s) != ZERO) - factor1 = this->_s; - else if (CGAL::sign (this->_t) != ZERO) - factor1 = this->_t; - else if (CGAL::sign (this->_u) != ZERO) - factor1 = this->_u; - else if (CGAL::sign (this->_v) != ZERO) - factor1 = this->_v; - else if (CGAL::sign (this->_w) != ZERO) - factor1 = this->_w; + if (CGAL::sign(this->m_r) != ZERO) factor1 = this->m_r; + else if (CGAL::sign(this->m_s) != ZERO) factor1 = this->m_s; + else if (CGAL::sign(this->m_t) != ZERO) factor1 = this->m_t; + else if (CGAL::sign(this->m_u) != ZERO) factor1 = this->m_u; + else if (CGAL::sign(this->m_v) != ZERO) factor1 = this->m_v; + else if (CGAL::sign(this->m_w) != ZERO) factor1 = this->m_w; - if (CGAL::sign (arc._r) != ZERO) - factor2 = arc._r; - else if (CGAL::sign (arc._s) != ZERO) - factor2 = arc._s; - else if (CGAL::sign (arc._t) != ZERO) - factor2 = arc._t; - else if (CGAL::sign (arc._u) != ZERO) + if (CGAL::sign(arc.m_r) != ZERO) factor2 = arc.m_r; + else if (CGAL::sign(arc.m_s) != ZERO) factor2 = arc.m_s; + else if (CGAL::sign(arc.m_t) != ZERO) factor2 = arc.m_t; + else if (CGAL::sign(arc.m_u) != ZERO) factor2 = arc.m_u; + else if (CGAL::sign(arc.m_v) != ZERO) factor2 = arc.m_v; + else if (CGAL::sign(arc.m_w) != ZERO) factor2 = arc.m_w; - factor2 = arc._u; - else if (CGAL::sign (arc._v) != ZERO) - factor2 = arc._v; - else if (CGAL::sign (arc._w) != ZERO) - factor2 = arc._w; - - return (CGAL::compare (this->_r * factor2, arc._r * factor1) == EQUAL && - CGAL::compare (this->_s * factor2, arc._s * factor1) == EQUAL && - CGAL::compare (this->_t * factor2, arc._t * factor1) == EQUAL && - CGAL::compare (this->_u * factor2, arc._u * factor1) == EQUAL && - CGAL::compare (this->_v * factor2, arc._v * factor1) == EQUAL && - CGAL::compare (this->_w * factor2, arc._w * factor1) == EQUAL); + return (CGAL::compare(this->m_r * factor2, arc.m_r * factor1) == EQUAL && + CGAL::compare(this->m_s * factor2, arc.m_s * factor1) == EQUAL && + CGAL::compare(this->m_t * factor2, arc.m_t * factor1) == EQUAL && + CGAL::compare(this->m_u * factor2, arc.m_u * factor1) == EQUAL && + CGAL::compare(this->m_v * factor2, arc.m_v * factor1) == EQUAL && + CGAL::compare(this->m_w * factor2, arc.m_w * factor1) == EQUAL); } - /*! - * Get the i'th order derivative by x of the conic at the point p=(x,y). + /*! Get the i'th order derivative by x of the conic at the point p=(x,y). * \param p The point where we derive. * \param i The order of the derivatives (either 1, 2 or 3). * \param slope_numer The numerator of the slope. * \param slope_denom The denominator of the slope. * \todo Allow higher order derivatives. */ - void _derive_by_x_at (const Point_2& p, const unsigned int& i, - Algebraic& slope_numer, Algebraic& slope_denom) const - { - if (_is_special_segment()) - { + void derive_by_x_at(const Point_2& p, const unsigned int& i, + Algebraic& slope_numer, Algebraic& slope_denom) const { + if (is_special_segment()) { // Special treatment for special segments, given by (a*x + b*y + c = 0), // so their first-order derivative by x is simply -a/b. The higher-order // derivatives are all 0. - if (i == 1) - { - if (CGAL::sign (this->_extra_data_P->b) != NEGATIVE) - { - slope_numer = - this->_extra_data_P->a; - slope_denom = this->_extra_data_P->b; + if (i == 1) { + if (CGAL::sign (this->m_extra_data->b) != NEGATIVE) { + slope_numer = - this->m_extra_data->a; + slope_denom = this->m_extra_data->b; } - else - { - slope_numer = this->_extra_data_P->a; - slope_denom = - this->_extra_data_P->b; + else { + slope_numer = this->m_extra_data->a; + slope_denom = - this->m_extra_data->b; } } - else - { + else { slope_numer = 0; slope_denom = 1; } @@ -1401,20 +1298,17 @@ private: // y' = - ---------------- = - ------- // 2s*y + t*x + v beta // - const Algebraic _two = 2; - const Algebraic sl_numer = _two*alg_r*p.x() + alg_t*p.y() + alg_u; - const Algebraic sl_denom = _two*alg_s*p.y() + alg_t*p.x() + alg_v; + const Algebraic two = 2; + const Algebraic sl_numer = two*alg_r*p.x() + alg_t*p.y() + alg_u; + const Algebraic sl_denom = two*alg_s*p.y() + alg_t*p.x() + alg_v; - if (i == 1) - { + if (i == 1) { // Make sure that the denominator is always positive. - if (CGAL::sign (sl_denom) != NEGATIVE) - { + if (CGAL::sign (sl_denom) != NEGATIVE) { slope_numer = -sl_numer; slope_denom = sl_denom; } - else - { + else { slope_numer = sl_numer; slope_denom = -sl_denom; } @@ -1428,22 +1322,18 @@ private: // y'' = -2 ------------------------------------- = ------- // beta^3 delta // - const Algebraic sl2_numer = alg_s * sl_numer*sl_numer - - alg_t * sl_numer*sl_denom + - alg_r * sl_denom*sl_denom; - const Algebraic sl2_denom = sl_denom*sl_denom*sl_denom; + const Algebraic sl2_numer = alg_s * sl_numer*sl_numer - + alg_t * sl_numer*sl_denom + alg_r * sl_denom*sl_denom; + const Algebraic sl2_denom = sl_denom*sl_denom*sl_denom; - if (i == 2) - { + if (i == 2) { // Make sure that the denominator is always positive. - if (CGAL::sign (sl_denom) != NEGATIVE) - { - slope_numer = -_two *sl2_numer; + if (CGAL::sign (sl_denom) != NEGATIVE) { + slope_numer = -two *sl2_numer; slope_denom = sl2_denom; } - else - { - slope_numer = _two *sl2_numer; + else { + slope_numer = two *sl2_numer; slope_denom = -sl2_denom; } @@ -1456,20 +1346,17 @@ private: // y''' = -6 ------------------------------ // beta^2 * delta // - const Algebraic sl3_numer = (_two * alg_s * sl_numer - - alg_t * sl_denom) * sl2_numer; - const Algebraic sl3_denom = sl_denom*sl_denom * sl2_denom; + const Algebraic sl3_numer = + (two * alg_s * sl_numer - alg_t * sl_denom) * sl2_numer; + const Algebraic sl3_denom = sl_denom*sl_denom * sl2_denom; - if (i == 3) - { + if (i == 3) { // Make sure that the denominator is always positive. - if (CGAL::sign (sl_denom) != NEGATIVE) - { + if (CGAL::sign (sl_denom) != NEGATIVE) { slope_numer = -6 * sl3_numer; slope_denom = sl3_denom; } - else - { + else { slope_numer = 6 * sl3_numer; slope_denom = -sl2_denom; } @@ -1479,7 +1366,6 @@ private: // \todo Handle higher-order derivatives as well. CGAL_error(); - return; } /*! @@ -1490,29 +1376,23 @@ private: * \param slope_denom The denominator of the slope. * \todo Allow higher order derivatives. */ - void _derive_by_y_at (const Point_2& p, const int& i, - Algebraic& slope_numer, Algebraic& slope_denom) const - { - if (_is_special_segment()) - { + void derive_by_y_at(const Point_2& p, const int& i, + Algebraic& slope_numer, Algebraic& slope_denom) const { + if (is_special_segment()) { // Special treatment for special segments, given by (a*x + b*y + c = 0), // so their first-order derivative by x is simply -b/a. The higher-order // derivatives are all 0. - if (i == 1) - { - if (CGAL::sign (this->_extra_data_P->a) != NEGATIVE) - { - slope_numer = - this->_extra_data_P->b; - slope_denom = this->_extra_data_P->a; + if (i == 1) { + if (CGAL::sign (this->m_extra_data->a) != NEGATIVE) { + slope_numer = - this->m_extra_data->b; + slope_denom = this->m_extra_data->a; } - else - { - slope_numer = this->_extra_data_P->b; - slope_denom = - this->_extra_data_P->a; + else { + slope_numer = this->m_extra_data->b; + slope_denom = - this->m_extra_data->a; } } - else - { + else { slope_numer = 0; slope_denom = 1; } @@ -1528,25 +1408,21 @@ private: // x' = - ---------------- = ------- // 2r*x + t*y + u beta // - const Algebraic _two = 2; - const Algebraic sl_numer = _two*alg_s*p.y() + alg_t*p.x() + alg_v; - const Algebraic sl_denom = _two*alg_r*p.x() + alg_t*p.y() + alg_u; + const Algebraic two = 2; + const Algebraic sl_numer = two*alg_s*p.y() + alg_t*p.x() + alg_v; + const Algebraic sl_denom = two*alg_r*p.x() + alg_t*p.y() + alg_u; - if (i == 1) - { + if (i == 1) { // Make sure that the denominator is always positive. - if (CGAL::sign (sl_denom) != NEGATIVE) - { + if (CGAL::sign (sl_denom) != NEGATIVE) { slope_numer = -sl_numer; slope_denom = sl_denom; } - else - { + else { slope_numer = sl_numer; slope_denom = -sl_denom; } - return; } @@ -1556,23 +1432,18 @@ private: // x'' = -2 ------------------------------------- // beta^3 // - const Algebraic sl2_numer = alg_r * sl_numer*sl_numer - - alg_t * sl_numer*sl_denom + - alg_s * sl_denom*sl_denom; - const Algebraic sl2_denom = sl_denom*sl_denom*sl_denom; - - if (i == 2) - { + const Algebraic sl2_numer = alg_r * sl_numer*sl_numer - + alg_t * sl_numer*sl_denom + alg_s * sl_denom*sl_denom; + const Algebraic sl2_denom = sl_denom*sl_denom*sl_denom; + if (i == 2) { // Make sure that the denominator is always positive. - if (CGAL::sign (sl_denom) != NEGATIVE) - { - slope_numer = -_two *sl2_numer; + if (CGAL::sign (sl_denom) != NEGATIVE) { + slope_numer = -two *sl2_numer; slope_denom = sl2_denom; } - else - { - slope_numer = _two *sl2_numer; + else { + slope_numer = two *sl2_numer; slope_denom = -sl2_denom; } @@ -1585,20 +1456,17 @@ private: // y''' = -6 ------------------------------ // beta^2 * delta // - const Algebraic sl3_numer = (_two * alg_r * sl_numer - - alg_t * sl_denom) * sl2_numer; - const Algebraic sl3_denom = sl_denom*sl_denom * sl2_denom; + const Algebraic sl3_numer = + (two * alg_r * sl_numer - alg_t * sl_denom) * sl2_numer; + const Algebraic sl3_denom = sl_denom*sl_denom * sl2_denom; - if (i == 3) - { + if (i == 3) { // Make sure that the denominator is always positive. - if (CGAL::sign (sl_denom) != NEGATIVE) - { + if (CGAL::sign (sl_denom) != NEGATIVE) { slope_numer = -6 * sl3_numer; slope_denom = sl3_denom; } - else - { + else { slope_numer = 6 * sl3_numer; slope_denom = -sl2_denom; } @@ -1608,161 +1476,151 @@ private: // \todo Handle higher-order derivatives as well. CGAL_error(); - return; } - /*! - * Compute the overlap with a given arc, which is supposed to have the same + /*! Compute the overlap with a given arc, which is supposed to have the same * supporting conic curve as this arc. * \param arc The given arc. * \param overlap Output: The overlapping arc (if any). * \return Whether we found an overlap. */ - bool _compute_overlap (const Self& arc, Self& overlap) const - { + bool compute_overlap(const Self& arc, Self& overlap) const { // Check if the two arcs are identical. - if (equals (arc)) - { + if (equals(arc)) { overlap = arc; - return (true); + return true; } - if (_is_strictly_between_endpoints (arc.left())) - { - if (_is_strictly_between_endpoints(arc.right())) - { + if (is_strictly_between_endpoints (arc.left())) { + if (is_strictly_between_endpoints(arc.right())) { // Case 1 - *this: +-----------> // arc: +=====> overlap = arc; - return (true); + return true; } - else - { + else { // Case 2 - *this: +-----------> // arc: +=====> overlap = *this; - if ((overlap._info & IS_DIRECTED_RIGHT) != 0) - overlap._source = arc.left(); + if ((overlap.m_info & IS_DIRECTED_RIGHT) != 0) + overlap.m_source = arc.left(); else - overlap._target = arc.left(); + overlap.m_target = arc.left(); - return (true); + return true; } } - else if (_is_strictly_between_endpoints (arc.right())) - { + else if (is_strictly_between_endpoints(arc.right())) { // Case 3 - *this: +-----------> // arc: +=====> overlap = *this; - if ((overlap._info & IS_DIRECTED_RIGHT) != 0) - overlap._target = arc.right(); + if ((overlap.m_info & IS_DIRECTED_RIGHT) != 0) + overlap.m_target = arc.right(); else - overlap._source = arc.right(); + overlap.m_source = arc.right(); - return (true); + return true; } - else if (arc._is_between_endpoints (this->_source) && - arc._is_between_endpoints (this->_target) && - (arc._is_strictly_between_endpoints(this->_source) || - arc._is_strictly_between_endpoints(this->_target))) + else if (arc.is_between_endpoints(this->m_source) && + arc.is_between_endpoints(this->m_target) && + (arc.is_strictly_between_endpoints(this->m_source) || + arc.is_strictly_between_endpoints(this->m_target))) { // Case 4 - *this: +-----------> // arc: +================> overlap = *this; - return (true); + return true; } // If we reached here, there are no overlaps: - return (false); + return false; } - /*! - * Intersect the supporing conic curves of this arc and the given arc. + /*! Intersect the supporing conic curves of this arc and the given arc. * \param arc The arc to intersect with. * \param inter_list The list of intersection points. */ - void _intersect_supporting_conics(const Self& arc, - Intersection_list& inter_list) const - { - if (_is_special_segment() && ! arc._is_special_segment()) { + void intersect_supporting_conics(const Self& arc, + Intersection_list& inter_list) const { + if (is_special_segment() && ! arc.is_special_segment()) { // If one of the arcs is a special segment, make sure it is (arc). - arc._intersect_supporting_conics(*this, inter_list); + arc.intersect_supporting_conics(*this, inter_list); return; } - const int deg1 = ((this->_info & DEGREE_MASK) == DEGREE_1) ? 1 : 2; - const int deg2 = ((arc._info & DEGREE_MASK) == DEGREE_1) ? 1 : 2; + const int deg1 = ((this->m_info & DEGREE_MASK) == DEGREE_1) ? 1 : 2; + const int deg2 = ((arc.m_info & DEGREE_MASK) == DEGREE_1) ? 1 : 2; Nt_traits nt_traits; Algebraic xs[4]; int n_xs = 0; Algebraic ys[4]; int n_ys = 0; - if (arc._is_special_segment()) { + if (arc.is_special_segment()) { // The second arc is a special segment (a*x + b*y + c = 0). - if (_is_special_segment()) { + if (is_special_segment()) { // Both arc are sepcial segment, so they have at most one intersection // point. - Algebraic denom = this->_extra_data_P->a * arc._extra_data_P->b - - this->_extra_data_P->b * arc._extra_data_P->a; + Algebraic denom = this->m_extra_data->a * arc.m_extra_data->b - + this->m_extra_data->b * arc.m_extra_data->a; if (CGAL::sign (denom) != CGAL::ZERO) { - xs[0] = (this->_extra_data_P->b * arc._extra_data_P->c - - this->_extra_data_P->c * arc._extra_data_P->b) / denom; + xs[0] = (this->m_extra_data->b * arc.m_extra_data->c - + this->m_extra_data->c * arc.m_extra_data->b) / denom; n_xs = 1; - ys[0] = (this->_extra_data_P->c * arc._extra_data_P->a - - this->_extra_data_P->a * arc._extra_data_P->c) / denom; + ys[0] = (this->m_extra_data->c * arc.m_extra_data->a - + this->m_extra_data->a * arc.m_extra_data->c) / denom; n_ys = 1; } } else { // Compute the x-coordinates of the intersection points. - n_xs = _compute_resultant_roots (nt_traits, - alg_r, alg_s, alg_t, - alg_u, alg_v, alg_w, - deg1, - arc._extra_data_P->a, - arc._extra_data_P->b, - arc._extra_data_P->c, - xs); + n_xs = compute_resultant_roots(nt_traits, + alg_r, alg_s, alg_t, + alg_u, alg_v, alg_w, + deg1, + arc.m_extra_data->a, + arc.m_extra_data->b, + arc.m_extra_data->c, + xs); CGAL_assertion (n_xs <= 2); // Compute the y-coordinates of the intersection points. - n_ys = _compute_resultant_roots (nt_traits, - alg_s, alg_r, alg_t, - alg_v, alg_u, alg_w, - deg1, - arc._extra_data_P->b, - arc._extra_data_P->a, - arc._extra_data_P->c, - ys); - CGAL_assertion (n_ys <= 2); + n_ys = compute_resultant_roots(nt_traits, + alg_s, alg_r, alg_t, + alg_v, alg_u, alg_w, + deg1, + arc.m_extra_data->b, + arc.m_extra_data->a, + arc.m_extra_data->c, + ys); + CGAL_assertion(n_ys <= 2); } } else { // Compute the x-coordinates of the intersection points. - n_xs = _compute_resultant_roots (nt_traits, - this->_r, this->_s, this->_t, - this->_u, this->_v, this->_w, - deg1, - arc._r, arc._s, arc._t, - arc._u, arc._v, arc._w, - deg2, - xs); - CGAL_assertion (n_xs <= 4); + n_xs = compute_resultant_roots(nt_traits, + this->m_r, this->m_s, this->m_t, + this->m_u, this->m_v, this->m_w, + deg1, + arc.m_r, arc.m_s, arc.m_t, + arc.m_u, arc.m_v, arc.m_w, + deg2, + xs); + CGAL_assertion(n_xs <= 4); // Compute the y-coordinates of the intersection points. - n_ys = _compute_resultant_roots (nt_traits, - this->_s, this->_r, this->_t, - this->_v, this->_u, this->_w, - deg1, - arc._s, arc._r, arc._t, - arc._v, arc._u, arc._w, - deg2, - ys); + n_ys = compute_resultant_roots(nt_traits, + this->m_s, this->m_r, this->m_t, + this->m_v, this->m_u, this->m_w, + deg1, + arc.m_s, arc.m_r, arc.m_t, + arc.m_v, arc.m_u, arc.m_w, + deg2, + ys); CGAL_assertion(n_ys <= 4); } @@ -1770,84 +1628,77 @@ private: // x and y-coordinates are sorted in ascending order, we output the // intersection points in lexicographically ascending order. unsigned int mult; - int i, j; + int i, j; - if (arc._is_special_segment()) - { - if (n_xs == 0 || n_ys == 0) - return; + if (arc.is_special_segment()) { + if ((n_xs == 0) || (n_ys == 0)) return; - if (n_xs == 1 && n_ys == 1) - { + if ((n_xs == 1) && (n_ys == 1)) { // Single intersection. Conic_point_2 ip (xs[0], ys[0]); - ip.set_generating_conic (_id); - ip.set_generating_conic (arc._id); + ip.set_generating_conic(m_id); + ip.set_generating_conic (arc.m_id); // In case the other curve is of degree 2, this is a tangency point. - mult = (deg1 == 1 || _is_special_segment()) ? 1 : 2; - inter_list.push_back(Intersection_point (ip, mult)); + mult = ((deg1 == 1) || is_special_segment()) ? 1 : 2; + inter_list.push_back(Intersection_point(ip, mult)); } - else if (n_xs == 1 && n_ys == 2) - { - Conic_point_2 ip1 (xs[0], ys[0]); + else if ((n_xs == 1) && (n_ys == 2)) { + Conic_point_2 ip1(xs[0], ys[0]); - ip1.set_generating_conic (_id); - ip1.set_generating_conic (arc._id); + ip1.set_generating_conic(m_id); + ip1.set_generating_conic(arc.m_id); - inter_list.push_back(Intersection_point (ip1, 1)); + inter_list.push_back(Intersection_point(ip1, 1)); - Conic_point_2 ip2 (xs[0], ys[1]); + Conic_point_2 ip2 (xs[0], ys[1]); - ip2.set_generating_conic (_id); - ip2.set_generating_conic (arc._id); + ip2.set_generating_conic(m_id); + ip2.set_generating_conic(arc.m_id); - inter_list.push_back(Intersection_point (ip2, 1)); + inter_list.push_back(Intersection_point(ip2, 1)); } - else if (n_xs == 2 && n_ys == 1) - { - Conic_point_2 ip1 (xs[0], ys[0]); + else if ((n_xs == 2) && (n_ys == 1)) { + Conic_point_2 ip1 (xs[0], ys[0]); - ip1.set_generating_conic (_id); - ip1.set_generating_conic (arc._id); + ip1.set_generating_conic(m_id); + ip1.set_generating_conic (arc.m_id); - inter_list.push_back(Intersection_point (ip1, 1)); + inter_list.push_back(Intersection_point(ip1, 1)); - Conic_point_2 ip2 (xs[1], ys[0]); + Conic_point_2 ip2 (xs[1], ys[0]); - ip2.set_generating_conic (_id); - ip2.set_generating_conic (arc._id); + ip2.set_generating_conic(m_id); + ip2.set_generating_conic(arc.m_id); - inter_list.push_back(Intersection_point (ip2, 1)); + inter_list.push_back(Intersection_point(ip2, 1)); } else { - CGAL_assertion (n_xs == 2 && n_ys == 2); + CGAL_assertion((n_xs == 2) && (n_ys == 2)); // The x-coordinates and the y-coordinates are given in ascending // order. If the slope of the segment is positive, we pair the // coordinates as is - otherwise, we swap the pairs. int ind_first_y = 0, ind_second_y = 1; - if (CGAL::sign (arc._extra_data_P->b) == - CGAL::sign(arc._extra_data_P->a)) - { + if (CGAL::sign(arc.m_extra_data->b) == CGAL::sign(arc.m_extra_data->a)) { ind_first_y = 1; ind_second_y = 0; } Conic_point_2 ip1(xs[0], ys[ind_first_y]); - ip1.set_generating_conic(_id); - ip1.set_generating_conic(arc._id); + ip1.set_generating_conic(m_id); + ip1.set_generating_conic(arc.m_id); - inter_list.push_back(Intersection_point (ip1, 1)); + inter_list.push_back(Intersection_point(ip1, 1)); Conic_point_2 ip2(xs[1], ys[ind_second_y]); - ip2.set_generating_conic (_id); - ip2.set_generating_conic (arc._id); + ip2.set_generating_conic(m_id); + ip2.set_generating_conic(arc.m_id); inter_list.push_back(Intersection_point(ip2, 1)); } @@ -1855,81 +1706,74 @@ private: return; } - for (i = 0; i < n_xs; i++) { - for (j = 0; j < n_ys; j++) { - if (_is_on_supporting_conic (xs[i], ys[j]) && - arc._is_on_supporting_conic (xs[i], ys[j])) + for (i = 0; i < n_xs; ++i) { + for (j = 0; j < n_ys; ++j) { + if (is_on_supporting_conic (xs[i], ys[j]) && + arc.is_on_supporting_conic(xs[i], ys[j])) { // Create the intersection point and set its generating conics. Conic_point_2 ip(xs[i], ys[j]); - ip.set_generating_conic (_id); - ip.set_generating_conic (arc._id); + ip.set_generating_conic(m_id); + ip.set_generating_conic(arc.m_id); // Compute the multiplicity of the intersection point. if (deg1 == 1 && deg2 == 1) mult = 1; - else mult = _multiplicity_of_intersection_point(arc, ip); + else mult = multiplicity_of_intersection_point(arc, ip); // Insert the intersection point to the output list. inter_list.push_back(Intersection_point(ip, mult)); } } } - - return; } - /*! - * Compute the multiplicity of an intersection point. + /*! Compute the multiplicity of an intersection point. * \param arc The arc to intersect with. * \param p The intersection point. * \return The multiplicity of the intersection point. */ - unsigned int _multiplicity_of_intersection_point (const Self& arc, - const Point_2& p) const - { - CGAL_assertion (! _is_special_segment() || ! arc._is_special_segment()); + unsigned int multiplicity_of_intersection_point(const Self& arc, + const Point_2& p) const { + CGAL_assertion(! is_special_segment() || ! arc.is_special_segment()); // Compare the slopes of the two arcs at p, using their first-order // partial derivatives. - Algebraic slope1_numer, slope1_denom; - Algebraic slope2_numer, slope2_denom; + Algebraic slope1_numer, slope1_denom; + Algebraic slope2_numer, slope2_denom; - _derive_by_x_at (p, 1, slope1_numer, slope1_denom); - arc._derive_by_x_at (p, 1, slope2_numer, slope2_denom); + derive_by_x_at(p, 1, slope1_numer, slope1_denom); + arc.derive_by_x_at(p, 1, slope2_numer, slope2_denom); - if (CGAL::compare (slope1_numer*slope2_denom, - slope2_numer*slope1_denom) != EQUAL) - { + if (CGAL::compare(slope1_numer*slope2_denom, slope2_numer*slope1_denom) != + EQUAL) { // Different slopes at p - the mutiplicity of p is 1: - return (1); + return 1; } - if (CGAL::sign (slope1_denom) != ZERO && - CGAL::sign (slope2_denom) != ZERO) - { + if (CGAL::sign(slope1_denom) != ZERO && + CGAL::sign(slope2_denom) != ZERO) { // The curves do not have a vertical slope at p. // Compare their second-order derivative by x: - _derive_by_x_at (p, 2, slope1_numer, slope1_denom); - arc._derive_by_x_at (p, 2, slope2_numer, slope2_denom); + derive_by_x_at(p, 2, slope1_numer, slope1_denom); + arc.derive_by_x_at(p, 2, slope2_numer, slope2_denom); } - else - { + else { // Both curves have a vertical slope at p. // Compare their second-order derivative by y: - _derive_by_y_at (p, 2, slope1_numer, slope1_denom); - arc._derive_by_y_at (p, 2, slope2_numer, slope2_denom); + derive_by_y_at(p, 2, slope1_numer, slope1_denom); + arc.derive_by_y_at(p, 2, slope2_numer, slope2_denom); } - if (CGAL::compare (slope1_numer*slope2_denom, - slope2_numer*slope1_denom) != EQUAL) + if (CGAL::compare(slope1_numer*slope2_denom, + slope2_numer*slope1_denom) != EQUAL) { // Different curvatures at p - the mutiplicity of p is 2: - return (2); + return 2; } // If we reached here, the multiplicity of the intersection point is 3: - return (3); + return 3; } //@} @@ -1939,8 +1783,8 @@ private: * Exporter for x-monotone conic arcs. */ template -std::ostream& operator<< (std::ostream& os, - const _Conic_x_monotone_arc_2& arc) +std::ostream& operator<<(std::ostream& os, + const _Conic_x_monotone_arc_2& arc) { // Output the supporting conic curve. os << "{" << CGAL::to_double(arc.r()) << "*x^2 + " @@ -1954,12 +1798,9 @@ std::ostream& operator<< (std::ostream& os, os << " : (" << CGAL::to_double(arc.source().x()) << "," << CGAL::to_double(arc.source().y()) << ") "; - if (arc.orientation() == CLOCKWISE) - os << "--cw-->"; - else if (arc.orientation() == COUNTERCLOCKWISE) - os << "--ccw-->"; - else - os << "--l-->"; + if (arc.orientation() == CLOCKWISE) os << "--cw-->"; + else if (arc.orientation() == COUNTERCLOCKWISE) os << "--ccw-->"; + else os << "--l-->"; os << " (" << CGAL::to_double(arc.target().x()) << "," << CGAL::to_double(arc.target().y()) << ")"; From e8eb85d5dc239d22ccc08a2f2588cf243338e85d Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 18 May 2022 14:04:52 +0300 Subject: [PATCH 004/105] Drew faces in the correct order (from unbounded to inner). --- .../include/CGAL/draw_arrangement_2.h | 48 +++++++++++-------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h index 9feb18a9a28..9b52b282c74 100644 --- a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h +++ b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h @@ -1,6 +1,8 @@ #ifndef CGAL_DRAW_ARRANGEMENT_2_H #define CGAL_DRAW_ARRANGEMENT_2_H +#include + #include #include #include @@ -10,9 +12,10 @@ namespace CGAL { // Viewer class for Polygon_2 template class Arr_2_viewer_qt : public Basic_viewer_qt { - typedef Basic_viewer_qt Base; - typedef Arrangement_2 Arr; - typedef typename Arr::Point_2 Point; + typedef Basic_viewer_qt Base; + typedef Arrangement_2 Arr; + typedef typename Arr::Point_2 Point; + typedef typename Arr::Face_const_handle Face_const_handle; public: /// Construct the viewer. @@ -26,44 +29,51 @@ public: { add_elements(); } protected: - void add_ccb(typename Arr::Ccb_halfedge_const_circulator circ) { + //! + void add_ccb(typename Arr::Ccb_halfedge_const_circulator circ, bool has_area = true) { typename Arr::Ccb_halfedge_const_circulator curr = circ; do { typename Arr::Halfedge_const_handle e = curr; add_segment(e->source()->point(), e->target()->point()); add_point(e->source()->point()); - add_point_in_face(e->source()->point()); + if (has_area) add_point_in_face(e->source()->point()); } while (++curr != circ); } - void add_face(typename Arr::Face_const_handle f, CGAL::IO::Color c) { - if (! f->is_unbounded()) { + //! + void add_face(Face_const_handle face, CGAL::IO::Color c) { + if (! face->is_unbounded()) { face_begin(c); - add_ccb(f->outer_ccb()); - for (auto iv = f->isolated_vertices_begin(); - iv != f->isolated_vertices_end(); ++iv) + add_ccb(face->outer_ccb()); + for (auto iv = face->isolated_vertices_begin(); + iv != face->isolated_vertices_end(); ++iv) add_point(iv->point()); face_end(); } - for (auto it = f->inner_ccbs_begin(); it != f->inner_ccbs_end(); ++it) { - face_begin(c); - add_ccb(*it); - for (auto iv = f->isolated_vertices_begin(); - iv != f->isolated_vertices_end(); ++iv) - add_point(iv->point()); - face_end(); + std::map visited; + for (auto it = face->inner_ccbs_begin(); it != face->inner_ccbs_end(); ++it) { + auto new_face = (*it)->twin()->face(); + if (new_face == face) { + add_ccb(*it, false); + continue; + } + if (visited.find(new_face) != visited.end()) continue; + visited[new_face] = true; + add_face(new_face, c); } } + //! void add_elements() { clear(); if (m_arr.is_empty()) return; CGAL::IO::Color c(75,160,255); - for (auto fit = m_arr.faces_begin(); fit != m_arr.faces_end(); ++fit) - add_face(fit, c); + for (auto it = m_arr.unbounded_faces_begin(); it != m_arr.unbounded_faces_end(); ++it) + add_face(it, c); } + //! virtual void keyPressEvent(QKeyEvent* e) { // Test key pressed: // const ::Qt::KeyboardModifiers modifiers = e->modifiers(); From 81b67b07086910ac099f960472a78d3279953422 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Thu, 19 May 2022 16:44:12 +0300 Subject: [PATCH 005/105] Started to use std::bitset for the info field --- .../CGAL/Arr_geometry_traits/Conic_arc_2.h | 164 ++++---- .../Conic_x_monotone_arc_2.h | 352 ++++++++++-------- 2 files changed, 287 insertions(+), 229 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h index a2fb69131fb..4f8a7900ed2 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h @@ -15,17 +15,17 @@ #include - /*! \file * Header file for the _Conic_arc_2 class. */ +#include +#include + #include #include #include -#include - namespace CGAL { /*! Representation of a conic arc -- a bounded segment that lies on a conic @@ -63,24 +63,29 @@ public: typedef _Conic_point_2 Conic_point_2; protected: - Integer m_r; // - Integer m_s; // The coefficients of the supporting conic curve: - Integer m_t; // - Integer m_u; // - Integer m_v; // r*x^2 + s*y^2 + t*xy + u*x + v*y +w = 0 . - Integer m_w; // + Integer m_r; // + Integer m_s; // The coefficients of the supporting conic curve: + Integer m_t; // + Integer m_u; // + Integer m_v; // r*x^2 + s*y^2 + t*xy + u*x + v*y +w = 0 . + Integer m_w; // - Orientation m_orient; // The orientation of the conic. + Orientation m_orient; // The orientation of the conic. // Bit masks for the m_info field. enum { IS_VALID = 1, - IS_FULL_CONIC = 2 + IS_FULL_CONIC = 2, + + IS_VALID_ = 0, + IS_FULL_CONIC_, + LAST_INFO, }; - int m_info; // Does the arc represent a full conic curve. - Conic_point_2 m_source; // The source of the arc (if not a full curve). - Conic_point_2 m_target; // The target of the arc (if not a full curve). + int m_old_info; // does the arc represent a full conic curve. + std::bitset<16> m_new_info; // does the arc represent a full conic curve. + Conic_point_2 m_source; // the source of the arc (if not a full curve). + Conic_point_2 m_target; // the target of the arc (if not a full curve). /*! \struct * For arcs whose base is a hyperbola we store the axis (a*x + b*y + c = 0) @@ -97,8 +102,8 @@ protected: Sign side; }; - Extra_data* m_extra_data; // The extra data stored with the arc - // (may be nullptr). + Extra_data* m_extra_data; // The extra data stored with the arc + // (may be nullptr). public: /// \name Construction and destruction functions. @@ -110,7 +115,8 @@ public: _Conic_arc_2() : m_r(0), m_s(0), m_t(0), m_u(0), m_v(0), m_w(0), m_orient(COLLINEAR), - m_info(0), + m_old_info(0), + m_new_info(0), m_extra_data(nullptr) {} @@ -121,7 +127,8 @@ public: m_r(arc.m_r), m_s(arc.m_s), m_t(arc.m_t), m_u(arc.m_u), m_v(arc.m_v), m_w(arc.m_w), m_orient(arc.m_orient), - m_info(arc.m_info), + m_old_info(arc.m_old_info), + m_new_info(arc.m_new_info), m_source(arc.m_source), m_target(arc.m_target) { @@ -135,6 +142,8 @@ public: */ _Conic_arc_2(const Rational& r, const Rational& s, const Rational& t, const Rational& u, const Rational& v, const Rational& w) : + m_old_info(0), + m_new_info(0), m_extra_data(nullptr) { // Make sure the given curve is an ellipse (4rs - t^2 should be positive). @@ -166,6 +175,8 @@ public: const Orientation& orient, const Point_2& source, const Point_2& target) : m_orient(orient), + m_old_info(0), + m_new_info(0), m_source(source), m_target(target), m_extra_data(nullptr) @@ -192,7 +203,8 @@ public: */ _Conic_arc_2(const Point_2& source, const Point_2& target) : m_orient(COLLINEAR), - m_info(static_cast(IS_VALID)), + m_old_info(static_cast(IS_VALID)), + m_new_info(0), m_source(source), m_target(target), m_extra_data(nullptr) @@ -200,6 +212,8 @@ public: CGAL_precondition(Alg_kernel().compare_xy_2_object()(m_source, m_target) != EQUAL); + m_new_info.set(IS_VALID_); + // Compose the equation of the underlying line. const Algebraic x1 = source.x(); const Algebraic y1 = source.y(); @@ -216,12 +230,13 @@ public: m_extra_data->side = ZERO; } - /*! - * Construct a conic arc from the given line segment. + /*! Construct a conic arc from a given line segment. * \param seg The line segment with rational endpoints. */ _Conic_arc_2(const Rat_segment_2& seg) : m_orient(COLLINEAR), + m_old_info(0), + m_new_info(0), m_extra_data (nullptr) { // Set the source and target. @@ -271,11 +286,13 @@ public: set(rat_coeffs); } - /*! Set a circular arc that corresponds to a full circle. + /*! Construct a conic arc that is a full circle. * \param circ The circle (with rational center and rational squared radius). */ _Conic_arc_2(const Rat_circle_2& circ) : m_orient(CLOCKWISE), + m_old_info(0), + m_new_info(0), m_extra_data(nullptr) { // Get the circle properties. @@ -306,7 +323,7 @@ public: set_full(rat_coeffs, false); } - /*! Set a circular arc that lies on the given circle: + /*! Construct a conic arc that lies on a given circle: * C: (x - x0)^2 + (y - y0)^2 = R^2 * \param orient The orientation of the circle. * \param source The source point. @@ -318,6 +335,8 @@ public: const Orientation& orient, const Point_2& source, const Point_2& target) : m_orient(orient), + m_old_info(0), + m_new_info(0), m_source(source), m_target(target), m_extra_data(nullptr) @@ -370,8 +389,7 @@ public: set(rat_coeffs); } - /*! - * Construct a circular arc from the given three points. + /*! Construct a conic arc that is a circular arc from given three points. * \param p1 The arc source. * \param p2 A point in the interior of the arc. * \param p3 The arc target. @@ -379,6 +397,8 @@ public: */ _Conic_arc_2(const Rat_point_2& p1, const Rat_point_2& p2, const Rat_point_2& p3): + m_old_info(0), + m_new_info(0), m_extra_data(nullptr) { // Set the source and target. @@ -420,7 +440,8 @@ public: const bool points_collinear = (CGAL::sign(D) == ZERO); if (points_collinear) { - m_info = 0; // Inavlid arc. + m_old_info = 0; // inavlid arc. + m_new_info.reset(); // inavlid arc return; } @@ -451,7 +472,7 @@ public: set(rat_coeffs); } - /*! Construct a conic arc from the given five points, specified by the + /*! Construct a conic arc from given five points, specified by the * points p1, p2, p3, p4 and p5. * \param p1 The source point of the given arc. * \param p2,p3,p4 Points lying on the conic arc, between p1 and p5. @@ -461,6 +482,8 @@ public: _Conic_arc_2(const Rat_point_2& p1, const Rat_point_2& p2, const Rat_point_2& p3, const Rat_point_2& p4, const Rat_point_2& p5) : + m_old_info(0), + m_new_info(0), m_extra_data(nullptr) { // Make sure that no three points are collinear. @@ -479,7 +502,8 @@ public: orient_f(p3, p4, p5) == COLLINEAR); if (point_collinear) { - m_info = 0; // Inavlid arc. + m_old_info = 0; // Inavlid arc. + m_new_info.reset(); // inavlid arc return; } @@ -537,11 +561,12 @@ public: ! is_strictly_between_endpoints(mp3) || ! is_strictly_between_endpoints(mp4)) { - m_info = 0; // Inalvid arc. + m_old_info = 0; // Inalvid arc. + m_new_info.reset(); // inavlid arc } } - /*! Construct a conic arc which lies on the conic: + /*! Construct a conic arc that lies on a conic given by its coefficients: * C: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0 * The source and the target are specified by the intersection of the * conic with: @@ -561,6 +586,8 @@ public: const Rational& r_2, const Rational& s_2, const Rational& t_2, const Rational& u_2, const Rational& v_2, const Rational& w_2): m_orient(orient), + m_old_info(0), + m_new_info(0), m_extra_data(nullptr) { // Create the integer coefficients of the base conic. @@ -616,15 +643,9 @@ public: nt_traits.convert_coefficients(aux_rat_coeffs, aux_rat_coeffs + 6, aux_coeffs); - if (CGAL::sign(aux_coeffs[0]) == ZERO && - CGAL::sign(aux_coeffs[1]) == ZERO && - CGAL::sign(aux_coeffs[2]) == ZERO) - { - deg_aux = 1; - } - else { - deg_aux = 2; - } + deg_aux = ((CGAL::sign(aux_coeffs[0]) == ZERO) && + (CGAL::sign(aux_coeffs[1]) == ZERO) && + (CGAL::sign(aux_coeffs[2]) == ZERO)) ? 1 : 2; // Compute the x- and y-coordinates of intersection points of the base // conic and the k'th auxiliary conic. @@ -704,14 +725,16 @@ public: } if (! found) { - m_info = 0; // Invalid arc. + m_old_info = 0; // Invalid arc. + m_new_info.reset(); // inavlid arc return; } } // Make sure that the source and the target are not the same. if (Alg_kernel().compare_xy_2_object()(m_source, m_target) == EQUAL) { - m_info = 0; // Invalid arc. + m_old_info = 0; // Invalid arc. + m_new_info.reset(); // inavlid arc return; } @@ -721,8 +744,7 @@ public: /*! Destructor. */ - virtual ~_Conic_arc_2() - { if (m_extra_data != nullptr) delete m_extra_data; } + virtual ~_Conic_arc_2() { if (m_extra_data != nullptr) delete m_extra_data; } /*! Assignment operator. * \param arc The copied arc. @@ -742,7 +764,8 @@ public: m_w = arc.m_w; m_orient = arc.m_orient; - m_info = arc.m_info; + m_old_info = arc.m_old_info; + m_new_info = arc.m_new_info; m_source = arc.m_source; m_target = arc.m_target; @@ -757,9 +780,9 @@ public: /// \name Get the arc properties. //@{ - /*! Check if the arc is valid. + /*! Check wheather the arc is valid. */ - bool is_valid() const { return ((m_info & IS_VALID) != 0); } + bool is_valid() const { return m_new_info.test(IS_VALID_); } /*! Get the coefficients of the underlying conic. */ @@ -788,7 +811,9 @@ public: /*! Check whether the arc represents a full conic curve. */ - bool is_full_conic() const { return ((m_info & IS_FULL_CONIC) != 0); } + bool is_full_conic() const { + return m_new_info.test(IS_FULL_CONIC_); + } /*! Get the arc's source. * \return The source point. @@ -803,8 +828,7 @@ public: * \return The target point. * \pre The arc does not represent a full conic curve. */ - const Point_2& target() const - { + const Point_2& target() const { CGAL_precondition(! is_full_conic()); return m_target; } @@ -818,10 +842,9 @@ public: * \return The bounding box. */ Bbox_2 bbox() const { - CGAL_precondition (is_valid()); + CGAL_precondition(is_valid()); - double x_min = 0, y_min = 0; - double x_max = 0, y_max = 0; + double x_min(0), y_min(0), x_max(0), y_max(0); if (is_full_conic()) { // In case of a full conic (an ellipse or a circle), compute the @@ -994,8 +1017,7 @@ public: return m; } - /*! - * Find all points on the arc with a given x-coordinate. + /*! Find all points on the arc with a given x-coordinate. * \param p A placeholder for the x-coordinate. * \param ps The point on the arc at x(p). * \pre The vector ps should be allocated at the size of 2. @@ -1054,7 +1076,8 @@ private: * of x^2, y^2, xy, x, y and the free coefficient resp. */ void set(const Rational* rat_coeffs) { - m_info = IS_VALID; + m_old_info = IS_VALID; + m_new_info.set(IS_VALID_); // Convert the coefficients vector to an equivalent vector of integer // coefficients. @@ -1090,7 +1113,8 @@ private: if (! is_on_supporting_conic(m_source) || ! is_on_supporting_conic(m_target)) { - m_info = 0; // Invalid arc. + m_old_info = 0; // Invalid arc. + m_new_info.reset(); // inavlid arc return; } @@ -1130,7 +1154,8 @@ private: nt_traits.convert(m_v)) * p_mid.y() + nt_traits.convert(m_w)) != ZERO) { - m_info = 0; // Invalid arc. + m_old_info = 0; // Invalid arc. + m_new_info.reset(); // inavlid arc return; } } @@ -1141,9 +1166,8 @@ private: // - if it is zero, the conic is a parabola. CGAL::Sign sign_conic = CGAL::sign(4*m_r*m_s - m_t*m_t); - if (sign_conic == NEGATIVE) - // Build the extra hyperbolic data - build_hyperbolic_arc_data(); + // Build the extra hyperbolic data if necessary + if (sign_conic == NEGATIVE) build_hyperbolic_arc_data(); if (sign_conic != POSITIVE) { // In case of a non-degenerate parabola or a hyperbola, make sure @@ -1156,7 +1180,8 @@ private: bool finite_at_y = (points_at_y(p_mid, ps) > 0); if (! finite_at_x && ! finite_at_y) { - m_info = 0; // Invalid arc. + m_old_info = 0; // Invalid arc. + m_new_info.reset(); // inavlid arc return; } } @@ -1164,7 +1189,8 @@ private: } // Mark that this arc valid and is not a full conic curve. - m_info = IS_VALID; + m_old_info = IS_VALID; + m_new_info.set(IS_VALID_); } /*! Set the properties of a conic arc that is really a full curve @@ -1216,12 +1242,18 @@ private: m_extra_data = nullptr; // Mark that this arc is a full conic curve. - if (is_ellipse) m_info = IS_VALID | IS_FULL_CONIC; - else m_info = 0; + if (is_ellipse) { + m_old_info = IS_VALID | IS_FULL_CONIC; + m_new_info.set(IS_VALID_); + m_new_info.set(IS_FULL_CONIC_); + } + else { + m_old_info = 0; + m_new_info.reset(); // inavlid arc + } } - /*! - * Build the data for hyperbolic arc, contaning the characterization of the + /*! Build the data for hyperbolic arc, contaning the characterization of the * hyperbolic branch the arc is placed on. */ void build_hyperbolic_arc_data() { diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h index ecd98ee490f..90d9615c958 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h @@ -19,6 +19,7 @@ */ #include +#include #include #include @@ -31,11 +32,11 @@ namespace CGAL { * The class is templated by a representation of a general bounded conic arc. */ -template -class _Conic_x_monotone_arc_2 : private Conic_arc_ { +template +class _Conic_x_monotone_arc_2 : private ConicArc { public: - typedef Conic_arc_ Conic_arc_2; + typedef ConicArc Conic_arc_2; typedef _Conic_x_monotone_arc_2 Self; typedef typename Conic_arc_2::Alg_kernel Alg_kernel; @@ -54,8 +55,13 @@ public: using Conic_arc_2::is_between_endpoints; using Conic_arc_2::is_strictly_between_endpoints; using Conic_arc_2::conic_get_y_coordinates; - /*! - * \struct Less functor for Conic_pair. + + using Conic_arc_2::IS_VALID; + using Conic_arc_2::IS_VALID_; + using Conic_arc_2::IS_FULL_CONIC; + using Conic_arc_2::IS_FULL_CONIC_; + + /*! \struct Less functor for Conic_pair. */ struct Less_conic_pair { bool operator()(const Conic_pair& cp1, const Conic_pair& cp2) const { @@ -89,7 +95,16 @@ protected: FACING_UP = 128, FACING_DOWN = 256, FACING_MASK = 128 + 256, - IS_SPECIAL_SEGMENT = 512 + IS_SPECIAL_SEGMENT = 512, + + IS_VERTICAL_SEGMENT_ = Conic_arc_2::LAST_INFO, + IS_DIRECTED_RIGHT_, + DEGREE_1_, + DEGREE_2_, + PLUS_SQRT_DISC_ROOT_, + FACING_UP_, + FACING_DOWN_, + IS_SPECIAL_SEGMENT_ }; Algebraic alg_r; // The coefficients of the supporting conic curve: @@ -102,20 +117,17 @@ protected: Conic_id m_id; // The ID number of the supporting conic curve. public: - /// \name Constrcution methods. //@{ - /*! - * Default constructor. + /*! Default constructor. */ - _Conic_x_monotone_arc_2 () : + _Conic_x_monotone_arc_2() : Base(), m_id() {} - /*! - * Copy constructor. + /*! Copy constructor. * \param arc The copied arc. */ _Conic_x_monotone_arc_2(const Self& arc) : @@ -182,19 +194,26 @@ public: _Conic_x_monotone_arc_2(const Point_2& source, const Point_2& target) : Base(source, target) { - this->m_info |= static_cast(DEGREE_1); + this->m_old_info |= static_cast(DEGREE_1); + this->m_new_info.set(DEGREE_1); Alg_kernel ker; auto cmp_xy = ker.compare_xy_2_object(); Comparison_result dir_res = cmp_xy(this->m_source, this->m_target); - if (dir_res == SMALLER) this->m_info |= IS_DIRECTED_RIGHT; + if (dir_res == SMALLER) { + this->m_old_info |= IS_DIRECTED_RIGHT; + this->m_new_info.set(IS_DIRECTED_RIGHT_); + } // Check if the segment is vertical. - if (CGAL::sign(this->m_extra_data->b) == ZERO) - this->m_info |= IS_VERTICAL_SEGMENT; + if (CGAL::sign(this->m_extra_data->b) == ZERO) { + this->m_old_info |= IS_VERTICAL_SEGMENT; + this->m_new_info.set(IS_VERTICAL_SEGMENT_); + } // Mark that this is a special segment. - this->m_info |= IS_SPECIAL_SEGMENT; + this->m_old_info |= IS_SPECIAL_SEGMENT; + this->m_new_info.set(IS_SPECIAL_SEGMENT_); } /*! Construct a special segment of a given line connecting to given @@ -216,11 +235,12 @@ public: CGAL_precondition (CGAL::sign(a * target.x() + b * target.y() + c) == CGAL::ZERO); - // Set the basic properties and clear the m_info bits. + // Set the basic properties and clear the m_old_info bits. this->m_source = source; this->m_target = target; this->m_orient = COLLINEAR; - this->m_info = 0; + this->m_old_info = 0; + this->m_new_info.reset(); // inavlid arc // Check if the arc is directed right (the target is lexicographically // greater than the source point), or to the left. @@ -228,11 +248,14 @@ public: Comparison_result res = ker.compare_x_2_object()(this->m_source, this->m_target); - this->m_info = - (static_cast(Conic_arc_2::IS_VALID) | static_cast(DEGREE_1)); + this->m_old_info = + (static_cast(IS_VALID) | static_cast(DEGREE_1)); + this->m_new_info.set(IS_VALID_); + this->m_new_info.set(DEGREE_1_); if (res == EQUAL) { // Mark that the segment is vertical. - this->m_info = (this->m_info | IS_VERTICAL_SEGMENT); + this->m_old_info = (this->m_old_info | IS_VERTICAL_SEGMENT); + this->m_new_info.set(IS_VERTICAL_SEGMENT_); // Compare the endpoints lexicographically. res = ker.compare_y_2_object()(this->m_source, this->m_target); @@ -240,13 +263,16 @@ public: CGAL_precondition (res != EQUAL); if (res == EQUAL) { // Invalid arc: - this->m_info = 0; + this->m_old_info = 0; + this->m_new_info.reset(); // inavlid arc return; } } - if (res == SMALLER) - this->m_info = (this->m_info | IS_DIRECTED_RIGHT); + if (res == SMALLER) { + this->m_old_info = (this->m_old_info | IS_DIRECTED_RIGHT); + this->m_new_info.set(IS_DIRECTED_RIGHT_); + } // Store the coefficients of the line. this->m_extra_data = new typename Base::Extra_data; @@ -256,13 +282,11 @@ public: this->m_extra_data->side = ZERO; // Mark that this is a special segment. - this->m_info = (this->m_info | IS_SPECIAL_SEGMENT); - - return; + this->m_old_info = (this->m_old_info | IS_SPECIAL_SEGMENT); + this->m_new_info.set(IS_SPECIAL_SEGMENT_); } - /*! - * Assignment operator. + /*! Assignment operator. * \param arc The copied arc. */ const Self& operator=(const Self& arc) { @@ -290,82 +314,73 @@ public: /// \name Accessing the arc properties. //@{ - /*! - * Get the coefficients of the underlying conic. + /*! Obtain the coefficients of the underlying conic. */ - const Integer& r() const { return (this->m_r); } - const Integer& s() const { return (this->m_s); } - const Integer& t() const { return (this->m_t); } - const Integer& u() const { return (this->m_u); } - const Integer& v() const { return (this->m_v); } - const Integer& w() const { return (this->m_w); } + const Integer& r() const { return ( this->m_r); } + const Integer& s() const { return ( this->m_s); } + const Integer& t() const { return ( this->m_t); } + const Integer& u() const { return ( this->m_u); } + const Integer& v() const { return ( this->m_v); } + const Integer& w() const { return ( this->m_w); } - /*! - * Get the arc's source. + /*! Obtain the arc's source. * \return The source point. */ const Conic_point_2& source() const { return (this->m_source); } - /*! Get the arc's target. + /*! Obtain the arc's target. * \return The target point. */ - const Conic_point_2& target() const { return (this->m_target); } + const Conic_point_2& target() const { return this->m_target; } - /*! Get the orientation of the arc. + /*! Obtain the orientation of the arc. * \return The orientation. */ - Orientation orientation() const { return (this->m_orient); } + Orientation orientation() const { return this->m_orient; } - /*! Get the left endpoint of the arc. + /*! Obtain the left endpoint of the arc. */ const Conic_point_2& left() const { - if ((this->m_info & IS_DIRECTED_RIGHT) != 0) return (this->m_source); - else return (this->m_target); + if (this->m_new_info.test(IS_DIRECTED_RIGHT_)) return this->m_source; + else return this->m_target; } - /*! Get the right endpoint of the arc. + /*! Obtain the right endpoint of the arc. */ - const Conic_point_2& right() const - { - if ((this->m_info & IS_DIRECTED_RIGHT) != 0) return (this->m_target); - else return (this->m_source); + const Conic_point_2& right() const { + if (this->m_new_info.test(IS_DIRECTED_RIGHT_)) return this->m_target; + else return this->m_source; } - /*! - * Return true iff the conic arc is directed right iexicographically. + /*! Return true iff the conic arc is directed right iexicographically. */ bool is_directed_right() const - { return ((this->m_info & IS_DIRECTED_RIGHT) != 0); } + { return this->m_new_info.test(IS_DIRECTED_RIGHT_); } - /*! - * Get a bounding box for the conic arc. + /*! Obtain a bounding box for the conic arc. * \return The bounding box. */ - Bbox_2 bbox() const { return (Base::bbox()); } + Bbox_2 bbox() const { return Base::bbox(); } //@} /// \name Predicates. //@{ - /*! - * Check if the conic arc is a vertical segment. + /*! Check if the conic arc is a vertical segment. */ bool is_vertical() const - { return ((this->m_info & IS_VERTICAL_SEGMENT) != 0); } + { return this->m_new_info.test(IS_VERTICAL_SEGMENT_); } - /*! - * Check whether the given point lies on the arc. + /*! Check whether the given point lies on the arc. * \param p The qury point. * \param (true) if p lies on the arc; (false) otherwise. */ bool contains_point(const Conic_point_2& p) const { // First check if p lies on the supporting conic. We first check whether // it is one of p's generating conic curves. - bool p_on_conic = false; + bool p_on_conic(false); - if (p.is_generating_conic(m_id)) { - p_on_conic = true; - } + if (p.is_generating_conic(m_id)) p_on_conic = true; else { // Check whether p satisfies the supporting conic equation. p_on_conic = is_on_supporting_conic(p.x(), p.y()); @@ -378,7 +393,7 @@ public: } } - if (! p_on_conic) return (false); + if (! p_on_conic) return false; // Check if p is between the endpoints of the arc. return is_between_endpoints(p); @@ -395,12 +410,12 @@ public: */ Point_2 point_at_x(const Point_2& p) const { // Make sure that p is in the x-range of the arc. - CGAL_precondition((this->m_info & IS_VERTICAL_SEGMENT) == 0); + CGAL_precondition(! this->m_new_info.test(IS_VERTICAL_SEGMENT_)); CGAL_precondition_code(Alg_kernel ker;); - CGAL_precondition(ker.compare_x_2_object() (p, left()) != SMALLER && - ker.compare_x_2_object() (p, right()) != LARGER); + CGAL_precondition(ker.compare_x_2_object()(p, left()) != SMALLER && + ker.compare_x_2_object()(p, right()) != LARGER); if (is_special_segment()) { // In case of a special segment, the equation of the supported line @@ -410,7 +425,7 @@ public: this->m_extra_data->b; // Return the computed point. - return Point_2 (p.x(), _y); + return Point_2(p.x(), _y); } // Compute the y-coordinate according to the degree of the supporting @@ -418,7 +433,7 @@ public: Nt_traits nt_traits; Algebraic y; - if ((this->m_info & DEGREE_MASK) == DEGREE_1) { + if ((this->m_old_info & DEGREE_MASK) == DEGREE_1) { // In case of a linear curve, the y-coordinate is a simple linear // expression of x(p) (note that v is not 0 as the arc is not vertical): // y = -(u*x(p) + w) / v @@ -433,7 +448,7 @@ public: this->m_extra_data->c) / this->m_extra_data->b; } else { - CGAL_assertion((this->m_info & DEGREE_MASK) == DEGREE_2); + CGAL_assertion((this->m_old_info & DEGREE_MASK) == DEGREE_2); // In this case the y-coordinate is one of solutions to the quadratic // equation: @@ -456,7 +471,7 @@ public: // We take either the root involving -sqrt(disc) or +sqrt(disc) // based on the information flags. - if ((this->m_info & PLUS_SQRT_DISC_ROOT) != 0) { + if (this->m_new_info.test(PLUS_SQRT_DISC_ROOT_)) { y = (nt_traits.sqrt (disc) - B) / (2*A); } else { @@ -469,7 +484,7 @@ public: return Point_2(p.x(), y); } - /*! Get a polyline approximating the conic arc. + /*! Obtain a polyline approximating the conic arc. * \param n The maximal number of sample points. * \param oi An output iterator, whose value-type is pair * (representing an approximated point). @@ -489,18 +504,18 @@ public: if (this->m_orient == COLLINEAR) { // In case of a line segment, return the two endpoints. - *oi++ = std::pair (x_left, y_left); - *oi++ = std::pair (x_right, y_right); + *oi++ = std::pair(x_left, y_left); + *oi++ = std::pair(x_right, y_right); return oi; } // Otherwise, sample (n - 1) equally-spaced points in between. - const double app_r = CGAL::to_double (this->m_r); - const double app_s = CGAL::to_double (this->m_s); - const double app_t = CGAL::to_double (this->m_t); - const double app_u = CGAL::to_double (this->m_u); - const double app_v = CGAL::to_double (this->m_v); - const double app_w = CGAL::to_double (this->m_w); + const double app_r = CGAL::to_double(this->m_r); + const double app_s = CGAL::to_double(this->m_s); + const double app_t = CGAL::to_double(this->m_t); + const double app_u = CGAL::to_double(this->m_u); + const double app_v = CGAL::to_double(this->m_v); + const double app_w = CGAL::to_double(this->m_w); const double x_jump = (x_right - x_left) / n; double x, y; const bool A_is_zero = (CGAL::sign(this->m_s) == ZERO); @@ -508,7 +523,7 @@ public: double disc; size_t i; - *oi++ = std::pair(x_left, y_left); // The left point. + *oi++ = std::pair(x_left, y_left); // the left point for (i = 1; i < n; ++i) { x = x_left + x_jump*i; @@ -523,12 +538,12 @@ public: // We take either the root involving -sqrt(disc) or +sqrt(disc) // based on the information flags. - y = ((this->m_info & PLUS_SQRT_DISC_ROOT) != 0) ? + y = ((this->m_old_info & PLUS_SQRT_DISC_ROOT) != 0) ? (std::sqrt(disc) - B) / (2*A) : -(B + std::sqrt (disc)) / (2*A); } - *oi++ = std::pair (x, y); + *oi++ = std::pair(x, y); } - *oi++ = std::pair (x_right, y_right); // The right point. + *oi++ = std::pair(x_right, y_right); // the right point return oi; } @@ -542,20 +557,19 @@ public: Comparison_result compare_to_right(const Self& arc, const Conic_point_2& p) const { - CGAL_precondition((this->m_info & IS_VERTICAL_SEGMENT) == 0 && - (arc.m_info & IS_VERTICAL_SEGMENT) == 0); + CGAL_precondition((this->m_old_info & IS_VERTICAL_SEGMENT) == 0 && + (arc.m_old_info & IS_VERTICAL_SEGMENT) == 0); // In case one arc is facing upwards and another facing downwards, it is // clear that the one facing upward is above the one facing downwards. if (has_same_supporting_conic (arc)) { - if ((this->m_info & FACING_UP) != 0 && (arc.m_info & FACING_DOWN) != 0) + if (this->m_new_info.test(FACING_UP_) && arc.m_new_info.test(FACING_DOWN_)) return LARGER; - else if ((this->m_info & FACING_DOWN) != 0 && (arc.m_info & FACING_UP) != - 0) + else if (this->m_new_info.test(FACING_DOWN_) && arc.m_new_info.test(FACING_UP_)) return SMALLER; // In this case the two arcs overlap. - CGAL_assertion((this->m_info & FACING_MASK) == (arc.m_info & FACING_MASK)); + CGAL_assertion((this->m_old_info & FACING_MASK) == (arc.m_old_info & FACING_MASK)); return EQUAL; } @@ -603,31 +617,31 @@ public: else if ( !is_vertical_slope2) { // The first arc has a vertical slope at p: check whether it is // facing upwards or downwards and decide accordingly. - CGAL_assertion ((this->m_info & FACING_MASK) != 0); + CGAL_assertion ((this->m_old_info & FACING_MASK) != 0); - if ((this->m_info & FACING_UP) != 0) return LARGER; + if ((this->m_old_info & FACING_UP) != 0) return LARGER; return SMALLER; } else if (! is_vertical_slope1) { // The second arc has a vertical slope at p_int: check whether it is // facing upwards or downwards and decide accordingly. - CGAL_assertion ((arc.m_info & FACING_MASK) != 0); + CGAL_assertion ((arc.m_old_info & FACING_MASK) != 0); - if ((arc.m_info & FACING_UP) != 0) return SMALLER; + if ((arc.m_old_info & FACING_UP) != 0) return SMALLER; return LARGER; } // The two arcs have vertical slopes at p_int: // First check whether one is facing up and one down. In this case the // comparison result is trivial. - if ((this->m_info & FACING_UP) != 0 && (arc.m_info & FACING_DOWN) != 0) + if ((this->m_old_info & FACING_UP) != 0 && (arc.m_old_info & FACING_DOWN) != 0) return (LARGER); - else if ((this->m_info & FACING_DOWN) != 0 && (arc.m_info & FACING_UP) != 0) + else if ((this->m_old_info & FACING_DOWN) != 0 && (arc.m_old_info & FACING_UP) != 0) return SMALLER; // Compute the second-order derivative by y and act according to it. - derive_by_y_at (p, 2, slope1_numer, slope1_denom); - arc.derive_by_y_at (p, 2, slope2_numer, slope2_denom); + derive_by_y_at(p, 2, slope1_numer, slope1_denom); + arc.derive_by_y_at(p, 2, slope2_numer, slope2_denom); Comparison_result slope_res = CGAL::compare(slope1_numer*slope2_denom, slope2_numer*slope1_denom); @@ -645,7 +659,7 @@ public: // \todo Handle higher-order derivatives: CGAL_assertion(slope_res != EQUAL); - if ((this->m_info & FACING_UP) != 0 && (arc.m_info & FACING_UP) != 0) { + if ((this->m_old_info & FACING_UP) != 0 && (arc.m_old_info & FACING_UP) != 0) { // Both are facing up. return ((slope_res == LARGER) ? SMALLER : LARGER); } @@ -662,20 +676,20 @@ public: Comparison_result compare_to_left(const Self& arc, const Conic_point_2& p) const { - CGAL_precondition((this->m_info & IS_VERTICAL_SEGMENT) == 0 && - (arc.m_info & IS_VERTICAL_SEGMENT) == 0); + CGAL_precondition((this->m_old_info & IS_VERTICAL_SEGMENT) == 0 && + (arc.m_old_info & IS_VERTICAL_SEGMENT) == 0); // In case one arc is facing upwards and another facing downwards, it is // clear that the one facing upward is above the one facing downwards. if (has_same_supporting_conic (arc)) { - if ((this->m_info & FACING_UP) != 0 && (arc.m_info & FACING_DOWN) != 0) + if ((this->m_old_info & FACING_UP) != 0 && (arc.m_old_info & FACING_DOWN) != 0) return LARGER; - else if ((this->m_info & FACING_DOWN) != 0 && (arc.m_info & FACING_UP) != + else if ((this->m_old_info & FACING_DOWN) != 0 && (arc.m_old_info & FACING_UP) != 0) return SMALLER; // In this case the two arcs overlap. - CGAL_assertion((this->m_info & FACING_MASK) == (arc.m_info & FACING_MASK)); + CGAL_assertion((this->m_old_info & FACING_MASK) == (arc.m_old_info & FACING_MASK)); return EQUAL; } @@ -701,8 +715,8 @@ public: if (slope_res != EQUAL) return (slope_res); // Use the second-order derivative. - derive_by_x_at (p, 2, slope1_numer, slope1_denom); - arc.derive_by_x_at (p, 2, slope2_numer, slope2_denom); + derive_by_x_at(p, 2, slope1_numer, slope1_denom); + arc.derive_by_x_at(p, 2, slope2_numer, slope2_denom); slope_res = CGAL::compare(slope1_numer*slope2_denom, slope2_numer*slope1_denom); @@ -724,26 +738,26 @@ public: else if (! is_vertical_slope2) { // The first arc has a vertical slope at p: check whether it is // facing upwards or downwards and decide accordingly. - CGAL_assertion ((this->m_info & FACING_MASK) != 0); + CGAL_assertion((this->m_old_info & FACING_MASK) != 0); - if ((this->m_info & FACING_UP) != 0) return LARGER; + if ((this->m_old_info & FACING_UP) != 0) return LARGER; return SMALLER; } else if (! is_vertical_slope1) { // The second arc has a vertical slope at p_int: check whether it is // facing upwards or downwards and decide accordingly. - CGAL_assertion((arc.m_info & FACING_MASK) != 0); + CGAL_assertion((arc.m_old_info & FACING_MASK) != 0); - if ((arc.m_info & FACING_UP) != 0) return SMALLER; + if ((arc.m_old_info & FACING_UP) != 0) return SMALLER; return LARGER; } // The two arcs have vertical slopes at p_int: // First check whether one is facing up and one down. In this case the // comparison result is trivial. - if ((this->m_info & FACING_UP) != 0 && (arc.m_info & FACING_DOWN) != 0) + if ((this->m_old_info & FACING_UP) != 0 && (arc.m_old_info & FACING_DOWN) != 0) return LARGER; - else if ((this->m_info & FACING_DOWN) != 0 && (arc.m_info & FACING_UP) != 0) + else if ((this->m_old_info & FACING_DOWN) != 0 && (arc.m_old_info & FACING_UP) != 0) return SMALLER; // Compute the second-order derivative by y and act according to it. @@ -766,12 +780,12 @@ public: // \todo Handle higher-order derivatives: CGAL_assertion(slope_res != EQUAL); - if ((this->m_info & FACING_UP) != 0 && (arc.m_info & FACING_UP) != 0) { + if ((this->m_old_info & FACING_UP) != 0 && (arc.m_old_info & FACING_UP) != 0) { // Both are facing up. return ((slope_res == LARGER) ? SMALLER : LARGER); } // Both are facing down. - return (slope_res); + return slope_res; } /*! Compute the intersections with the given arc. @@ -884,7 +898,7 @@ public: c2 = *this; // Assign the endpoints of the arc. - if ((this->m_info & IS_DIRECTED_RIGHT) != 0) { + if ((this->m_old_info & IS_DIRECTED_RIGHT) != 0) { // The arc is directed from left to right, so p becomes c1's target // and c2's source. c1.m_target = p; @@ -924,7 +938,8 @@ public: arc.m_target = this->m_source; // Change the direction bit among the information flags. - arc.m_info = (this->m_info ^ IS_DIRECTED_RIGHT); + arc.m_old_info = (this->m_old_info ^ IS_DIRECTED_RIGHT); + arc.m_new_info.flip(IS_DIRECTED_RIGHT_); return arc; } @@ -938,21 +953,21 @@ public: */ Self trim(const Conic_point_2& ps, const Conic_point_2& pt) const { // Make sure that both ps and pt lie on the arc. - CGAL_precondition(this->contains_point (ps) && - this->contains_point (pt)); + CGAL_precondition(this->contains_point(ps) && this->contains_point(pt)); // Make sure that the endpoints conform with the direction of the arc. Self arc = *this; Alg_kernel ker; - if (! ((((this->m_info & IS_DIRECTED_RIGHT) != 0) && - ker.compare_xy_2_object() (ps, pt) == SMALLER) || - (((this->m_info & IS_DIRECTED_RIGHT) == 0) && - ker.compare_xy_2_object() (ps, pt) == LARGER))) + if (! ((((this->m_old_info & IS_DIRECTED_RIGHT) != 0) && + ker.compare_xy_2_object()(ps, pt) == SMALLER) || + (((this->m_old_info & IS_DIRECTED_RIGHT) == 0) && + ker.compare_xy_2_object()(ps, pt) == LARGER))) { // We are allowed to change the direction only in case of a segment. - CGAL_assertion (this->m_orient == COLLINEAR); - arc.m_info = (this->m_info ^ IS_DIRECTED_RIGHT); + CGAL_assertion(this->m_orient == COLLINEAR); + arc.m_old_info = (this->m_old_info ^ IS_DIRECTED_RIGHT); + arc.m_new_info.flip(IS_DIRECTED_RIGHT_); } // Make a copy of the current arc and assign its endpoints. @@ -1033,32 +1048,30 @@ public: if (ker.equal_2_object() (right(), arc.left())) { // Extend the arc to the right. - if ((this->m_info & IS_DIRECTED_RIGHT) != 0) this->m_target = arc.right(); + if ((this->m_old_info & IS_DIRECTED_RIGHT) != 0) this->m_target = arc.right(); else this->m_source = arc.right(); } else { - CGAL_precondition (ker.equal_2_object() (left(), arc.right())); + CGAL_precondition(ker.equal_2_object() (left(), arc.right())); // Extend the arc to the left. - if ((this->m_info & IS_DIRECTED_RIGHT) != 0) + if ((this->m_old_info & IS_DIRECTED_RIGHT) != 0) this->m_source = arc.left(); else this->m_target = arc.left(); } } - bool is_upper() const { return ((this->m_info & FACING_UP) != 0); } + bool is_upper() const { return ((this->m_old_info & FACING_UP) != 0); } - bool is_lower() const { return ((this->m_info & FACING_DOWN) != 0); } + bool is_lower() const { return ((this->m_old_info & FACING_DOWN) != 0); } //@} private: - /// \name Auxiliary (private) functions. //@{ - /*! - * Set the properties of the x-monotone conic arc (for the usage of the + /*! Set the properties of the x-monotone conic arc (for the usage of the * constructors). */ void set() { @@ -1076,8 +1089,10 @@ private: this->m_source.set_generating_conic(m_id); this->m_target.set_generating_conic(m_id); - // Clear the m_info bits. - this->m_info = Conic_arc_2::IS_VALID; + // Clear the m_old_info bits. + this->m_old_info = IS_VALID; + this->m_new_info.set(IS_VALID_); + this->m_new_info.reset(IS_FULL_CONIC_); // Check if the arc is directed right (the target is lexicographically // greater than the source point), or to the left. @@ -1087,21 +1102,27 @@ private: CGAL_assertion (dir_res != EQUAL); - if (dir_res == SMALLER) this->m_info = (this->m_info | IS_DIRECTED_RIGHT); + if (dir_res == SMALLER) { + this->m_old_info = (this->m_old_info | IS_DIRECTED_RIGHT); + this->m_new_info.set(IS_DIRECTED_RIGHT_); + } // Compute the degree of the underlying conic. if ((CGAL::sign(this->m_r) != ZERO) || (CGAL::sign(this->m_s) != ZERO) || (CGAL::sign(this->m_t) != ZERO)) { - this->m_info = (this->m_info | DEGREE_2); + this->m_old_info = (this->m_old_info | DEGREE_2); + this->m_new_info.set(DEGREE_2_); if (this->m_orient == COLLINEAR) { - this->m_info = (this->m_info | IS_SPECIAL_SEGMENT); + this->m_old_info = (this->m_old_info | IS_SPECIAL_SEGMENT); + this->m_new_info.set(IS_SPECIAL_SEGMENT_); if (ker.compare_x_2_object()(this->m_source, this->m_target) == EQUAL) { // The arc is a vertical segment: - this->m_info = (this->m_info | IS_VERTICAL_SEGMENT); + this->m_old_info = (this->m_old_info | IS_VERTICAL_SEGMENT); + this->m_new_info.set(IS_VERTICAL_SEGMENT_); } return; @@ -1111,13 +1132,15 @@ private: CGAL_assertion(CGAL::sign(this->m_u) != ZERO || CGAL::sign(this->m_v) != ZERO); - if (CGAL::sign (this->m_v) == ZERO) { + if (CGAL::sign(this->m_v) == ZERO) { // The supporting curve is of the form: _u*x + _w = 0 - this->m_info = (this->m_info | IS_VERTICAL_SEGMENT); + this->m_old_info = (this->m_old_info | IS_VERTICAL_SEGMENT); + this->m_new_info.set(IS_VERTICAL_SEGMENT_); } - this->m_info = (this->m_info | DEGREE_1); + this->m_old_info = (this->m_old_info | DEGREE_1); + this->m_new_info.set(DEGREE_1_); return; } @@ -1137,20 +1160,22 @@ private: // Check which solution lies on the x-monotone arc. Point_2 p_arc_mid(p_mid.x(), ys[0]); - if (is_strictly_between_endpoints (p_arc_mid)) { + if (is_strictly_between_endpoints(p_arc_mid)) { // Mark that we should use the -sqrt(disc) root for points on this // x-monotone arc. - this->m_info = (this->m_info & ~PLUS_SQRT_DISC_ROOT); + this->m_old_info = (this->m_old_info & ~PLUS_SQRT_DISC_ROOT); + this->m_new_info.reset(PLUS_SQRT_DISC_ROOT_); } else { CGAL_assertion (n_ys == 2); p_arc_mid = Point_2 (p_mid.x(), ys[1]); - CGAL_assertion (is_strictly_between_endpoints (p_arc_mid)); + CGAL_assertion(is_strictly_between_endpoints(p_arc_mid)); // Mark that we should use the +sqrt(disc) root for points on this // x-monotone arc. - this->m_info = (this->m_info | PLUS_SQRT_DISC_ROOT); + this->m_old_info = (this->m_old_info | PLUS_SQRT_DISC_ROOT); + this->m_new_info.set(PLUS_SQRT_DISC_ROOT_); } // Check whether the conic is facing up or facing down: @@ -1162,11 +1187,13 @@ private: if (res == LARGER) { // The arc is above the connecting segment, so it is facing upwards. - this->m_info = (this->m_info | FACING_UP); + this->m_old_info = (this->m_old_info | FACING_UP); + this->m_new_info.set(FACING_UP_); } else if (res == SMALLER) { // The arc is below the connecting segment, so it is facing downwards. - this->m_info = (this->m_info | FACING_DOWN); + this->m_old_info = (this->m_old_info | FACING_DOWN); + this->m_new_info.set(FACING_DOWN_); } } @@ -1174,7 +1201,7 @@ private: * (and has no undelying integer conic coefficients). */ bool is_special_segment() const - { return ((this->m_info & IS_SPECIAL_SEGMENT) != 0); } + { return this->m_new_info.test(IS_SPECIAL_SEGMENT_); } /*! Check whether the given point lies on the supporting conic of the arc. * \param px The x-coordinate of query point. @@ -1259,7 +1286,7 @@ private: CGAL::compare(this->m_w * factor2, arc.m_w * factor1) == EQUAL); } - /*! Get the i'th order derivative by x of the conic at the point p=(x,y). + /*! Obtain the i'th order derivative by x of the conic at the point p=(x,y). * \param p The point where we derive. * \param i The order of the derivatives (either 1, 2 or 3). * \param slope_numer The numerator of the slope. @@ -1368,8 +1395,7 @@ private: CGAL_error(); } - /*! - * Get the i'th order derivative by y of the conic at the point p=(x,y). + /*! Obtain the i'th order derivative by y of the conic at the point p=(x,y). * \param p The point where we derive. * \param i The order of the derivatives (either 1, 2 or 3). * \param slope_numer The numerator of the slope. @@ -1485,13 +1511,14 @@ private: * \return Whether we found an overlap. */ bool compute_overlap(const Self& arc, Self& overlap) const { + std::cout << "compute_overlap()\n"; // Check if the two arcs are identical. if (equals(arc)) { overlap = arc; return true; } - if (is_strictly_between_endpoints (arc.left())) { + if (is_strictly_between_endpoints(arc.left())) { if (is_strictly_between_endpoints(arc.right())) { // Case 1 - *this: +-----------> // arc: +=====> @@ -1503,7 +1530,7 @@ private: // arc: +=====> overlap = *this; - if ((overlap.m_info & IS_DIRECTED_RIGHT) != 0) + if (overlap.m_new_info.test(IS_DIRECTED_RIGHT_)) overlap.m_source = arc.left(); else overlap.m_target = arc.left(); @@ -1516,7 +1543,7 @@ private: // arc: +=====> overlap = *this; - if ((overlap.m_info & IS_DIRECTED_RIGHT) != 0) + if (overlap.m_new_info.test(IS_DIRECTED_RIGHT_)) overlap.m_target = arc.right(); else overlap.m_source = arc.right(); @@ -1550,8 +1577,8 @@ private: return; } - const int deg1 = ((this->m_info & DEGREE_MASK) == DEGREE_1) ? 1 : 2; - const int deg2 = ((arc.m_info & DEGREE_MASK) == DEGREE_1) ? 1 : 2; + const int deg1 = ((this->m_old_info & DEGREE_MASK) == DEGREE_1) ? 1 : 2; + const int deg2 = ((arc.m_old_info & DEGREE_MASK) == DEGREE_1) ? 1 : 2; Nt_traits nt_traits; Algebraic xs[4]; int n_xs = 0; @@ -1779,10 +1806,9 @@ private: }; -/*! - * Exporter for x-monotone conic arcs. +/*! Exporter for x-monotone conic arcs. */ -template +template std::ostream& operator<<(std::ostream& os, const _Conic_x_monotone_arc_2& arc) { From 5021b828e97025513d29dd316beb271b8c569cb3 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Thu, 19 May 2022 17:22:07 +0300 Subject: [PATCH 006/105] updated --- .../Conic_x_monotone_arc_2.h | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h index 90d9615c958..db310509ee2 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h @@ -557,8 +557,8 @@ public: Comparison_result compare_to_right(const Self& arc, const Conic_point_2& p) const { - CGAL_precondition((this->m_old_info & IS_VERTICAL_SEGMENT) == 0 && - (arc.m_old_info & IS_VERTICAL_SEGMENT) == 0); + CGAL_precondition(! this->m_new_info.test(IS_VERTICAL_SEGMENT_) && + ! arc.m_new_info.test(IS_VERTICAL_SEGMENT_)); // In case one arc is facing upwards and another facing downwards, it is // clear that the one facing upward is above the one facing downwards. @@ -733,31 +733,29 @@ public: // \todo Handle higher-order derivatives: CGAL_assertion(slope_res != EQUAL); - return (slope_res); + return slope_res; } else if (! is_vertical_slope2) { // The first arc has a vertical slope at p: check whether it is // facing upwards or downwards and decide accordingly. CGAL_assertion((this->m_old_info & FACING_MASK) != 0); - if ((this->m_old_info & FACING_UP) != 0) return LARGER; - return SMALLER; + return (this->m_new_info.test(FACING_UP_)) ? LARGER : SMALLER; } else if (! is_vertical_slope1) { // The second arc has a vertical slope at p_int: check whether it is // facing upwards or downwards and decide accordingly. CGAL_assertion((arc.m_old_info & FACING_MASK) != 0); - if ((arc.m_old_info & FACING_UP) != 0) return SMALLER; - return LARGER; + return (arc.m_new_info.test(FACING_UP_)) ? SMALLER : LARGER; } // The two arcs have vertical slopes at p_int: // First check whether one is facing up and one down. In this case the // comparison result is trivial. - if ((this->m_old_info & FACING_UP) != 0 && (arc.m_old_info & FACING_DOWN) != 0) + if (this->m_new_info.test(FACING_UP_) && arc.m_new_info.test(FACING_DOWN_)) return LARGER; - else if ((this->m_old_info & FACING_DOWN) != 0 && (arc.m_old_info & FACING_UP) != 0) + else if (this->m_new_info.test(FACING_DOWN_) && arc.m_new_info.test(FACING_UP_)) return SMALLER; // Compute the second-order derivative by y and act according to it. @@ -1048,23 +1046,23 @@ public: if (ker.equal_2_object() (right(), arc.left())) { // Extend the arc to the right. - if ((this->m_old_info & IS_DIRECTED_RIGHT) != 0) this->m_target = arc.right(); + if (this->m_new_info.test(IS_DIRECTED_RIGHT_)) this->m_target = arc.right(); else this->m_source = arc.right(); } else { CGAL_precondition(ker.equal_2_object() (left(), arc.right())); // Extend the arc to the left. - if ((this->m_old_info & IS_DIRECTED_RIGHT) != 0) + if (this->m_new_info.test(IS_DIRECTED_RIGHT_)) this->m_source = arc.left(); else this->m_target = arc.left(); } } - bool is_upper() const { return ((this->m_old_info & FACING_UP) != 0); } + bool is_upper() const { return this->m_new_info.test(FACING_UP_); } - bool is_lower() const { return ((this->m_old_info & FACING_DOWN) != 0); } + bool is_lower() const { return this->m_new_info.test(FACING_DOWN_); } //@} private: From 5329c37bc7f957b17a564c224d4d88150f040d30 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Thu, 19 May 2022 17:43:08 +0300 Subject: [PATCH 007/105] Updated --- .../Conic_x_monotone_arc_2.h | 37 +++++++++---------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h index db310509ee2..70362bae6a8 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h @@ -614,29 +614,27 @@ public: return slope_res; } - else if ( !is_vertical_slope2) { + else if (! is_vertical_slope2) { // The first arc has a vertical slope at p: check whether it is // facing upwards or downwards and decide accordingly. CGAL_assertion ((this->m_old_info & FACING_MASK) != 0); - if ((this->m_old_info & FACING_UP) != 0) return LARGER; - return SMALLER; + return (this->m_new_info.test(FACING_UP_)) ? LARGER : SMALLER; } else if (! is_vertical_slope1) { // The second arc has a vertical slope at p_int: check whether it is // facing upwards or downwards and decide accordingly. CGAL_assertion ((arc.m_old_info & FACING_MASK) != 0); - if ((arc.m_old_info & FACING_UP) != 0) return SMALLER; - return LARGER; + return (arc.m_new_info.test(FACING_UP_)) ? SMALLER : LARGER; } // The two arcs have vertical slopes at p_int: // First check whether one is facing up and one down. In this case the // comparison result is trivial. - if ((this->m_old_info & FACING_UP) != 0 && (arc.m_old_info & FACING_DOWN) != 0) - return (LARGER); - else if ((this->m_old_info & FACING_DOWN) != 0 && (arc.m_old_info & FACING_UP) != 0) + if (this->m_new_info.test(FACING_UP_) && arc.m_new_info.test(FACING_DOWN_)) + return LARGER; + else if (this->m_new_info.test(FACING_DOWN_) && arc.m_new_info.test(FACING_UP_)) return SMALLER; // Compute the second-order derivative by y and act according to it. @@ -659,7 +657,7 @@ public: // \todo Handle higher-order derivatives: CGAL_assertion(slope_res != EQUAL); - if ((this->m_old_info & FACING_UP) != 0 && (arc.m_old_info & FACING_UP) != 0) { + if (this->m_new_info.test(FACING_UP_) && arc.m_new_info.test(FACING_UP_)) { // Both are facing up. return ((slope_res == LARGER) ? SMALLER : LARGER); } @@ -682,10 +680,9 @@ public: // In case one arc is facing upwards and another facing downwards, it is // clear that the one facing upward is above the one facing downwards. if (has_same_supporting_conic (arc)) { - if ((this->m_old_info & FACING_UP) != 0 && (arc.m_old_info & FACING_DOWN) != 0) + if (this->m_new_info.test(FACING_UP_) && arc.m_new_info.test(FACING_DOWN_)) return LARGER; - else if ((this->m_old_info & FACING_DOWN) != 0 && (arc.m_old_info & FACING_UP) != - 0) + else if (this->m_new_info.test(FACING_DOWN_) && arc.m_new_info.test(FACING_UP_)) return SMALLER; // In this case the two arcs overlap. @@ -778,10 +775,10 @@ public: // \todo Handle higher-order derivatives: CGAL_assertion(slope_res != EQUAL); - if ((this->m_old_info & FACING_UP) != 0 && (arc.m_old_info & FACING_UP) != 0) { - // Both are facing up. + // Check whether both are facing up. + if (this->m_new_info.test(FACING_UP_) && arc.m_new_info.test(FACING_UP_)) return ((slope_res == LARGER) ? SMALLER : LARGER); - } + // Both are facing down. return slope_res; } @@ -896,7 +893,7 @@ public: c2 = *this; // Assign the endpoints of the arc. - if ((this->m_old_info & IS_DIRECTED_RIGHT) != 0) { + if (this->m_new_info.test(IS_DIRECTED_RIGHT_)) { // The arc is directed from left to right, so p becomes c1's target // and c2's source. c1.m_target = p; @@ -957,10 +954,10 @@ public: Self arc = *this; Alg_kernel ker; - if (! ((((this->m_old_info & IS_DIRECTED_RIGHT) != 0) && - ker.compare_xy_2_object()(ps, pt) == SMALLER) || - (((this->m_old_info & IS_DIRECTED_RIGHT) == 0) && - ker.compare_xy_2_object()(ps, pt) == LARGER))) + if (! ((this->m_new_info.test(IS_DIRECTED_RIGHT_) && + (ker.compare_xy_2_object()(ps, pt) == SMALLER)) || + (this->m_new_info.test(IS_DIRECTED_RIGHT_) && + (ker.compare_xy_2_object()(ps, pt) == LARGER)))) { // We are allowed to change the direction only in case of a segment. CGAL_assertion(this->m_orient == COLLINEAR); From 9353296bcb7bcbc068b3aebae0faf028f8e565c2 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Thu, 19 May 2022 23:36:08 +0300 Subject: [PATCH 008/105] Cleaned up --- .../CGAL/Arr_geometry_traits/Conic_point_2.h | 97 ++++++------------- 1 file changed, 32 insertions(+), 65 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_point_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_point_2.h index 737610bc86d..344c1bf6395 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_point_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_point_2.h @@ -29,11 +29,9 @@ namespace CGAL { * \class A class that stores additional information with the point's * coordinates, namely the conic IDs of the generating curves. */ -template -class _Conic_point_2 : public Alg_kernel_::Point_2 -{ +template +class _Conic_point_2 : public Alg_kernel_::Point_2 { public: - typedef Alg_kernel_ Alg_kernel; typedef typename Alg_kernel::Point_2 Base; typedef _Conic_point_2 Self; @@ -43,89 +41,67 @@ public: /*! \class * Representation of an ID of a conic arc. */ - class Conic_id - { + class Conic_id { private: - - unsigned int index; // The index of the conic arc. + unsigned int index; // the index of the conic arc public: - /*! Default constructor. */ - Conic_id () : - index (0) - {} + Conic_id() : index(0) {} /*! Constructor. */ - Conic_id (unsigned int ind) : + Conic_id(unsigned int ind) : index (ind) - { - CGAL_precondition (ind != 0); - } + { CGAL_precondition(ind != 0); } /*! Check if the ID is valid. */ - bool is_valid () const - { - return (index != 0); - } + bool is_valid() const { return (index != 0); } /*! Equality operator. */ - bool operator== (const Conic_id& id) const - { - return (index == id.index); - } + bool operator==(const Conic_id& id) const + { return (index == id.index); } /*! Inequality operator. */ - bool operator!= (const Conic_id& id) const - { - return (index != id.index); - } + bool operator!=(const Conic_id& id) const + { return (index != id.index); } /*! Less-than operator. */ bool operator< (const Conic_id& id) const - { - return (index < id.index); - } + { return (index < id.index); } /*! Greater-than operator. */ - bool operator> (const Conic_id& id) const - { - return (index > id.index); - } + bool operator>(const Conic_id& id) const + { return (index > id.index); } }; private: - typedef std::list Ids_container; typedef typename std::list::const_iterator Ids_iterator; - Ids_container conic_ids; // The IDs of the generating conics. + Ids_container conic_ids; // The IDs of the generating conics. public: - /// \name Constructors. //@{ /*! Default constructors. */ - _Conic_point_2 () : - Base() - {} + _Conic_point_2() : Base() {} /*! Constrcutor from the base class. */ - _Conic_point_2 (const Base& p) : - Base (p) + _Conic_point_2(const Base& p) : + Base(p) {} /*! Constructor with homegeneous coordinates. */ - _Conic_point_2 (const Algebraic& hx, - const Algebraic& hy, - const Algebraic& hz) : + _Conic_point_2(const Algebraic& hx, + const Algebraic& hy, + const Algebraic& hz) : Base (hx, hy, hz) {} /*! Constructor with Cartesian coordinates. */ - _Conic_point_2 (const Algebraic& x, const Algebraic& y) : - Base (x, y) + _Conic_point_2(const Algebraic& x, const Algebraic& y) : + Base(x, y) {} //@} @@ -133,29 +109,20 @@ private: //@{ /*! Add a generating conic ID. */ - void set_generating_conic (const Conic_id& id) - { - if (id.is_valid()) - conic_ids.push_back (id); - - return; - } + void set_generating_conic(const Conic_id& id) + { if (id.is_valid()) conic_ids.push_back(id); } /*! Check if the given conic generates the point. */ - bool is_generating_conic (const Conic_id& id) const - { - if (! id.is_valid()) - return (false); + bool is_generating_conic(const Conic_id& id) const { + if (! id.is_valid()) return false; - Ids_iterator it; + Ids_iterator it; - for (it = conic_ids.begin(); it != conic_ids.end(); ++it) - { - if (*it == id) - return (true); + for (it = conic_ids.begin(); it != conic_ids.end(); ++it) { + if (*it == id) return true; } - return (false); + return false; } //@} From 2429950bdd7d06d96f5a68cd488360f11f7b6b98 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Thu, 19 May 2022 23:36:29 +0300 Subject: [PATCH 009/105] Finished handling flags --- .../CGAL/Arr_geometry_traits/Conic_arc_2.h | 119 ++++----- .../Conic_x_monotone_arc_2.h | 241 +++++++----------- 2 files changed, 152 insertions(+), 208 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h index 4f8a7900ed2..7a68539d074 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h @@ -19,7 +19,6 @@ * Header file for the _Conic_arc_2 class. */ -#include #include #include @@ -74,16 +73,12 @@ protected: // Bit masks for the m_info field. enum { - IS_VALID = 1, - IS_FULL_CONIC = 2, - - IS_VALID_ = 0, - IS_FULL_CONIC_, + IS_VALID = 0, + IS_FULL_CONIC, LAST_INFO, }; - int m_old_info; // does the arc represent a full conic curve. - std::bitset<16> m_new_info; // does the arc represent a full conic curve. + int m_info; // does the arc represent a full conic curve. Conic_point_2 m_source; // the source of the arc (if not a full curve). Conic_point_2 m_target; // the target of the arc (if not a full curve). @@ -105,6 +100,27 @@ protected: Extra_data* m_extra_data; // The extra data stored with the arc // (may be nullptr). + /// \name Flag manipulation functions. + //@{ + template + constexpr size_t flag_mask(const T flag) const { return 0x1 << flag; } + + void reset_flags() { m_info = 0; } + + template + void set_flag(const T flag) { m_info |= flag_mask(flag); } + + template + void reset_flag(const T flag) { m_info &= ~flag_mask(flag); } + + template + void flip_flag(const T flag) { m_info ^= flag_mask(flag);} + + template + bool test_flag(const T flag) const + { return (m_info & flag_mask(flag)); } + //@} + public: /// \name Construction and destruction functions. //@{ @@ -115,8 +131,7 @@ public: _Conic_arc_2() : m_r(0), m_s(0), m_t(0), m_u(0), m_v(0), m_w(0), m_orient(COLLINEAR), - m_old_info(0), - m_new_info(0), + m_info(0), m_extra_data(nullptr) {} @@ -127,8 +142,7 @@ public: m_r(arc.m_r), m_s(arc.m_s), m_t(arc.m_t), m_u(arc.m_u), m_v(arc.m_v), m_w(arc.m_w), m_orient(arc.m_orient), - m_old_info(arc.m_old_info), - m_new_info(arc.m_new_info), + m_info(arc.m_info), m_source(arc.m_source), m_target(arc.m_target) { @@ -142,8 +156,7 @@ public: */ _Conic_arc_2(const Rational& r, const Rational& s, const Rational& t, const Rational& u, const Rational& v, const Rational& w) : - m_old_info(0), - m_new_info(0), + m_info(0), m_extra_data(nullptr) { // Make sure the given curve is an ellipse (4rs - t^2 should be positive). @@ -175,8 +188,7 @@ public: const Orientation& orient, const Point_2& source, const Point_2& target) : m_orient(orient), - m_old_info(0), - m_new_info(0), + m_info(0), m_source(source), m_target(target), m_extra_data(nullptr) @@ -203,8 +215,7 @@ public: */ _Conic_arc_2(const Point_2& source, const Point_2& target) : m_orient(COLLINEAR), - m_old_info(static_cast(IS_VALID)), - m_new_info(0), + m_info(flag_mask(IS_VALID)), m_source(source), m_target(target), m_extra_data(nullptr) @@ -212,7 +223,7 @@ public: CGAL_precondition(Alg_kernel().compare_xy_2_object()(m_source, m_target) != EQUAL); - m_new_info.set(IS_VALID_); + set_flag(IS_VALID); // Compose the equation of the underlying line. const Algebraic x1 = source.x(); @@ -235,8 +246,7 @@ public: */ _Conic_arc_2(const Rat_segment_2& seg) : m_orient(COLLINEAR), - m_old_info(0), - m_new_info(0), + m_info(0), m_extra_data (nullptr) { // Set the source and target. @@ -291,8 +301,7 @@ public: */ _Conic_arc_2(const Rat_circle_2& circ) : m_orient(CLOCKWISE), - m_old_info(0), - m_new_info(0), + m_info(0), m_extra_data(nullptr) { // Get the circle properties. @@ -335,8 +344,7 @@ public: const Orientation& orient, const Point_2& source, const Point_2& target) : m_orient(orient), - m_old_info(0), - m_new_info(0), + m_info(0), m_source(source), m_target(target), m_extra_data(nullptr) @@ -397,8 +405,7 @@ public: */ _Conic_arc_2(const Rat_point_2& p1, const Rat_point_2& p2, const Rat_point_2& p3): - m_old_info(0), - m_new_info(0), + m_info(0), m_extra_data(nullptr) { // Set the source and target. @@ -440,8 +447,7 @@ public: const bool points_collinear = (CGAL::sign(D) == ZERO); if (points_collinear) { - m_old_info = 0; // inavlid arc. - m_new_info.reset(); // inavlid arc + reset_flags(); // inavlid arc return; } @@ -482,8 +488,7 @@ public: _Conic_arc_2(const Rat_point_2& p1, const Rat_point_2& p2, const Rat_point_2& p3, const Rat_point_2& p4, const Rat_point_2& p5) : - m_old_info(0), - m_new_info(0), + m_info(0), m_extra_data(nullptr) { // Make sure that no three points are collinear. @@ -502,8 +507,7 @@ public: orient_f(p3, p4, p5) == COLLINEAR); if (point_collinear) { - m_old_info = 0; // Inavlid arc. - m_new_info.reset(); // inavlid arc + reset_flags(); // inavlid arc return; } @@ -561,8 +565,7 @@ public: ! is_strictly_between_endpoints(mp3) || ! is_strictly_between_endpoints(mp4)) { - m_old_info = 0; // Inalvid arc. - m_new_info.reset(); // inavlid arc + reset_flags(); // inavlid arc } } @@ -586,8 +589,7 @@ public: const Rational& r_2, const Rational& s_2, const Rational& t_2, const Rational& u_2, const Rational& v_2, const Rational& w_2): m_orient(orient), - m_old_info(0), - m_new_info(0), + m_info(0), m_extra_data(nullptr) { // Create the integer coefficients of the base conic. @@ -725,16 +727,14 @@ public: } if (! found) { - m_old_info = 0; // Invalid arc. - m_new_info.reset(); // inavlid arc + reset_flags(); // inavlid arc return; } } // Make sure that the source and the target are not the same. if (Alg_kernel().compare_xy_2_object()(m_source, m_target) == EQUAL) { - m_old_info = 0; // Invalid arc. - m_new_info.reset(); // inavlid arc + reset_flags(); // inavlid arc return; } @@ -764,8 +764,7 @@ public: m_w = arc.m_w; m_orient = arc.m_orient; - m_old_info = arc.m_old_info; - m_new_info = arc.m_new_info; + m_info = arc.m_info; m_source = arc.m_source; m_target = arc.m_target; @@ -782,7 +781,7 @@ public: /*! Check wheather the arc is valid. */ - bool is_valid() const { return m_new_info.test(IS_VALID_); } + bool is_valid() const { return test_flag(IS_VALID); } /*! Get the coefficients of the underlying conic. */ @@ -811,9 +810,7 @@ public: /*! Check whether the arc represents a full conic curve. */ - bool is_full_conic() const { - return m_new_info.test(IS_FULL_CONIC_); - } + bool is_full_conic() const { return test_flag(IS_FULL_CONIC); } /*! Get the arc's source. * \return The source point. @@ -1076,8 +1073,7 @@ private: * of x^2, y^2, xy, x, y and the free coefficient resp. */ void set(const Rational* rat_coeffs) { - m_old_info = IS_VALID; - m_new_info.set(IS_VALID_); + set_flag(IS_VALID); // Convert the coefficients vector to an equivalent vector of integer // coefficients. @@ -1113,8 +1109,7 @@ private: if (! is_on_supporting_conic(m_source) || ! is_on_supporting_conic(m_target)) { - m_old_info = 0; // Invalid arc. - m_new_info.reset(); // inavlid arc + reset_flags(); // inavlid arc return; } @@ -1154,8 +1149,7 @@ private: nt_traits.convert(m_v)) * p_mid.y() + nt_traits.convert(m_w)) != ZERO) { - m_old_info = 0; // Invalid arc. - m_new_info.reset(); // inavlid arc + reset_flags(); // inavlid arc return; } } @@ -1180,17 +1174,16 @@ private: bool finite_at_y = (points_at_y(p_mid, ps) > 0); if (! finite_at_x && ! finite_at_y) { - m_old_info = 0; // Invalid arc. - m_new_info.reset(); // inavlid arc + reset_flags(); // inavlid arc return; } } } } - // Mark that this arc valid and is not a full conic curve. - m_old_info = IS_VALID; - m_new_info.set(IS_VALID_); + + set_flag(IS_VALID); // mark that this arc valid + reset_flag(IS_FULL_CONIC); // mark that this arc is not a full conic } /*! Set the properties of a conic arc that is really a full curve @@ -1243,14 +1236,10 @@ private: // Mark that this arc is a full conic curve. if (is_ellipse) { - m_old_info = IS_VALID | IS_FULL_CONIC; - m_new_info.set(IS_VALID_); - m_new_info.set(IS_FULL_CONIC_); - } - else { - m_old_info = 0; - m_new_info.reset(); // inavlid arc + set_flag(IS_VALID); + set_flag(IS_FULL_CONIC); } + else reset_flags(); // inavlid arc } /*! Build the data for hyperbolic arc, contaning the characterization of the diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h index 70362bae6a8..5de01b56875 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h @@ -19,7 +19,6 @@ */ #include -#include #include #include @@ -35,7 +34,6 @@ namespace CGAL { template class _Conic_x_monotone_arc_2 : private ConicArc { public: - typedef ConicArc Conic_arc_2; typedef _Conic_x_monotone_arc_2 Self; @@ -57,9 +55,14 @@ public: using Conic_arc_2::conic_get_y_coordinates; using Conic_arc_2::IS_VALID; - using Conic_arc_2::IS_VALID_; using Conic_arc_2::IS_FULL_CONIC; - using Conic_arc_2::IS_FULL_CONIC_; + + using Conic_arc_2::flag_mask; + using Conic_arc_2::reset_flags; + using Conic_arc_2::set_flag; + using Conic_arc_2::reset_flag; + using Conic_arc_2::flip_flag; + using Conic_arc_2::test_flag; /*! \struct Less functor for Conic_pair. */ @@ -86,25 +89,17 @@ protected: // Bit masks for the m_info field (the two least significant bits are already // used by the base class). enum { - IS_VERTICAL_SEGMENT = 4, - IS_DIRECTED_RIGHT = 8, - DEGREE_1 = 16, - DEGREE_2 = 32, - DEGREE_MASK = 16 + 32, - PLUS_SQRT_DISC_ROOT = 64, - FACING_UP = 128, - FACING_DOWN = 256, - FACING_MASK = 128 + 256, - IS_SPECIAL_SEGMENT = 512, + IS_VERTICAL_SEGMENT = Conic_arc_2::LAST_INFO, + IS_DIRECTED_RIGHT, + DEGREE_1, + DEGREE_2, + PLUS_SQRT_DISC_ROOT, + FACING_UP, + FACING_DOWN, + IS_SPECIAL_SEGMENT, - IS_VERTICAL_SEGMENT_ = Conic_arc_2::LAST_INFO, - IS_DIRECTED_RIGHT_, - DEGREE_1_, - DEGREE_2_, - PLUS_SQRT_DISC_ROOT_, - FACING_UP_, - FACING_DOWN_, - IS_SPECIAL_SEGMENT_ + DEGREE_MASK = (0x1 << DEGREE_1) | (0x1 << DEGREE_2), + FACING_MASK = (0x1 << FACING_UP) | (0x1 << FACING_DOWN) }; Algebraic alg_r; // The coefficients of the supporting conic curve: @@ -194,26 +189,19 @@ public: _Conic_x_monotone_arc_2(const Point_2& source, const Point_2& target) : Base(source, target) { - this->m_old_info |= static_cast(DEGREE_1); - this->m_new_info.set(DEGREE_1); + set_flag(DEGREE_1); Alg_kernel ker; auto cmp_xy = ker.compare_xy_2_object(); Comparison_result dir_res = cmp_xy(this->m_source, this->m_target); - if (dir_res == SMALLER) { - this->m_old_info |= IS_DIRECTED_RIGHT; - this->m_new_info.set(IS_DIRECTED_RIGHT_); - } + if (dir_res == SMALLER) set_flag(IS_DIRECTED_RIGHT); // Check if the segment is vertical. - if (CGAL::sign(this->m_extra_data->b) == ZERO) { - this->m_old_info |= IS_VERTICAL_SEGMENT; - this->m_new_info.set(IS_VERTICAL_SEGMENT_); - } + if (CGAL::sign(this->m_extra_data->b) == ZERO) + set_flag(IS_VERTICAL_SEGMENT); // Mark that this is a special segment. - this->m_old_info |= IS_SPECIAL_SEGMENT; - this->m_new_info.set(IS_SPECIAL_SEGMENT_); + set_flag(IS_SPECIAL_SEGMENT); } /*! Construct a special segment of a given line connecting to given @@ -235,12 +223,11 @@ public: CGAL_precondition (CGAL::sign(a * target.x() + b * target.y() + c) == CGAL::ZERO); - // Set the basic properties and clear the m_old_info bits. + // Set the basic properties and clear the m_info bits. this->m_source = source; this->m_target = target; this->m_orient = COLLINEAR; - this->m_old_info = 0; - this->m_new_info.reset(); // inavlid arc + reset_flags(); // inavlid arc // Check if the arc is directed right (the target is lexicographically // greater than the source point), or to the left. @@ -248,31 +235,23 @@ public: Comparison_result res = ker.compare_x_2_object()(this->m_source, this->m_target); - this->m_old_info = - (static_cast(IS_VALID) | static_cast(DEGREE_1)); - this->m_new_info.set(IS_VALID_); - this->m_new_info.set(DEGREE_1_); + set_flag(IS_VALID); + set_flag(DEGREE_1); if (res == EQUAL) { // Mark that the segment is vertical. - this->m_old_info = (this->m_old_info | IS_VERTICAL_SEGMENT); - this->m_new_info.set(IS_VERTICAL_SEGMENT_); + set_flag(IS_VERTICAL_SEGMENT); // Compare the endpoints lexicographically. res = ker.compare_y_2_object()(this->m_source, this->m_target); CGAL_precondition (res != EQUAL); if (res == EQUAL) { - // Invalid arc: - this->m_old_info = 0; - this->m_new_info.reset(); // inavlid arc + reset_flags(); // inavlid arc return; } } - if (res == SMALLER) { - this->m_old_info = (this->m_old_info | IS_DIRECTED_RIGHT); - this->m_new_info.set(IS_DIRECTED_RIGHT_); - } + if (res == SMALLER) set_flag(IS_DIRECTED_RIGHT); // Store the coefficients of the line. this->m_extra_data = new typename Base::Extra_data; @@ -282,8 +261,7 @@ public: this->m_extra_data->side = ZERO; // Mark that this is a special segment. - this->m_old_info = (this->m_old_info | IS_SPECIAL_SEGMENT); - this->m_new_info.set(IS_SPECIAL_SEGMENT_); + set_flag(IS_SPECIAL_SEGMENT); } /*! Assignment operator. @@ -341,21 +319,21 @@ public: /*! Obtain the left endpoint of the arc. */ const Conic_point_2& left() const { - if (this->m_new_info.test(IS_DIRECTED_RIGHT_)) return this->m_source; + if (test_flag(IS_DIRECTED_RIGHT)) return this->m_source; else return this->m_target; } /*! Obtain the right endpoint of the arc. */ const Conic_point_2& right() const { - if (this->m_new_info.test(IS_DIRECTED_RIGHT_)) return this->m_target; + if (test_flag(IS_DIRECTED_RIGHT)) return this->m_target; else return this->m_source; } /*! Return true iff the conic arc is directed right iexicographically. */ bool is_directed_right() const - { return this->m_new_info.test(IS_DIRECTED_RIGHT_); } + { return test_flag(IS_DIRECTED_RIGHT); } /*! Obtain a bounding box for the conic arc. * \return The bounding box. @@ -369,7 +347,7 @@ public: /*! Check if the conic arc is a vertical segment. */ bool is_vertical() const - { return this->m_new_info.test(IS_VERTICAL_SEGMENT_); } + { return test_flag(IS_VERTICAL_SEGMENT); } /*! Check whether the given point lies on the arc. * \param p The qury point. @@ -410,7 +388,7 @@ public: */ Point_2 point_at_x(const Point_2& p) const { // Make sure that p is in the x-range of the arc. - CGAL_precondition(! this->m_new_info.test(IS_VERTICAL_SEGMENT_)); + CGAL_precondition(! test_flag(IS_VERTICAL_SEGMENT)); CGAL_precondition_code(Alg_kernel ker;); @@ -433,7 +411,7 @@ public: Nt_traits nt_traits; Algebraic y; - if ((this->m_old_info & DEGREE_MASK) == DEGREE_1) { + if ((this->m_info & DEGREE_MASK) == flag_mask(DEGREE_1)) { // In case of a linear curve, the y-coordinate is a simple linear // expression of x(p) (note that v is not 0 as the arc is not vertical): // y = -(u*x(p) + w) / v @@ -448,7 +426,7 @@ public: this->m_extra_data->c) / this->m_extra_data->b; } else { - CGAL_assertion((this->m_old_info & DEGREE_MASK) == DEGREE_2); + CGAL_assertion((this->m_info & DEGREE_MASK) == flag_mask(DEGREE_2)); // In this case the y-coordinate is one of solutions to the quadratic // equation: @@ -471,12 +449,9 @@ public: // We take either the root involving -sqrt(disc) or +sqrt(disc) // based on the information flags. - if (this->m_new_info.test(PLUS_SQRT_DISC_ROOT_)) { - y = (nt_traits.sqrt (disc) - B) / (2*A); - } - else { - y = -(B + nt_traits.sqrt (disc)) / (2*A); - } + y = (test_flag(PLUS_SQRT_DISC_ROOT)) ? + (nt_traits.sqrt (disc) - B) / (2*A) : + -(B + nt_traits.sqrt (disc)) / (2*A); } } @@ -538,7 +513,7 @@ public: // We take either the root involving -sqrt(disc) or +sqrt(disc) // based on the information flags. - y = ((this->m_old_info & PLUS_SQRT_DISC_ROOT) != 0) ? + y = (test_flag(PLUS_SQRT_DISC_ROOT)) ? (std::sqrt(disc) - B) / (2*A) : -(B + std::sqrt (disc)) / (2*A); } *oi++ = std::pair(x, y); @@ -557,19 +532,19 @@ public: Comparison_result compare_to_right(const Self& arc, const Conic_point_2& p) const { - CGAL_precondition(! this->m_new_info.test(IS_VERTICAL_SEGMENT_) && - ! arc.m_new_info.test(IS_VERTICAL_SEGMENT_)); + CGAL_precondition(! test_flag(IS_VERTICAL_SEGMENT) && + ! arc.test_flag(IS_VERTICAL_SEGMENT)); // In case one arc is facing upwards and another facing downwards, it is // clear that the one facing upward is above the one facing downwards. - if (has_same_supporting_conic (arc)) { - if (this->m_new_info.test(FACING_UP_) && arc.m_new_info.test(FACING_DOWN_)) + if (has_same_supporting_conic(arc)) { + if (test_flag(FACING_UP) && arc.test_flag(FACING_DOWN)) return LARGER; - else if (this->m_new_info.test(FACING_DOWN_) && arc.m_new_info.test(FACING_UP_)) + else if (test_flag(FACING_DOWN) && arc.test_flag(FACING_UP)) return SMALLER; // In this case the two arcs overlap. - CGAL_assertion((this->m_old_info & FACING_MASK) == (arc.m_old_info & FACING_MASK)); + CGAL_assertion((this->m_info & FACING_MASK) == (arc.m_info & FACING_MASK)); return EQUAL; } @@ -617,24 +592,24 @@ public: else if (! is_vertical_slope2) { // The first arc has a vertical slope at p: check whether it is // facing upwards or downwards and decide accordingly. - CGAL_assertion ((this->m_old_info & FACING_MASK) != 0); + CGAL_assertion((this->m_info & FACING_MASK) != 0); - return (this->m_new_info.test(FACING_UP_)) ? LARGER : SMALLER; + return (test_flag(FACING_UP)) ? LARGER : SMALLER; } else if (! is_vertical_slope1) { // The second arc has a vertical slope at p_int: check whether it is // facing upwards or downwards and decide accordingly. - CGAL_assertion ((arc.m_old_info & FACING_MASK) != 0); + CGAL_assertion((arc.m_info & FACING_MASK) != 0); - return (arc.m_new_info.test(FACING_UP_)) ? SMALLER : LARGER; + return (arc.test_flag(FACING_UP)) ? SMALLER : LARGER; } // The two arcs have vertical slopes at p_int: // First check whether one is facing up and one down. In this case the // comparison result is trivial. - if (this->m_new_info.test(FACING_UP_) && arc.m_new_info.test(FACING_DOWN_)) + if (test_flag(FACING_UP) && arc.test_flag(FACING_DOWN)) return LARGER; - else if (this->m_new_info.test(FACING_DOWN_) && arc.m_new_info.test(FACING_UP_)) + else if (test_flag(FACING_DOWN) && arc.test_flag(FACING_UP)) return SMALLER; // Compute the second-order derivative by y and act according to it. @@ -657,7 +632,7 @@ public: // \todo Handle higher-order derivatives: CGAL_assertion(slope_res != EQUAL); - if (this->m_new_info.test(FACING_UP_) && arc.m_new_info.test(FACING_UP_)) { + if (test_flag(FACING_UP) && arc.test_flag(FACING_UP)) { // Both are facing up. return ((slope_res == LARGER) ? SMALLER : LARGER); } @@ -674,19 +649,19 @@ public: Comparison_result compare_to_left(const Self& arc, const Conic_point_2& p) const { - CGAL_precondition((this->m_old_info & IS_VERTICAL_SEGMENT) == 0 && - (arc.m_old_info & IS_VERTICAL_SEGMENT) == 0); + CGAL_precondition(! test_flag(IS_VERTICAL_SEGMENT) && + ! arc.test_flag(IS_VERTICAL_SEGMENT)); // In case one arc is facing upwards and another facing downwards, it is // clear that the one facing upward is above the one facing downwards. if (has_same_supporting_conic (arc)) { - if (this->m_new_info.test(FACING_UP_) && arc.m_new_info.test(FACING_DOWN_)) + if (test_flag(FACING_UP) && arc.test_flag(FACING_DOWN)) return LARGER; - else if (this->m_new_info.test(FACING_DOWN_) && arc.m_new_info.test(FACING_UP_)) + else if (test_flag(FACING_DOWN) && arc.test_flag(FACING_UP)) return SMALLER; // In this case the two arcs overlap. - CGAL_assertion((this->m_old_info & FACING_MASK) == (arc.m_old_info & FACING_MASK)); + CGAL_assertion((this->m_info & FACING_MASK) == (arc.m_info & FACING_MASK)); return EQUAL; } @@ -735,24 +710,24 @@ public: else if (! is_vertical_slope2) { // The first arc has a vertical slope at p: check whether it is // facing upwards or downwards and decide accordingly. - CGAL_assertion((this->m_old_info & FACING_MASK) != 0); + CGAL_assertion((this->m_info & FACING_MASK) != 0); - return (this->m_new_info.test(FACING_UP_)) ? LARGER : SMALLER; + return (test_flag(FACING_UP)) ? LARGER : SMALLER; } else if (! is_vertical_slope1) { // The second arc has a vertical slope at p_int: check whether it is // facing upwards or downwards and decide accordingly. - CGAL_assertion((arc.m_old_info & FACING_MASK) != 0); + CGAL_assertion((arc.m_info & FACING_MASK) != 0); - return (arc.m_new_info.test(FACING_UP_)) ? SMALLER : LARGER; + return (arc.test_flag(FACING_UP)) ? SMALLER : LARGER; } // The two arcs have vertical slopes at p_int: // First check whether one is facing up and one down. In this case the // comparison result is trivial. - if (this->m_new_info.test(FACING_UP_) && arc.m_new_info.test(FACING_DOWN_)) + if (test_flag(FACING_UP) && arc.test_flag(FACING_DOWN)) return LARGER; - else if (this->m_new_info.test(FACING_DOWN_) && arc.m_new_info.test(FACING_UP_)) + else if (test_flag(FACING_DOWN) && arc.test_flag(FACING_UP)) return SMALLER; // Compute the second-order derivative by y and act according to it. @@ -776,7 +751,7 @@ public: CGAL_assertion(slope_res != EQUAL); // Check whether both are facing up. - if (this->m_new_info.test(FACING_UP_) && arc.m_new_info.test(FACING_UP_)) + if (test_flag(FACING_UP) && arc.test_flag(FACING_UP)) return ((slope_res == LARGER) ? SMALLER : LARGER); // Both are facing down. @@ -893,7 +868,7 @@ public: c2 = *this; // Assign the endpoints of the arc. - if (this->m_new_info.test(IS_DIRECTED_RIGHT_)) { + if (test_flag(IS_DIRECTED_RIGHT)) { // The arc is directed from left to right, so p becomes c1's target // and c2's source. c1.m_target = p; @@ -933,8 +908,7 @@ public: arc.m_target = this->m_source; // Change the direction bit among the information flags. - arc.m_old_info = (this->m_old_info ^ IS_DIRECTED_RIGHT); - arc.m_new_info.flip(IS_DIRECTED_RIGHT_); + arc.flip_flag(IS_DIRECTED_RIGHT); return arc; } @@ -954,15 +928,14 @@ public: Self arc = *this; Alg_kernel ker; - if (! ((this->m_new_info.test(IS_DIRECTED_RIGHT_) && + if (! ((test_flag(IS_DIRECTED_RIGHT) && (ker.compare_xy_2_object()(ps, pt) == SMALLER)) || - (this->m_new_info.test(IS_DIRECTED_RIGHT_) && + (test_flag(IS_DIRECTED_RIGHT) && (ker.compare_xy_2_object()(ps, pt) == LARGER)))) { // We are allowed to change the direction only in case of a segment. CGAL_assertion(this->m_orient == COLLINEAR); - arc.m_old_info = (this->m_old_info ^ IS_DIRECTED_RIGHT); - arc.m_new_info.flip(IS_DIRECTED_RIGHT_); + arc.flip_flag(IS_DIRECTED_RIGHT); } // Make a copy of the current arc and assign its endpoints. @@ -1043,23 +1016,23 @@ public: if (ker.equal_2_object() (right(), arc.left())) { // Extend the arc to the right. - if (this->m_new_info.test(IS_DIRECTED_RIGHT_)) this->m_target = arc.right(); + if (test_flag(IS_DIRECTED_RIGHT)) this->m_target = arc.right(); else this->m_source = arc.right(); } else { CGAL_precondition(ker.equal_2_object() (left(), arc.right())); // Extend the arc to the left. - if (this->m_new_info.test(IS_DIRECTED_RIGHT_)) + if (test_flag(IS_DIRECTED_RIGHT)) this->m_source = arc.left(); else this->m_target = arc.left(); } } - bool is_upper() const { return this->m_new_info.test(FACING_UP_); } + bool is_upper() const { return test_flag(FACING_UP); } - bool is_lower() const { return this->m_new_info.test(FACING_DOWN_); } + bool is_lower() const { return test_flag(FACING_DOWN); } //@} private: @@ -1084,10 +1057,9 @@ private: this->m_source.set_generating_conic(m_id); this->m_target.set_generating_conic(m_id); - // Clear the m_old_info bits. - this->m_old_info = IS_VALID; - this->m_new_info.set(IS_VALID_); - this->m_new_info.reset(IS_FULL_CONIC_); + // Update the m_info bits. + set_flag(IS_VALID); + reset_flag(IS_FULL_CONIC); // Check if the arc is directed right (the target is lexicographically // greater than the source point), or to the left. @@ -1095,30 +1067,23 @@ private: Comparison_result dir_res = ker.compare_xy_2_object()(this->m_source, this->m_target); - CGAL_assertion (dir_res != EQUAL); + CGAL_assertion(dir_res != EQUAL); - if (dir_res == SMALLER) { - this->m_old_info = (this->m_old_info | IS_DIRECTED_RIGHT); - this->m_new_info.set(IS_DIRECTED_RIGHT_); - } + if (dir_res == SMALLER) set_flag(IS_DIRECTED_RIGHT); // Compute the degree of the underlying conic. if ((CGAL::sign(this->m_r) != ZERO) || (CGAL::sign(this->m_s) != ZERO) || (CGAL::sign(this->m_t) != ZERO)) { - this->m_old_info = (this->m_old_info | DEGREE_2); - this->m_new_info.set(DEGREE_2_); + set_flag(DEGREE_2); if (this->m_orient == COLLINEAR) { - this->m_old_info = (this->m_old_info | IS_SPECIAL_SEGMENT); - this->m_new_info.set(IS_SPECIAL_SEGMENT_); + set_flag(IS_SPECIAL_SEGMENT); - if (ker.compare_x_2_object()(this->m_source, this->m_target) == EQUAL) { - // The arc is a vertical segment: - this->m_old_info = (this->m_old_info | IS_VERTICAL_SEGMENT); - this->m_new_info.set(IS_VERTICAL_SEGMENT_); - } + // Check whether the arc is a vertical segment: + if (ker.compare_x_2_object()(this->m_source, this->m_target) == EQUAL) + set_flag(IS_VERTICAL_SEGMENT); return; } @@ -1130,12 +1095,10 @@ private: if (CGAL::sign(this->m_v) == ZERO) { // The supporting curve is of the form: _u*x + _w = 0 - this->m_old_info = (this->m_old_info | IS_VERTICAL_SEGMENT); - this->m_new_info.set(IS_VERTICAL_SEGMENT_); + set_flag(IS_VERTICAL_SEGMENT); } - this->m_old_info = (this->m_old_info | DEGREE_1); - this->m_new_info.set(DEGREE_1_); + set_flag(DEGREE_1); return; } @@ -1158,8 +1121,7 @@ private: if (is_strictly_between_endpoints(p_arc_mid)) { // Mark that we should use the -sqrt(disc) root for points on this // x-monotone arc. - this->m_old_info = (this->m_old_info & ~PLUS_SQRT_DISC_ROOT); - this->m_new_info.reset(PLUS_SQRT_DISC_ROOT_); + reset_flag(PLUS_SQRT_DISC_ROOT); } else { CGAL_assertion (n_ys == 2); @@ -1169,8 +1131,7 @@ private: // Mark that we should use the +sqrt(disc) root for points on this // x-monotone arc. - this->m_old_info = (this->m_old_info | PLUS_SQRT_DISC_ROOT); - this->m_new_info.set(PLUS_SQRT_DISC_ROOT_); + set_flag(PLUS_SQRT_DISC_ROOT); } // Check whether the conic is facing up or facing down: @@ -1180,23 +1141,17 @@ private: // coordinate is (x1+x2)/2 and compare it to (y1+y2)/2. Comparison_result res = ker.compare_y_2_object() (p_arc_mid, p_mid); - if (res == LARGER) { - // The arc is above the connecting segment, so it is facing upwards. - this->m_old_info = (this->m_old_info | FACING_UP); - this->m_new_info.set(FACING_UP_); - } - else if (res == SMALLER) { - // The arc is below the connecting segment, so it is facing downwards. - this->m_old_info = (this->m_old_info | FACING_DOWN); - this->m_new_info.set(FACING_DOWN_); - } + // If the arc is above the connecting segment, so it is facing upwards. + if (res == LARGER) set_flag(FACING_UP); + // If the arc is below the connecting segment, so it is facing downwards. + else if (res == SMALLER) set_flag(FACING_DOWN); } /*! Check if the arc is a special segment connecting two algebraic endpoints * (and has no undelying integer conic coefficients). */ bool is_special_segment() const - { return this->m_new_info.test(IS_SPECIAL_SEGMENT_); } + { return test_flag(IS_SPECIAL_SEGMENT); } /*! Check whether the given point lies on the supporting conic of the arc. * \param px The x-coordinate of query point. @@ -1525,7 +1480,7 @@ private: // arc: +=====> overlap = *this; - if (overlap.m_new_info.test(IS_DIRECTED_RIGHT_)) + if (overlap.test_flag(IS_DIRECTED_RIGHT)) overlap.m_source = arc.left(); else overlap.m_target = arc.left(); @@ -1538,7 +1493,7 @@ private: // arc: +=====> overlap = *this; - if (overlap.m_new_info.test(IS_DIRECTED_RIGHT_)) + if (overlap.test_flag(IS_DIRECTED_RIGHT)) overlap.m_target = arc.right(); else overlap.m_source = arc.right(); @@ -1572,8 +1527,8 @@ private: return; } - const int deg1 = ((this->m_old_info & DEGREE_MASK) == DEGREE_1) ? 1 : 2; - const int deg2 = ((arc.m_old_info & DEGREE_MASK) == DEGREE_1) ? 1 : 2; + const int deg1 = ((this->m_info & DEGREE_MASK) == flag_mask(DEGREE_1)) ? 1 : 2; + const int deg2 = ((arc.m_info & DEGREE_MASK) == flag_mask(DEGREE_1)) ? 1 : 2; Nt_traits nt_traits; Algebraic xs[4]; int n_xs = 0; From a5e015a8a39a63bf9248e8cdfb0f0a8f543b38c5 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Thu, 19 May 2022 23:57:42 +0300 Subject: [PATCH 010/105] Cleaned up --- .../include/CGAL/Arr_conic_traits_2.h | 474 +++++++----------- 1 file changed, 171 insertions(+), 303 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index f926dca65f0..69130afdd21 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -33,8 +33,7 @@ namespace CGAL { -/*! - * \class A traits class for maintaining an arrangement of conic arcs (bounded +/*! \class A traits class for maintaining an arrangement of conic arcs (bounded * segments of algebraic curves of degree 2 at most). * * The class is templated with two parameters: @@ -46,14 +45,14 @@ namespace CGAL { * Nt_traits A traits class for performing various operations on the integer, * rational and algebraic types. */ -template +template class Arr_conic_traits_2 { public: - typedef Rat_kernel_ Rat_kernel; - typedef Alg_kernel_ Alg_kernel; - typedef Nt_traits_ Nt_traits; + typedef RatKernel Rat_kernel; + typedef AlgKernel Alg_kernel; + typedef NtTraits Nt_traits; typedef typename Rat_kernel::FT Rational; typedef typename Rat_kernel::Point_2 Rat_point_2; @@ -85,26 +84,21 @@ public: typedef unsigned int Multiplicity; private: - // Type definition for the intersection points mapping. typedef typename X_monotone_curve_2::Conic_id Conic_id; typedef typename X_monotone_curve_2::Intersection_point Intersection_point; typedef typename X_monotone_curve_2::Intersection_map Intersection_map; - mutable Intersection_map inter_map; // Mapping conic pairs to their + mutable Intersection_map inter_map; // Mapping conic pairs to their // intersection points. public: - - /*! - * Default constructor. + /*! Default constructor. */ - Arr_conic_traits_2 () - {} + Arr_conic_traits_2() {} - /*! Get the next conic index. */ - static unsigned int get_index () - { + /*! Obtain the next conic index. */ + static unsigned int get_index() { #ifdef CGAL_NO_ATOMIC static unsigned int index; #else @@ -116,119 +110,89 @@ public: /// \name Basic functor definitions. //@{ - class Compare_x_2 - { + class Compare_x_2 { public: - /*! - * Compare the x-coordinates of two points. + /*! Compare the x-coordinates of two points. * \param p1 The first point. * \param p2 The second point. * \return LARGER if x(p1) > x(p2); * SMALLER if x(p1) < x(p2); * EQUAL if x(p1) = x(p2). */ - Comparison_result operator() (const Point_2 & p1, const Point_2 & p2) const + Comparison_result operator() (const Point_2& p1, const Point_2& p2) const { Alg_kernel ker; - return (ker.compare_x_2_object() (p1, p2)); + return (ker.compare_x_2_object()(p1, p2)); } }; - /*! Get a Compare_x_2 functor object. */ - Compare_x_2 compare_x_2_object () const - { - return Compare_x_2(); - } + /*! Obtain a Compare_x_2 functor object. */ + Compare_x_2 compare_x_2_object () const { return Compare_x_2(); } - class Compare_xy_2 - { + class Compare_xy_2 { public: - /*! - * Compares two points lexigoraphically: by x, then by y. + /*! Compares two points lexigoraphically: by x, then by y. * \param p1 The first point. * \param p2 The second point. * \return LARGER if x(p1) > x(p2), or if x(p1) = x(p2) and y(p1) > y(p2); * SMALLER if x(p1) < x(p2), or if x(p1) = x(p2) and y(p1) < y(p2); * EQUAL if the two points are equal. */ - Comparison_result operator() (const Point_2& p1, const Point_2& p2) const - { - Alg_kernel ker; - return (ker.compare_xy_2_object() (p1, p2)); + Comparison_result operator()(const Point_2& p1, const Point_2& p2) const { + Alg_kernel ker; + return ker.compare_xy_2_object()(p1, p2); } }; - /*! Get a Compare_xy_2 functor object. */ - Compare_xy_2 compare_xy_2_object () const - { - return Compare_xy_2(); - } + /*! Obtain a Compare_xy_2 functor object. */ + Compare_xy_2 compare_xy_2_object() const + { return Compare_xy_2(); } - class Construct_min_vertex_2 - { + class Construct_min_vertex_2 { public: - /*! - * Get the left endpoint of the x-monotone curve (segment). + /*! Obtain the left endpoint of the x-monotone curve (segment). * \param cv The curve. * \return The left endpoint. */ - const Point_2& operator() (const X_monotone_curve_2 & cv) const - { - return (cv.left()); - } + const Point_2& operator()(const X_monotone_curve_2 & cv) const + { return cv.left(); } }; - /*! Get a Construct_min_vertex_2 functor object. */ - Construct_min_vertex_2 construct_min_vertex_2_object () const - { - return Construct_min_vertex_2(); - } + /*! Obtain a Construct_min_vertex_2 functor object. */ + Construct_min_vertex_2 construct_min_vertex_2_object() const + { return Construct_min_vertex_2(); } - class Construct_max_vertex_2 - { + class Construct_max_vertex_2 { public: - /*! - * Get the right endpoint of the x-monotone curve (segment). + /*! Obtain the right endpoint of the x-monotone curve (segment). * \param cv The curve. * \return The right endpoint. */ - const Point_2& operator() (const X_monotone_curve_2 & cv) const - { - return (cv.right()); - } + const Point_2& operator()(const X_monotone_curve_2 & cv) const + { return cv.right(); } }; - /*! Get a Construct_max_vertex_2 functor object. */ - Construct_max_vertex_2 construct_max_vertex_2_object () const - { - return Construct_max_vertex_2(); - } + /*! Obtain a Construct_max_vertex_2 functor object. */ + Construct_max_vertex_2 construct_max_vertex_2_object() const + { return Construct_max_vertex_2(); } - class Is_vertical_2 - { + class Is_vertical_2 { public: - /*! - * Check whether the given x-monotone curve is a vertical segment. + /*! Check whether the given x-monotone curve is a vertical segment. * \param cv The curve. * \return (true) if the curve is a vertical segment; (false) otherwise. */ - bool operator() (const X_monotone_curve_2& cv) const - { - return (cv.is_vertical()); - } + bool operator()(const X_monotone_curve_2& cv) const + { return cv.is_vertical(); } }; - /*! Get an Is_vertical_2 functor object. */ - Is_vertical_2 is_vertical_2_object () const - { - return Is_vertical_2(); - } + /*! Obtain an Is_vertical_2 functor object. */ + Is_vertical_2 is_vertical_2_object() const + { return Is_vertical_2(); } - class Compare_y_at_x_2 - { + class Compare_y_at_x_2 { public: - /*! - * Return the location of the given point with respect to the input curve. + /*! Return the location of the given point with respect to the input curve. * \param cv The curve. * \param p The point. * \pre p is in the x-range of cv. @@ -236,69 +200,57 @@ public: * LARGER if y(p) > cv(x(p)), i.e. the point is above the curve; * EQUAL if p lies on the curve. */ - Comparison_result operator() (const Point_2 & p, - const X_monotone_curve_2 & cv) const + Comparison_result operator()(const Point_2 & p, + const X_monotone_curve_2 & cv) const { - Alg_kernel ker; + Alg_kernel ker; - if (cv.is_vertical()) - { + if (cv.is_vertical()) { // A special treatment for vertical segments: // In case p has the same x c-ordinate of the vertical segment, compare // it to the segment endpoints to determine its position. - Comparison_result res1 = ker.compare_y_2_object() (p, cv.left()); - Comparison_result res2 = ker.compare_y_2_object() (p, cv.right()); + Comparison_result res1 = ker.compare_y_2_object()(p, cv.left()); + Comparison_result res2 = ker.compare_y_2_object()(p, cv.right()); - if (res1 == res2) - return (res1); - else - return (EQUAL); + if (res1 == res2) return res1; + else return EQUAL; } // Check whether the point is exactly on the curve. - if (cv.contains_point(p)) - return (EQUAL); + if (cv.contains_point(p)) return EQUAL; - // Get a point q on the x-monotone arc with the same x coordinate as p. - Comparison_result x_res; - Point_2 q; + // Obtain a point q on the x-monotone arc with the same x coordinate as p. + Comparison_result x_res; + Point_2 q; - if ((x_res = ker.compare_x_2_object() (p, cv.left())) == EQUAL) - { + if ((x_res = ker.compare_x_2_object()(p, cv.left())) == EQUAL) { q = cv.left(); } - else - { + else { CGAL_precondition (x_res != SMALLER); - if ((x_res = ker.compare_x_2_object() (p, cv.right())) == EQUAL) - { + if ((x_res = ker.compare_x_2_object()(p, cv.right())) == EQUAL) { q = cv.right(); } - else - { - CGAL_precondition (x_res != LARGER); + else { + CGAL_precondition(x_res != LARGER); q = cv.point_at_x (p); } } // Compare p with the a point of the curve with the same x coordinate. - return (ker.compare_y_2_object() (p, q)); + return (ker.compare_y_2_object()(p, q)); } }; - /*! Get a Compare_y_at_x_2 functor object. */ - Compare_y_at_x_2 compare_y_at_x_2_object () const - { - return Compare_y_at_x_2(); - } + /*! Obtain a Compare_y_at_x_2 functor object. */ + Compare_y_at_x_2 compare_y_at_x_2_object() const + { return Compare_y_at_x_2(); } - class Compare_y_at_x_left_2 - { + class Compare_y_at_x_left_2 { public: - /*! - * Compares the y value of two x-monotone curves immediately to the left + /*! Compares the y value of two x-monotone curves immediately to the left * of their intersection point. * \param cv1 The first curve. * \param cv2 The second curve. @@ -308,53 +260,39 @@ public: * \return The relative position of cv1 with respect to cv2 immdiately to * the left of p: SMALLER, LARGER or EQUAL. */ - Comparison_result operator() (const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2, - const Point_2& p) const + Comparison_result operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2, + const Point_2& p) const { // Make sure that p lies on both curves, and that both are defined to its // left (so their left endpoint is lexicographically smaller than p). - CGAL_precondition (cv1.contains_point (p) && - cv2.contains_point (p)); + CGAL_precondition(cv1.contains_point(p) && + cv2.contains_point(p)); - CGAL_precondition_code ( - Alg_kernel ker; - ); - CGAL_precondition (ker.compare_xy_2_object() (p, - cv1.left()) == LARGER && - ker.compare_xy_2_object() (p, - cv2.left()) == LARGER); + CGAL_precondition_code(Alg_kernel ker;); + CGAL_precondition(ker.compare_xy_2_object()(p, cv1.left()) == LARGER && + ker.compare_xy_2_object()(p, cv2.left()) == LARGER); // If one of the curves is vertical, it is below the other one. - if (cv1.is_vertical()) - { - if (cv2.is_vertical()) - // Both are vertical: - return (EQUAL); - else - return (SMALLER); - } - else if (cv2.is_vertical()) - { - return (LARGER); + if (cv1.is_vertical()) { + // Check whether both are vertical: + if (cv2.is_vertical()) return EQUAL; + else return SMALLER; } + else if (cv2.is_vertical()) return LARGER; // Compare the two curves immediately to the left of p: - return (cv1.compare_to_left (cv2, p)); + return cv1.compare_to_left(cv2, p); } }; - /*! Get a Compare_y_at_x_left_2 functor object. */ - Compare_y_at_x_left_2 compare_y_at_x_left_2_object () const - { - return Compare_y_at_x_left_2(); - } + /*! Obtain a Compare_y_at_x_left_2 functor object. */ + Compare_y_at_x_left_2 compare_y_at_x_left_2_object() const + { return Compare_y_at_x_left_2(); } - class Compare_y_at_x_right_2 - { + class Compare_y_at_x_right_2 { public: - /*! - * Compares the y value of two x-monotone curves immediately to the right + /*! Compares the y value of two x-monotone curves immediately to the right * of their intersection point. * \param cv1 The first curve. * \param cv2 The second curve. @@ -364,88 +302,63 @@ public: * \return The relative position of cv1 with respect to cv2 immdiately to * the right of p: SMALLER, LARGER or EQUAL. */ - Comparison_result operator() (const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2, - const Point_2& p) const + Comparison_result operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2, + const Point_2& p) const { // Make sure that p lies on both curves, and that both are defined to its // left (so their left endpoint is lexicographically smaller than p). - CGAL_precondition (cv1.contains_point (p) && - cv2.contains_point (p)); - - CGAL_precondition_code ( - Alg_kernel ker; - ); - - CGAL_precondition (ker.compare_xy_2_object() (p, - cv1.right()) == SMALLER && - ker.compare_xy_2_object() (p, - cv2.right()) == SMALLER); + CGAL_precondition(cv1.contains_point(p) && cv2.contains_point(p)); + CGAL_precondition_code(Alg_kernel ker;); + CGAL_precondition(ker.compare_xy_2_object()(p, cv1.right()) == SMALLER && + ker.compare_xy_2_object()(p, cv2.right()) == SMALLER); // If one of the curves is vertical, it is above the other one. - if (cv1.is_vertical()) - { - if (cv2.is_vertical()) - // Both are vertical: - return (EQUAL); - else - return (LARGER); - } - else if (cv2.is_vertical()) - { - return (SMALLER); + if (cv1.is_vertical()) { + // Check whether both are vertical: + if (cv2.is_vertical()) return EQUAL; + else return LARGER; } + else if (cv2.is_vertical()) return SMALLER; // Compare the two curves immediately to the right of p: - return (cv1.compare_to_right (cv2, p)); + return cv1.compare_to_right(cv2, p); } }; - /*! Get a Compare_y_at_x_right_2 functor object. */ - Compare_y_at_x_right_2 compare_y_at_x_right_2_object () const - { - return Compare_y_at_x_right_2(); - } + /*! Obtain a Compare_y_at_x_right_2 functor object. */ + Compare_y_at_x_right_2 compare_y_at_x_right_2_object() const + { return Compare_y_at_x_right_2(); } - class Equal_2 - { + class Equal_2 { public: - /*! - * Check if the two x-monotone curves are the same (have the same graph). + /*! Check whether the two x-monotone curves are the same (have the same graph). * \param cv1 The first curve. * \param cv2 The second curve. * \return (true) if the two curves are the same; (false) otherwise. */ - bool operator() (const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2) const + bool operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2) const { - if (&cv1 == &cv2) - return (true); - - return (cv1.equals (cv2)); + if (&cv1 == &cv2) return true; + return cv1.equals(cv2); } - /*! - * Check if the two points are the same. + /*! Check whether the two points are the same. * \param p1 The first point. * \param p2 The second point. * \return (true) if the two point are the same; (false) otherwise. */ - bool operator() (const Point_2& p1, const Point_2& p2) const - { - if (&p1 == &p2) - return (true); + bool operator()(const Point_2& p1, const Point_2& p2) const { + if (&p1 == &p2) return (true); - Alg_kernel ker; - return (ker.compare_xy_2_object() (p1, p2) == EQUAL); + Alg_kernel ker; + return(ker.compare_xy_2_object()(p1, p2) == EQUAL); } }; - /*! Get an Equal_2 functor object. */ - Equal_2 equal_2_object () const - { - return Equal_2(); - } + /*! Obtain an Equal_2 functor object. */ + Equal_2 equal_2_object() const { return Equal_2(); } //@} /// \name Intersections, subdivisions, and mergings @@ -455,7 +368,7 @@ public: * A functor for subdividing curves into x-monotone curves. */ class Make_x_monotone_2 { - typedef Arr_conic_traits_2 Self; + typedef Arr_conic_traits_2 Self; public: /*! Subdivide a given conic curve (or conic arc) into x-monotone subcurves @@ -467,8 +380,7 @@ public: * \return the past-the-end iterator. */ template - OutputIterator operator()(const Curve_2& cv, OutputIterator oi) const - { + OutputIterator operator()(const Curve_2& cv, OutputIterator oi) const { typedef boost::variant Make_x_monotone_result; @@ -524,11 +436,11 @@ public: // tangnecy points (or both lies above it). int ind_first = 0; int ind_second = 1; - Alg_kernel_ ker; - typename Alg_kernel_::Line_2 line = + Alg_kernel ker; + typename Alg_kernel::Line_2 line = ker.construct_line_2_object()(vtan_ps[0], vtan_ps[1]); const Comparison_result start_pos = - ker.compare_y_at_x_2_object() (cv.source(), line); + ker.compare_y_at_x_2_object()(cv.source(), line); const Comparison_result order_vpts = ker.compare_x_2_object()(vtan_ps[0], vtan_ps[1]); @@ -566,34 +478,26 @@ public: } }; - /*! Get a Make_x_monotone_2 functor object. */ + /*! Obtain a Make_x_monotone_2 functor object. */ Make_x_monotone_2 make_x_monotone_2_object() const { return Make_x_monotone_2(); } - class Split_2 - { + class Split_2 { public: - /*! - * Split a given x-monotone curve at a given point into two sub-curves. + /*! Split a given x-monotone curve at a given point into two sub-curves. * \param cv The curve to split * \param p The split point. * \param c1 Output: The left resulting subcurve (p is its right endpoint). * \param c2 Output: The right resulting subcurve (p is its left endpoint). * \pre p lies on cv but is not one of its end-points. */ - void operator() (const X_monotone_curve_2& cv, const Point_2 & p, - X_monotone_curve_2& c1, X_monotone_curve_2& c2) const - { - cv.split (p, c1, c2); - return; - } + void operator()(const X_monotone_curve_2& cv, const Point_2 & p, + X_monotone_curve_2& c1, X_monotone_curve_2& c2) const + { cv.split(p, c1, c2); } }; - /*! Get a Split_2 functor object. */ - Split_2 split_2_object () const - { - return Split_2(); - } + /*! Obtain a Split_2 functor object. */ + Split_2 split_2_object() const { return Split_2(); } class Intersect_2 { private: @@ -615,17 +519,15 @@ public: OutputIterator operator()(const X_monotone_curve_2& cv1, const X_monotone_curve_2& cv2, OutputIterator oi) const - { return (cv1.intersect(cv2, _inter_map, oi)); } + { return cv1.intersect(cv2, _inter_map, oi); } }; - /*! Get an Intersect_2 functor object. */ - Intersect_2 intersect_2_object () const { return (Intersect_2(inter_map)); } + /*! Obtain an Intersect_2 functor object. */ + Intersect_2 intersect_2_object() const { return (Intersect_2(inter_map)); } - class Are_mergeable_2 - { + class Are_mergeable_2 { public: - /*! - * Check whether it is possible to merge two given x-monotone curves. + /*! Check whether it is possible to merge two given x-monotone curves. * \param cv1 The first curve. * \param cv2 The second curve. * \return (true) if the two curves are mergeable - if they are supported @@ -633,22 +535,17 @@ public: */ bool operator() (const X_monotone_curve_2& cv1, const X_monotone_curve_2& cv2) const - { - return (cv1.can_merge_with (cv2)); - } + { return cv1.can_merge_with(cv2); } }; - /*! Get an Are_mergeable_2 functor object. */ - Are_mergeable_2 are_mergeable_2_object () const - { - return Are_mergeable_2(); - } + /*! Obtain an Are_mergeable_2 functor object. */ + Are_mergeable_2 are_mergeable_2_object() const + { return Are_mergeable_2(); } /*! \class Merge_2 * A functor that merges two x-monotone arcs into one. */ - class Merge_2 - { + class Merge_2 { protected: typedef Arr_conic_traits_2 Traits; @@ -663,16 +560,15 @@ public: friend class Arr_conic_traits_2; public: - /*! - * Merge two given x-monotone curves into a single curve (segment). + /*! Merge two given x-monotone curves into a single curve (segment). * \param cv1 The first curve. * \param cv2 The second curve. * \param c Output: The merged curve. * \pre The two curves are mergeable. */ - void operator() (const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2, - X_monotone_curve_2& c) const + void operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2, + X_monotone_curve_2& c) const { CGAL_precondition(m_traits->are_mergeable_2_object()(cv2, cv1)); @@ -682,10 +578,7 @@ public: }; /*! Obtain a Merge_2 functor object. */ - Merge_2 merge_2_object() const - { - return Merge_2(this); - } + Merge_2 merge_2_object() const { return Merge_2(this); } //@} @@ -693,35 +586,26 @@ public: //@{ typedef double Approximate_number_type; - class Approximate_2 - { + class Approximate_2 { public: - - /*! - * Return an approximation of a point coordinate. + /*! Return an approximation of a point coordinate. * \param p The exact point. * \param i The coordinate index (either 0 or 1). * \pre i is either 0 or 1. * \return An approximation of p's x-coordinate (if i == 0), or an * approximation of p's y-coordinate (if i == 1). */ - Approximate_number_type operator() (const Point_2& p, - int i) const - { - CGAL_precondition (i == 0 || i == 1); + Approximate_number_type operator()(const Point_2& p, int i) const { + CGAL_precondition(i == 0 || i == 1); - if (i == 0) - return (CGAL::to_double(p.x())); - else - return (CGAL::to_double(p.y())); + if (i == 0) return CGAL::to_double(p.x()); + else return CGAL::to_double(p.y()); } }; - /*! Get an Approximate_2 functor object. */ + /*! Obtain an Approximate_2 functor object. */ Approximate_2 approximate_2_object () const - { - return Approximate_2(); - } + { return Approximate_2(); } //! Functor class Construct_x_monotone_curve_2 { @@ -736,7 +620,7 @@ public: { return (X_monotone_curve_2(p, q)); } }; - /*! Get a Construct_x_monotone_curve_2 functor object. */ + /*! Obtain a Construct_x_monotone_curve_2 functor object. */ Construct_x_monotone_curve_2 construct_x_monotone_curve_2_object () const { return Construct_x_monotone_curve_2(); } @@ -750,10 +634,10 @@ public: * \return A segment connecting p and q. */ Curve_2 operator()(const Point_2& p, const Point_2& q) const - { return (Curve_2(p, q)); } + { return Curve_2(p, q); } }; - /*! Get a Construct_curve_2 functor object. */ + /*! Obtain a Construct_curve_2 functor object. */ Construct_curve_2 construct_curve_2_object () const { return Construct_curve_2(); } //@} @@ -761,55 +645,39 @@ public: /// \name Functor definitions for the Boolean set-operation traits. //@{ - class Compare_endpoints_xy_2 - { + class Compare_endpoints_xy_2 { public: - - /*! - * Compare the endpoints of an $x$-monotone curve lexicographically. + /*! Compare the endpoints of an $x$-monotone curve lexicographically. * (assuming the curve has a designated source and target points). * \param cv The curve. * \return SMALLER if the curve is directed right; * LARGER if the curve is directed left. */ - Comparison_result operator() (const X_monotone_curve_2& cv) const - { - if (cv.is_directed_right()) - return (SMALLER); - else - return (LARGER); + Comparison_result operator() (const X_monotone_curve_2& cv) const { + if (cv.is_directed_right()) return SMALLER; + else return LARGER; } }; - /*! Get a Compare_endpoints_xy_2 functor object. */ + /*! Obtain a Compare_endpoints_xy_2 functor object. */ Compare_endpoints_xy_2 compare_endpoints_xy_2_object() const - { - return Compare_endpoints_xy_2(); - } + { return Compare_endpoints_xy_2(); } - class Construct_opposite_2 - { + class Construct_opposite_2 { public: - - /*! - * Construct an opposite x-monotone (with swapped source and target). + /*! Construct an opposite x-monotone (with swapped source and target). * \param cv The curve. * \return The opposite curve. */ - X_monotone_curve_2 operator() (const X_monotone_curve_2& cv) const - { - return (cv.flip()); - } + X_monotone_curve_2 operator()(const X_monotone_curve_2& cv) const + { return cv.flip(); } }; - /*! Get a Construct_opposite_2 functor object. */ + /*! Obtain a Construct_opposite_2 functor object. */ Construct_opposite_2 construct_opposite_2_object() const - { - return Construct_opposite_2(); - } + { return Construct_opposite_2(); } - class Trim_2 - { + class Trim_2 { protected: typedef Arr_conic_traits_2 Traits; From 70d21e5a394d1506427684c1deccdc30ac80e9d0 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Mon, 23 May 2022 11:01:11 +0300 Subject: [PATCH 011/105] Move conic construction to the (conic) traits and elliminated the constructions of local kernel objects. --- .../include/CGAL/Arr_conic_traits_2.h | 825 +++++++++++++++++- .../CGAL/Arr_geometry_traits/Conic_arc_2.h | 43 +- 2 files changed, 854 insertions(+), 14 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index 69130afdd21..b32eeda58bb 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -46,10 +47,8 @@ namespace CGAL { * rational and algebraic types. */ template -class Arr_conic_traits_2 -{ +class Arr_conic_traits_2 { public: - typedef RatKernel Rat_kernel; typedef AlgKernel Alg_kernel; typedef NtTraits Nt_traits; @@ -89,6 +88,14 @@ private: typedef typename X_monotone_curve_2::Intersection_point Intersection_point; typedef typename X_monotone_curve_2::Intersection_map Intersection_map; + typedef std::shared_ptr Shared_rat_kernel; + typedef std::shared_ptr Shared_alg_kernel; + typedef std::shared_ptr Shared_nt_Traits; + + const Shared_rat_kernel m_rat_kernel; + const Shared_alg_kernel m_alg_kernel; + const Shared_nt_Traits m_nt_traits; + mutable Intersection_map inter_map; // Mapping conic pairs to their // intersection points. @@ -97,6 +104,16 @@ public: */ Arr_conic_traits_2() {} + /*! Construct from resources. + */ + Arr_conic_traits_2(Shared_rat_kernel rat_kernel, + Shared_alg_kernel alg_kernel, + Shared_nt_Traits nt_traits) : + m_rat_kernel(rat_kernel), + m_alg_kernel(alg_kernel), + m_nt_traits(nt_traits) + {} + /*! Obtain the next conic index. */ static unsigned int get_index() { #ifdef CGAL_NO_ATOMIC @@ -624,22 +641,450 @@ public: Construct_x_monotone_curve_2 construct_x_monotone_curve_2_object () const { return Construct_x_monotone_curve_2(); } - //! Functor + //! Constructor of conic arcs class Construct_curve_2 { + protected: + typedef Arr_conic_traits_2 Traits; + + /*! The traits (in case it has state) */ + const Traits& m_traits; + + /*! Constructor + * \param traits the traits. + */ + Construct_curve_2(const Traits& traits) : m_traits(traits) {} + + friend class Arr_conic_traits_2; + public: + /*! Construct an empty curve. + */ + Curve_2 operator()() const { return Curve_2(); } + + /*! Construct a conic arc which is the full conic: + * C: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0 + * \pre The conic C must be an ellipse (so 4rs - t^2 > 0). + */ + Curve_2 operator()(const Rational& r, const Rational& s, const Rational& t, + const Rational& u, const Rational& v, const Rational& w) + const + { + // Ensure that the given curve is an ellipse (4rs - t^2 is positive). + CGAL_precondition(CGAL::sign(4*r*s - t*t) == POSITIVE); + + // Set the arc to be the full conic (and compute the orientation). + Rational rat_coeffs[6]; + + rat_coeffs[0] = r; + rat_coeffs[1] = s; + rat_coeffs[2] = t; + rat_coeffs[3] = u; + rat_coeffs[4] = v; + rat_coeffs[5] = w; + + set_full(rat_coeffs, true); + } + + /*! Construct a conic arc that lies on the conic: + * C: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0 + * \param orient The orientation of the arc (clockwise or counterclockwise). + * \param source The source point. + * \param target The target point. + * \pre The source and the target must be on the conic boundary and must + * not be the same. + */ + Curve_2 operator()(const Rational& r, const Rational& s, const Rational& t, + const Rational& u, const Rational& v, const Rational& w, + const Orientation& orient, + const Point_2& source, const Point_2& target) const { + // Make sure that the source and the taget are not the same. + const auto* alg_kernel = m_traits.m_alg_kernel; + CGAL_precondition(alg_kernel->compare_xy_2_object()(source, target) != + EQUAL); + // Set the arc properties (no need to compute the orientation). + Rational rat_coeffs[6] = {r, s, t, u, v, w}; + Curve_2 arc; + arc.set_orientation(orient); + arc.set_endpoints(source, target); + set(arc, rat_coeffs); + return arc; + } + + /*! Construct a conic arc that is a circular arc from given three points. + * \param p1 The arc source. + * \param p2 A point in the interior of the arc. + * \param p3 The arc target. + * \pre The three points must not be collinear. + */ + Curve_2 operator()(const Rat_point_2& p1, const Rat_point_2& p2, + const Rat_point_2& p3) { + Curve_2 arc; + + // Set the source and target. + const Rational& x1 = p1.x(); + const Rational& y1 = p1.y(); + const Rational& x2 = p2.x(); + const Rational& y2 = p2.y(); + const Rational& x3 = p3.x(); + const Rational& y3 = p3.y(); + + const auto* nt_traits = m_traits.m_nt_traits; + const auto* alg_kernel = m_traits.m_alg_kernel; + auto source = Point_2(nt_traits->convert(x1), nt_traits->convert(y1)); + auto target = Point_2(nt_traits->convert(x3), nt_traits->convert(y3)); + arc.set_enpoints(source, target); + + // Make sure that the source and the taget are not the same. + CGAL_precondition(alg_kernel->compare_xy_2_object()(source, target) != + EQUAL); + + // Compute the lines: A1*x + B1*y + C1 = 0, + // and: A2*x + B2*y + C2 = 0, + // where: + const Rational two = 2; + + const Rational A1 = two*(x1 - x2); + const Rational B1 = two*(y1 - y2); + const Rational C1 = y2*y2 - y1*y1 + x2*x2 - x1*x1; + + const Rational A2 = two*(x2 - x3); + const Rational B2 = two*(y2 - y3); + const Rational C2 = y3*y3 - y2*y2 + x3*x3 - x2*x2; + + // Compute the coordinates of the intersection point between the + // two lines, given by (Nx / D, Ny / D), where: + const Rational Nx = B1*C2 - B2*C1; + const Rational Ny = A2*C1 - A1*C2; + const Rational D = A1*B2 - A2*B1; + + // Make sure the three points are not collinear. + const bool points_collinear = (CGAL::sign(D) == ZERO); + + if (points_collinear) { + arc.reset_flags(); // inavlid arc + return arc; + } + + // The equation of the underlying circle is given by: + Rational rat_coeffs[6]; + rat_coeffs[0] = D*D; + rat_coeffs[1] = D*D; + rat_coeffs[2] = 0; + rat_coeffs[3] = -two*D*Nx; + rat_coeffs[4] = -two*D*Ny; + rat_coeffs[5] = + Nx*Nx + Ny*Ny - ((D*x2 - Nx)*(D*x2 - Nx) + (D*y2 - Ny)*(D*y2 - Ny)); + + // Determine the orientation: If the mid-point forms a left-turn with + // the source and the target points, the orientation is positive (going + // counterclockwise). + // Otherwise, it is negative (going clockwise). + auto orient_f = m_alg_kernel.orientation_2_object(); + Point_2 p_mid = Point_2(nt_traits->convert(x2), nt_traits->convert(y2)); + + auto orient = (orient_f(source, p_mid, target) == LEFT_TURN) ? + COUNTERCLOCKWISE : CLOCKWISE; + arc.set_orientation(orient); + + // Set the arc properties (no need to compute the orientation). + set(arc, rat_coeffs); + return arc; + } + + /*! Construct a conic arc from given five points, specified by the + * points p1, p2, p3, p4 and p5. + * \param p1 The source point of the given arc. + * \param p2,p3,p4 Points lying on the conic arc, between p1 and p5. + * \param p5 The target point of the given arc. + * \pre No three points are collinear. + */ + Curve_2 operator()(const Rat_point_2& p1, const Rat_point_2& p2, + const Rat_point_2& p3, const Rat_point_2& p4, + const Rat_point_2& p5) { + Curve_2 arc; + + // Make sure that no three points are collinear. + Rat_kernel ker; + auto orient_f = m_rat_kernel.orientation_2_object(); + const bool point_collinear = + (orient_f(p1, p2, p3) == COLLINEAR || + orient_f(p1, p2, p4) == COLLINEAR || + orient_f(p1, p2, p5) == COLLINEAR || + orient_f(p1, p3, p4) == COLLINEAR || + orient_f(p1, p3, p5) == COLLINEAR || + orient_f(p1, p4, p5) == COLLINEAR || + orient_f(p2, p3, p4) == COLLINEAR || + orient_f(p2, p3, p5) == COLLINEAR || + orient_f(p2, p4, p5) == COLLINEAR || + orient_f(p3, p4, p5) == COLLINEAR); + + if (point_collinear) { + arc.reset_flags(); // inavlid arc + return arc; + } + + // Set the source and target. + const Rational& x1 = p1.x(); + const Rational& y1 = p1.y(); + const Rational& x5 = p5.x(); + const Rational& y5 = p5.y(); + + const auto* nt_traits = m_traits.m_nt_traits; + auto source = Point_2(nt_traits->convert(x1), nt_traits->convert(y1)); + auto target = Point_2(nt_traits->convert(x5), nt_traits->convert(y5)); + arc.set_endpoints(source, target); + + // Set a conic curve that passes through the five given point. + typename Rat_kernel::Conic_2 temp_conic; + temp_conic.set(p1, p2, p3, p4, p5); + + // Get the conic coefficients. + Rational rat_coeffs[6]; + rat_coeffs[0] = temp_conic.r(); + rat_coeffs[1] = temp_conic.s(); + rat_coeffs[2] = temp_conic.t(); + rat_coeffs[3] = temp_conic.u(); + rat_coeffs[4] = temp_conic.v(); + rat_coeffs[5] = temp_conic.w(); + + // Determine the orientation: If one of the midpoints forms a left-turn + // with the source and the target points, the orientation is positive + // (going counterclockwise). + // Otherwise, it is negative (going clockwise). + const Orientation turn = orient_f(p1, p2, p5); + + if (turn == LEFT_TURN) { + arc.set_orientation(COUNTERCLOCKWISE); + CGAL_precondition(orient_f(p1, p3, p5) == LEFT_TURN && + orient_f(p1, p4, p5) == LEFT_TURN); + } + else { + arc.set_orientation(CLOCKWISE); + CGAL_precondition(orient_f(p1, p3, p5) != LEFT_TURN && + orient_f(p1, p4, p5) != LEFT_TURN); + } + + // Set the arc properties (no need to compute the orientation). + set(arc, rat_coeffs); + + // Make sure that all midpoints are strictly between the + // source and the target. + Point_2 mp2 = + Point_2(nt_traits->convert(p2.x()), nt_traits->convert(p2.y())); + Point_2 mp3 = + Point_2(nt_traits->convert(p3.x()), m_nt_traits->convert(p3.y())); + Point_2 mp4 = + Point_2(nt_traits->convert(p4.x()), nt_traits->convert(p4.y())); + + if (! is_strictly_between_endpoints(arc, mp2) || + ! is_strictly_between_endpoints(arc, mp3) || + ! is_strictly_between_endpoints(arc, mp4)) + { + arc.reset_flags(); // inavlid arc + return arc; + } + return arc; + } + + /*! Construct a conic arc that lies on a conic given by its coefficients: + * C: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0 + * The source and the target are specified by the intersection of the + * conic with: + * C_1: r_1*x^2 + s_1*y^2 + t_1*xy + u_1*x + v_1*y + w_1 = 0 + * C_2: r_2*x^2 + s_2*y^2 + t_2*xy + u_2*x + v_2*y + w_2 = 0 + * The user must also specify the source and the target with approximated + * coordinates. The actual intersection points that best fits the source + * (or the target) will be selected. + */ + Curve_2 operator()(const Rational& r, const Rational& s, const Rational& t, + const Rational& u, const Rational& v, const Rational& w, + const Orientation& orient, + const Point_2& app_source, + const Rational& r_1, const Rational& s_1, + const Rational& t_1, const Rational& u_1, + const Rational& v_1, const Rational& w_1, + const Point_2& app_target, + const Rational& r_2, const Rational& s_2, + const Rational& t_2, const Rational& u_2, + const Rational& v_2, const Rational& w_2) const { + Curve_2 arc; + arc.set_orientation(orient); + + // Create the integer coefficients of the base conic. + Rational rat_coeffs [6]; + rat_coeffs[0] = r; + rat_coeffs[1] = s; + rat_coeffs[2] = t; + rat_coeffs[3] = u; + rat_coeffs[4] = v; + rat_coeffs[5] = w; + + const auto* nt_traits = m_traits.m_nt_traits; + Integer base_coeffs[6]; + nt_traits->convert_coefficients(rat_coeffs, rat_coeffs + 6, base_coeffs); + + int deg_base = (CGAL::sign(base_coeffs[0]) == ZERO && + CGAL::sign(base_coeffs[1]) == ZERO && + CGAL::sign(base_coeffs[2]) == ZERO) ? 1 : 2; + + // Compute the endpoints. + Rational aux_rat_coeffs [6]; + Algebraic xs[4]; + Algebraic ys[4]; + Algebraic val; + bool found; + double curr_dist; + double min_dist = -1; + Integer aux_coeffs[6]; + for (int k = 1; k <= 2; ++k) { + // Get the integer coefficients of the k'th auxiliary conic curve. + aux_rat_coeffs[0] = (k == 1) ? r_1 : r_2; + aux_rat_coeffs[1] = (k == 1) ? s_1 : s_2; + aux_rat_coeffs[2] = (k == 1) ? t_1 : t_2; + aux_rat_coeffs[3] = (k == 1) ? u_1 : u_2; + aux_rat_coeffs[4] = (k == 1) ? v_1 : v_2; + aux_rat_coeffs[5] = (k == 1) ? w_1 : w_2; + + nt_traits->convert_coefficients(aux_rat_coeffs, aux_rat_coeffs + 6, + aux_coeffs); + + int deg_aux = ((CGAL::sign(aux_coeffs[0]) == ZERO) && + (CGAL::sign(aux_coeffs[1]) == ZERO) && + (CGAL::sign(aux_coeffs[2]) == ZERO)) ? 1 : 2; + + // Compute the x- and y-coordinates of intersection points of the base + // conic and the k'th auxiliary conic. + int n_xs = compute_resultant_roots(nt_traits, + base_coeffs[0], base_coeffs[1], + base_coeffs[2], + base_coeffs[3], base_coeffs[4], + base_coeffs[5], + deg_base, + aux_coeffs[0], aux_coeffs[1], + aux_coeffs[2], + aux_coeffs[3], aux_coeffs[4], + aux_coeffs[5], + deg_aux, + xs); + + int n_ys = compute_resultant_roots(nt_traits, + base_coeffs[1], base_coeffs[0], + base_coeffs[2], + base_coeffs[4], base_coeffs[3], + base_coeffs[5], + deg_base, + aux_coeffs[1], aux_coeffs[0], + aux_coeffs[2], + aux_coeffs[4], aux_coeffs[3], + aux_coeffs[5], + deg_aux, + ys); + + // Find the intersection point which is nearest the given approximation + // and set it as the endpoint. + found = false; + for (int i = 0; i < n_xs; ++i) { + for (int j = 0; j < n_ys; ++j) { + // Check if the point (xs[i], ys[j]) lies on both conics. + val = nt_traits->convert(base_coeffs[0]) * xs[i]*xs[i] + + nt_traits->convert(base_coeffs[1]) * ys[j]*ys[j] + + nt_traits->convert(base_coeffs[2]) * xs[i]*ys[j] + + nt_traits->convert(base_coeffs[3]) * xs[i] + + nt_traits->convert(base_coeffs[4]) * ys[j] + + nt_traits->convert(base_coeffs[5]); + + if (CGAL::sign(val) != ZERO) continue; + + val = nt_traits->convert(aux_coeffs[0]) * xs[i]*xs[i] + + nt_traits->convert(aux_coeffs[1]) * ys[j]*ys[j] + + nt_traits->convert(aux_coeffs[2]) * xs[i]*ys[j] + + nt_traits->convert(aux_coeffs[3]) * xs[i] + + nt_traits->convert(aux_coeffs[4]) * ys[j] + + nt_traits->convert(aux_coeffs[5]); + + if (CGAL::sign(val) == ZERO) { + // Compute the distance of (xs[i], ys[j]) from the approximated + // endpoint. + double dx, dy; + if (k == 1) { + dx = CGAL::to_double (xs[i] - app_source.x()); + dy = CGAL::to_double (ys[j] - app_source.y()); + } + else { + dx = CGAL::to_double (xs[i] - app_target.x()); + dy = CGAL::to_double (ys[j] - app_target.y()); + } + + curr_dist = dx*dx + dy*dy; + + // Update the endpoint if (xs[i], ys[j]) is the nearest pair so + // far. + if (! found || curr_dist < min_dist) { + if (k == 1) arc.set_source(Point_2(xs[i], ys[j])); + else arc.set_target(Point_2(xs[i], ys[j])); + min_dist = curr_dist; + found = true; + } + } + } + } + + if (! found) { + arc.reset_flags(); // inavlid arc + return arc; + } + } + + // Make sure that the source and the target are not the same. + auto cmp_xy = m_traits.m_alg_kernel->compare_xy_2_object(); + if (cmp_xy(arc.source(), arc.target()) == EQUAL) { + arc.reset_flags(); // inavlid arc + return arc; + } + + // Set the arc properties (no need to compute the orientation). + set(arc, rat_coeffs); + return arc; + } + /*! Return a curve connecting the two given endpoints. * \param p The first point. * \param q The second point. * \pre p and q must not be the same. * \return A segment connecting p and q. */ - Curve_2 operator()(const Point_2& p, const Point_2& q) const - { return Curve_2(p, q); } + Curve_2 operator()(const Point_2& p, const Point_2& q) { + const auto* alg_kernel = m_traits.m_alg_kernel; + CGAL_precondition(alg_kernel->compare_xy_2_object()(p, q) != EQUAL); + + Curve_2 arc; + set_orientation(Curve_2::COLLINEAR); + arc.set_flag(Curve_2::IS_VALID); + arc.set_source(p); + arc.set_target(q); + + // Compose the equation of the underlying line. + const Algebraic& x1 = p.x(); + const Algebraic& y1 = p.y(); + const Algebraic& x2 = q.x(); + const Algebraic& y2 = q.y(); + + // The supporting line is A*x + B*y + C = 0, where: + // A = y2 - y1, B = x1 - x2, C = x2*y1 - x1*y2 + // We use the extra data field to store the equation of this line. + auto* extra_data = new typename Curve_2::Extra_data; + extra_data->a = y2 - y1; + extra_data->b = x1 - x2; + extra_data->c = x2*y1 - x1*y2; + extra_data->side = ZERO; + arc.set_extra_data(extra_data); + return arc; + } }; /*! Obtain a Construct_curve_2 functor object. */ - Construct_curve_2 construct_curve_2_object () const - { return Construct_curve_2(); } + Construct_curve_2 construct_curve_2_object() const + { return Construct_curve_2(*this); } //@} /// \name Functor definitions for the Boolean set-operation traits. @@ -728,6 +1173,370 @@ public: /*! Obtain a Trim_2 functor object. */ Trim_2 trim_2_object() const { return Trim_2(*this); } //@} + + /*! Set the properties of a conic arc (for the usage of the constructors). + * \param rat_coeffs A vector of size 6, storing the rational coefficients + * of x^2, y^2, xy, x, y and the free coefficient resp. + */ + void set(Curve_2& arc, const Rational* rat_coeffs) { + arc.set_flag(Curve_2::IS_VALID); + + // Convert the coefficients vector to an equivalent vector of integer + // coefficients. + Integer int_coeffs[6]; + m_nt_traits->convert_coefficients(rat_coeffs, rat_coeffs + 6, int_coeffs); + + // Check the orientation of conic curve, and negate the conic coefficients + // if its given orientation. + typename Rat_kernel::Conic_2 temp_conic(rat_coeffs[0], rat_coeffs[1], + rat_coeffs[2], rat_coeffs[3], + rat_coeffs[4], rat_coeffs[5]); + + + Integer r, s, t, u, v, w; + if (arc.orientation() == temp_conic.orientation()) { + r = int_coeffs[0]; + s = int_coeffs[1]; + t = int_coeffs[2]; + u = int_coeffs[3]; + v = int_coeffs[4]; + w = int_coeffs[5]; + } + else { + r = -int_coeffs[0]; + s = -int_coeffs[1]; + t = -int_coeffs[2]; + u = -int_coeffs[3]; + v = -int_coeffs[4]; + w = -int_coeffs[5]; + } + arc.set_coefficients(r, s, t, u, v, w); + + const auto& source = arc.source(); + const auto& target = arc.target(); + // Make sure both endpoint lie on the supporting conic. + if (! is_on_supporting_conic(arc, source) || + ! is_on_supporting_conic(arc, target)) + { + arc.reset_flags(); // inavlid arc + } + + // Check whether we have a degree 2 curve. + if ((CGAL::sign(r) != ZERO) || (CGAL::sign(s) != ZERO) || + (CGAL::sign(t) != ZERO)) + { + if (arc.orientation() == COLLINEAR) { + // Make sure the midpoint is on the line pair (thus making sure that + // the two points are not taken from different lines). + Point_2 p_mid = m_alg_kernel->compare_xy_2_object()(source, target); + // if (! is_on_supporting_conic(arc, p_mid)) + if (CGAL::sign((m_nt_traits->convert(r)*p_mid.x() + + m_nt_traits->convert(t)*p_mid.y() + + m_nt_traits->convert(u)) * p_mid.x() + + (m_nt_traits->convert(s)*p_mid.y() + + m_nt_traits->convert(v)) * p_mid.y() + + m_nt_traits->convert(w)) != ZERO) + { + arc.reset_flags(); // inavlid arc + return; + } + + + // We have a segment of a line pair with rational coefficients. + // Compose the equation of the underlying line + // (with algebraic coefficients). + const Algebraic& x1 = source.x(); + const Algebraic& y1 = source.y(); + const Algebraic& x2 = target.x(); + const Algebraic& y2 = target.y(); + + // The supporting line is A*x + B*y + C = 0, where: + // + // A = y2 - y1, B = x1 - x2, C = x2*y1 - x1*y2 + // + // We use the extra dat field to store the equation of this line. + auto* extra_data = new typename Curve_2::Extra_data; + extra_data->a = y2 - y1; + extra_data->b = x1 - x2; + extra_data->c = x2*y1 - x1*y2; + extra_data->side = ZERO; + arc.set_extra_data(extra_data); + } + else { + // The sign of (4rs - t^2) detetmines the conic type: + // - if it is possitive, the conic is an ellipse, + // - if it is negative, the conic is a hyperbola, + // - if it is zero, the conic is a parabola. + CGAL::Sign sign_conic = CGAL::sign(4*r*s - t*t); + + // Build the extra hyperbolic data if necessary + if (sign_conic == NEGATIVE) build_hyperbolic_arc_data(arc); + + if (sign_conic != POSITIVE) { + // In case of a non-degenerate parabola or a hyperbola, make sure + // the arc is not infinite. + Alg_kernel ker; + Point_2 p_mid = ker.construct_midpoint_2_object()(source, target); + Point_2 ps[2]; + + bool finite_at_x = (points_at_x(p_mid, ps) > 0); + bool finite_at_y = (points_at_y(p_mid, ps) > 0); + + if (! finite_at_x && ! finite_at_y) { + arc.reset_flags(); // inavlid arc + return; + } + } + } + } + + + arc.set_flag(Curve_2::IS_VALID); // arc is valid + arc.reset_flag(Curve_2::IS_FULL_CONIC); // not a full conic + } + + /*! Set the properties of a conic arc that is really a full curve + * (that is, an ellipse). + * \param rat_coeffs A vector of size 6, storing the rational coefficients + * of x^2, y^2, xy, x, y and the free coefficient resp. + * \param comp_orient Should we compute the orientation of the given curve. + */ + void set_full(Curve_2& arc, const Rational* rat_coeffs, + const bool& comp_orient) { + // Convert the coefficients vector to an equivalent vector of integer + // coefficients. + Integer int_coeffs[6]; + m_nt_traits->convert_coefficients(rat_coeffs, rat_coeffs + 6, int_coeffs); + + // Check the orientation of conic curve, and negate the conic coefficients + // if its given orientation. + typename Rat_kernel::Conic_2 temp_conic(rat_coeffs[0], rat_coeffs[1], + rat_coeffs[2], rat_coeffs[3], + rat_coeffs[4], rat_coeffs[5]); + const Orientation temp_orient = temp_conic.orientation(); + + if (comp_orient) arc.set_orientation(temp_orient); + + Integer r, s, t, u, v, w; + if (arc.orientation() == temp_orient) { + r = int_coeffs[0]; + s = int_coeffs[1]; + t = int_coeffs[2]; + u = int_coeffs[3]; + v = int_coeffs[4]; + w = int_coeffs[5]; + } + else { + r = -int_coeffs[0]; + s = -int_coeffs[1]; + t = -int_coeffs[2]; + u = -int_coeffs[3]; + v = -int_coeffs[4]; + w = -int_coeffs[5]; + } + + // Make sure the conic is a non-degenerate ellipse: + // The coefficients should satisfy (4rs - t^2) > 0. + const bool is_ellipse = (CGAL::sign(4*r*s - t*t) == POSITIVE); + CGAL_assertion(is_ellipse); + + // We do not have to store any extra data with the arc. + + // Mark that this arc is a full conic curve. + if (is_ellipse) { + arc.set_flag(Curve_2::IS_VALID); + arc.set_flag(Curve_2::IS_FULL_CONIC); + } + else arc.reset_flags(); // inavlid arc + } + + /*! Check whether the given point lies on the supporting conic of the arc. + * \param p The query point. + * \return true if p lies on the supporting conic; (false) otherwise. + */ + bool is_on_supporting_conic(Curve_2& arc, const Point_2& p) const { + // Check whether p satisfies the conic equation. + const Algebraic r = m_nt_traits->convert(arc.r()); + const Algebraic t = m_nt_traits->convert(arc.t()); + const Algebraic u = m_nt_traits->convert(arc.u()); + const Algebraic s = m_nt_traits->convert(arc.s()); + const Algebraic v = m_nt_traits->convert(arc.v()); + const Algebraic w = m_nt_traits->convert(arc.w()); + + // The point must satisfy: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0. + const Algebraic val = + (r*p.x() + t*p.y() + u)*p.x() + (s*p.y() + v)* p.y() + w; + return (CGAL::sign(val) == ZERO); + } + + /*! Check whether the given point is strictly between the source and the + * target (but not any of them). + * The point is assumed to be on the conic's boundary. + * \param p The query point. + * \return true if the point is strictly between the two endpoints, + * (false) if it is not. + */ + bool is_strictly_between_endpoints(const Curve_2& arc, const Point_2& p) const + { + // In case this is a full conic, any point on its boundary is between + // its end points. + if (arc.is_full_conic()) return true; + + // Check if we have extra data available. + const auto* extra_data = arc.extra_data(); + if (extra_data != nullptr) { + if (extra_data->side != ZERO) { + // In case of a hyperbolic arc, make sure the point is located on the + // same branch as the arc. + if (arc.sign_of_extra_data(p.x(), p.y()) != extra_data->side) + return false; + } + else { + // In case we have a segment of a line pair, make sure that p really + // satisfies the equation of the line. + if (arc.sign_of_extra_data(p.x(), p.y()) != ZERO) return false; + } + } + + // Act according to the conic degree. + auto orient_f = m_alg_kernel->orientation_2_object(); + const auto& source = arc.source(); + const auto& target = arc.target(); + if (arc.orientation() == COLLINEAR) { + Comparison_result res1; + Comparison_result res2; + + if (m_alg_kernel->compare_x_2_object()(source, target) == EQUAL) { + // In case of a vertical segment - just check whether the y coordinate + // of p is between those of the source's and of the target's. + auto cmp_y = m_alg_kernel->compare_y_2_object(); + res1 = cmp_y(p, source); + res2 = cmp_y(p, target); + } + else { + // Otherwise, since the segment is x-monotone, just check whether the + // x coordinate of p is between those of the source's and of the + // target's. + auto cmp_x = m_alg_kernel->compare_x_2_object(); + res1 = cmp_x(p, source); + res2 = cmp_x(p, target); + } + + // If p is not in the (open) x-range (or y-range) of the segment, it + // cannot be contained in the segment. + if ((res1 == EQUAL) || (res2 == EQUAL) || (res1 == res2)) return false; + + // Perform an orientation test: This is crucial for segment of line + // pairs, as we want to make sure that p lies on the same line as the + // source and the target. + return (orient_f(source, p, target) == COLLINEAR); + } + else { + // In case of a conic of degree 2, make a decision based on the conic's + // orientation and whether (source,p,target) is a right or a left turn. + if (arc.orientation() == COUNTERCLOCKWISE) + return (orient_f(source, p, target) == LEFT_TURN); + else + return (orient_f(source, p, target) == RIGHT_TURN); + } + } + + /*! Build the data for hyperbolic arc, contaning the characterization of the + * hyperbolic branch the arc is placed on. + */ + void build_hyperbolic_arc_data(Curve_2& arc) { + // Let phi be the rotation angle of the conic from its canonic form. + // We can write: + // + // t + // sin(2*phi) = ----------------------- + // sqrt((r - s)^2 + t^2) + // + // r - s + // cos(2*phi) = ----------------------- + // sqrt((r - s)^2 + t^2) + // + const int or_fact = (arc.orientation() == CLOCKWISE) ? -1 : 1; + const Algebraic r = m_nt_traits->convert(or_fact * arc.r()); + const Algebraic s = m_nt_traits->convert(or_fact * arc.s()); + const Algebraic t = m_nt_traits->convert(or_fact * arc.t()); + const Algebraic cos_2phi = (r - s) / m_nt_traits->sqrt((r-s)*(r-s) + t*t); + const Algebraic zero = 0; + const Algebraic one = 1; + const Algebraic two = 2; + Algebraic sin_phi; + Algebraic cos_phi; + + // Calculate sin(phi) and cos(phi) according to the half-angle formulae: + // + // sin(phi)^2 = 0.5 * (1 - cos(2*phi)) + // cos(phi)^2 = 0.5 * (1 + cos(2*phi)) + Sign sign_t = CGAL::sign(t); + + if (sign_t == ZERO) { + // sin(2*phi) == 0, so phi = 0 or phi = PI/2 + if (CGAL::sign(cos_2phi) == POSITIVE) { + // phi = 0. + sin_phi = zero; + cos_phi = one; + } + else { + // phi = PI/2. + sin_phi = one; + cos_phi = zero; + } + } + else if (sign_t == POSITIVE) { + // sin(2*phi) > 0 so 0 < phi < PI/2. + sin_phi = m_nt_traits->sqrt((one + cos_2phi) / two); + cos_phi = m_nt_traits->sqrt((one - cos_2phi) / two); + } + else { + // sin(2*phi) < 0 so PI/2 < phi < PI. + sin_phi = m_nt_traits->sqrt((one + cos_2phi) / two); + cos_phi = - m_nt_traits->sqrt((one - cos_2phi) / two); + } + + // Calculate the center (x0, y0) of the conic, given by the formulae: + // + // t*v - 2*s*u t*u - 2*r*v + // x0 = ------------- , y0 = ------------- + // 4*r*s - t^2 4*r*s - t^2 + // + // The denominator (4*r*s - t^2) must be negative for hyperbolas. + const Algebraic u = m_nt_traits->convert(or_fact * arc.u()); + const Algebraic v = m_nt_traits->convert(or_fact * arc.v()); + const Algebraic det = 4*r*s - t*t; + Algebraic x0, y0; + + CGAL_assertion(CGAL::sign(det) == NEGATIVE); + + x0 = (t*v - two*s*u) / det; + y0 = (t*u - two*r*v) / det; + + // The axis separating the two branches of the hyperbola is now given by: + // + // cos(phi)*x + sin(phi)*y - (cos(phi)*x0 + sin(phi)*y0) = 0 + // + // We store the equation of this line in the extra data structure and also + // the sign (side of half-plane) our arc occupies with respect to the line. + auto* extra_data = new typename Curve_2::Extra_data; + + extra_data->a = cos_phi; + extra_data->b = sin_phi; + extra_data->c = - (cos_phi*x0 + sin_phi*y0); + + // Make sure that the two endpoints are located on the same branch + // of the hyperbola. + const auto& source = arc.source(); + const auto& target = arc.target(); + extra_data->side = arc.sign_of_extra_data(source.x(), source.y()); + + CGAL_assertion(extra_data->side != ZERO); + CGAL_assertion(extra_data->side == + arc.sign_of_extra_data(target.x(), target.y())); + arc.set_extra_data(extra_data); + } }; #include diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h index 7a68539d074..de483e224ac 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h @@ -121,6 +121,33 @@ protected: { return (m_info & flag_mask(flag)); } //@} + /// \name Setters; only friends have the priviledge to use. + //@{ + + void set_coefficients(Integer r, Integer s, Integer t, + Integer u, Integer v, Integer w) { + + m_r = r; + s = m_s; + t = m_t; + m_u = u; + m_v = v; + m_w = w; + } + + void set_orientation(Orientation orient) { m_orient = orient; } + + void set_endpoints(const Conic_point_2& source, const Conic_point_2& target) { + m_source = source; + m_target = target; + } + + void set_extra_data(Extra_data* extra_data) { + m_extra_data = extra_data; + } + + //@} + public: /// \name Construction and destruction functions. //@{ @@ -404,7 +431,7 @@ public: * \pre The three points must not be collinear. */ _Conic_arc_2(const Rat_point_2& p1, const Rat_point_2& p2, - const Rat_point_2& p3): + const Rat_point_2& p3) : m_info(0), m_extra_data(nullptr) { @@ -587,7 +614,7 @@ public: const Rational& u_1, const Rational& v_1, const Rational& w_1, const Point_2& app_target, const Rational& r_2, const Rational& s_2, const Rational& t_2, - const Rational& u_2, const Rational& v_2, const Rational& w_2): + const Rational& u_2, const Rational& v_2, const Rational& w_2) : m_orient(orient), m_info(0), m_extra_data(nullptr) @@ -812,7 +839,7 @@ public: */ bool is_full_conic() const { return test_flag(IS_FULL_CONIC); } - /*! Get the arc's source. + /*! Obtain the arc's source. * \return The source point. * \pre The arc does not represent a full conic curve. */ @@ -821,7 +848,7 @@ public: return m_source; } - /*! Get the arc's target. + /*! Obtain the arc's target. * \return The target point. * \pre The arc does not represent a full conic curve. */ @@ -830,12 +857,16 @@ public: return m_target; } - /*! Get the orientation of the arc. + /*! Obtain the orientation of the arc. * \return The orientation. */ Orientation orientation() const { return m_orient; } - /*! Get a bounding box for the conic arc. + /*! Obtain the extra data. + */ + const Extra_data* extra_data() const { return m_extra_data(); } + + /*! Obtain a bounding box for the conic arc. * \return The bounding box. */ Bbox_2 bbox() const { From a5a0c049cb1625f28e82501bae10ff20f609fae7 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Mon, 23 May 2022 15:13:45 +0300 Subject: [PATCH 012/105] Continued to move Conic_arc_2 constructors to the traits --- .../include/CGAL/Arr_conic_traits_2.h | 264 ++++++++++++++++-- .../CGAL/Arr_geometry_traits/Conic_arc_2.h | 80 ++---- 2 files changed, 273 insertions(+), 71 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index b32eeda58bb..b36d32fbec3 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -674,14 +674,12 @@ public: // Set the arc to be the full conic (and compute the orientation). Rational rat_coeffs[6]; - rat_coeffs[0] = r; rat_coeffs[1] = s; rat_coeffs[2] = t; rat_coeffs[3] = u; rat_coeffs[4] = v; rat_coeffs[5] = w; - set_full(rat_coeffs, true); } @@ -698,7 +696,7 @@ public: const Orientation& orient, const Point_2& source, const Point_2& target) const { // Make sure that the source and the taget are not the same. - const auto* alg_kernel = m_traits.m_alg_kernel; + const auto alg_kernel = m_traits.m_alg_kernel; CGAL_precondition(alg_kernel->compare_xy_2_object()(source, target) != EQUAL); // Set the arc properties (no need to compute the orientation). @@ -728,8 +726,8 @@ public: const Rational& x3 = p3.x(); const Rational& y3 = p3.y(); - const auto* nt_traits = m_traits.m_nt_traits; - const auto* alg_kernel = m_traits.m_alg_kernel; + const auto nt_traits = m_traits.m_nt_traits; + const auto alg_kernel = m_traits.m_alg_kernel; auto source = Point_2(nt_traits->convert(x1), nt_traits->convert(y1)); auto target = Point_2(nt_traits->convert(x3), nt_traits->convert(y3)); arc.set_enpoints(source, target); @@ -829,7 +827,7 @@ public: const Rational& x5 = p5.x(); const Rational& y5 = p5.y(); - const auto* nt_traits = m_traits.m_nt_traits; + const auto nt_traits = m_traits.m_nt_traits; auto source = Point_2(nt_traits->convert(x1), nt_traits->convert(y1)); auto target = Point_2(nt_traits->convert(x5), nt_traits->convert(y5)); arc.set_endpoints(source, target); @@ -919,7 +917,7 @@ public: rat_coeffs[4] = v; rat_coeffs[5] = w; - const auto* nt_traits = m_traits.m_nt_traits; + const auto nt_traits = m_traits.m_nt_traits; Integer base_coeffs[6]; nt_traits->convert_coefficients(rat_coeffs, rat_coeffs + 6, base_coeffs); @@ -1053,8 +1051,8 @@ public: * \pre p and q must not be the same. * \return A segment connecting p and q. */ - Curve_2 operator()(const Point_2& p, const Point_2& q) { - const auto* alg_kernel = m_traits.m_alg_kernel; + Curve_2 operator()(const Point_2& p, const Point_2& q) const { + const auto alg_kernel = m_traits.m_alg_kernel; CGAL_precondition(alg_kernel->compare_xy_2_object()(p, q) != EQUAL); Curve_2 arc; @@ -1080,6 +1078,96 @@ public: arc.set_extra_data(extra_data); return arc; } + + /*! Construct a conic arc from a given line segment. + * \param seg The line segment with rational endpoints. + */ + Curve_2 operator()(const Rat_segment_2& seg) const { + Curve_2 arc; + arc.set_orientation(COLLINEAR); + + // Set the source and target. + const auto rat_kernel = m_traits.m_rat_kernel; + Rat_point_2 source = rat_kernel->construct_vertex_2_object()(seg, 0); + Rat_point_2 target = rat_kernel->construct_vertex_2_object()(seg, 1); + const Rational& x1 = source.x(); + const Rational& y1 = source.y(); + const Rational& x2 = target.x(); + const Rational& y2 = target.y(); + + const auto nt_traits = m_traits.m_nt_traits; + arc.set_source(Point_2(nt_traits->convert(x1), nt_traits->convert(y1))); + arc.set_target(Point_2(nt_traits->convert(x2), nt_traits->convert(y2))); + + // Make sure that the source and the taget are not the same. + CGAL_precondition(rat_kernel->compare_xy_2_object()(source, target) != + EQUAL); + + // The supporting conic is r=s=t=0, and u*x + v*y + w = 0 should hold + // for both the source (x1,y1) and the target (x2, y2). + const Rational zero(0); + const Rational one(1); + Rational rat_coeffs[6]; + + rat_coeffs[0] = zero; + rat_coeffs[1] = zero; + rat_coeffs[2] = zero; + + if (rat_kernel->compare_x_2_object()(source, target) == EQUAL) { + // The supporting conic is a vertical line, of the form x = CONST. + rat_coeffs[3] = one; + rat_coeffs[4] = zero; + rat_coeffs[5] = -x1; + } + else { + // The supporting line is A*x + B*y + C = 0, where: + // + // A = y2 - y1, B = x1 - x2, C = x2*y1 - x1*y2 + // + rat_coeffs[3] = y2 - y1; + rat_coeffs[4] = x1 - x2; + rat_coeffs[5] = x2*y1 - x1*y2; + } + + // Set the arc properties (no need to compute the orientation). + m_traits.set(arc, rat_coeffs); + return arc; + } + + /*! Construct a conic arc that is a full circle. + * \param circ The circle with rational center and rational squared radius. + */ + Curve_2 operator()(const Rat_circle_2& circ) const { + Curve_2 arc; + arc.set_orientation(CLOCKWISE); + + // Get the circle properties. + const auto rat_kernel = m_traits.m_rat_kernel; + Rat_point_2 center = rat_kernel->construct_center_2_object()(circ); + Rational x0 = center.x(); + Rational y0 = center.y(); + Rational R_sqr = rat_kernel->compute_squared_radius_2_object()(circ); + + // Produce the correponding conic: if the circle center is (x0,y0) + // and its squared radius is R^2, that its equation is: + // x^2 + y^2 - 2*x0*x - 2*y0*y + (x0^2 + y0^2 - R^2) = 0 + // Note that this equation describes a curve with a negative (clockwise) + // orientation. + const Rational zero(0); + const Rational one(1); + const Rational minus_two(-2); + Rational rat_coeffs[6]; + rat_coeffs[0] = one; + rat_coeffs[1] = one; + rat_coeffs[2] = zero; + rat_coeffs[3] = minus_two*x0; + rat_coeffs[4] = minus_two*y0; + rat_coeffs[5] = x0*x0 + y0*y0 - R_sqr; + + // Set the arc to be the full conic (no need to compute the orientation). + m_traits.set_full(arc.rat_coeffs, false); + return arc; + } }; /*! Obtain a Construct_curve_2 functor object. */ @@ -1178,7 +1266,7 @@ public: * \param rat_coeffs A vector of size 6, storing the rational coefficients * of x^2, y^2, xy, x, y and the free coefficient resp. */ - void set(Curve_2& arc, const Rational* rat_coeffs) { + void set(Curve_2& arc, const Rational* rat_coeffs) const { arc.set_flag(Curve_2::IS_VALID); // Convert the coefficients vector to an equivalent vector of integer @@ -1228,7 +1316,8 @@ public: if (arc.orientation() == COLLINEAR) { // Make sure the midpoint is on the line pair (thus making sure that // the two points are not taken from different lines). - Point_2 p_mid = m_alg_kernel->compare_xy_2_object()(source, target); + auto ctr_mid_point = m_alg_kernel->construct_midpoint_2_object(); + Point_2 p_mid = ctr_mid_point(source, target); // if (! is_on_supporting_conic(arc, p_mid)) if (CGAL::sign((m_nt_traits->convert(r)*p_mid.x() + m_nt_traits->convert(t)*p_mid.y() + @@ -1275,12 +1364,12 @@ public: if (sign_conic != POSITIVE) { // In case of a non-degenerate parabola or a hyperbola, make sure // the arc is not infinite. - Alg_kernel ker; - Point_2 p_mid = ker.construct_midpoint_2_object()(source, target); + Point_2 p_mid = + m_alg_kernel->construct_midpoint_2_object()(source, target); Point_2 ps[2]; - bool finite_at_x = (points_at_x(p_mid, ps) > 0); - bool finite_at_y = (points_at_y(p_mid, ps) > 0); + bool finite_at_x = (points_at_x(arc, p_mid, ps) > 0); + bool finite_at_y = (points_at_y(arc, p_mid, ps) > 0); if (! finite_at_x && ! finite_at_y) { arc.reset_flags(); // inavlid arc @@ -1302,7 +1391,7 @@ public: * \param comp_orient Should we compute the orientation of the given curve. */ void set_full(Curve_2& arc, const Rational* rat_coeffs, - const bool& comp_orient) { + const bool& comp_orient) const { // Convert the coefficients vector to an equivalent vector of integer // coefficients. Integer int_coeffs[6]; @@ -1369,6 +1458,21 @@ public: return (CGAL::sign(val) == ZERO); } + /*! Check whether the given point is between the source and the target. + * The point is assumed to be on the conic's boundary. + * \param p The query point. + * \return true if the point is between the two endpoints, + * (false) if it is not. + */ + bool is_between_endpoints(const Curve_2& arc, const Point_2& p) const { + CGAL_precondition(! arc.is_full_conic()); + + // Check if p is one of the endpoints. + auto eq = m_alg_kernel->equal_2_object(); + if (eq(p, arc.source()) || eq(p, arc.target())) return true; + else return (is_strictly_between_endpoints(arc, p)); + } + /*! Check whether the given point is strictly between the source and the * target (but not any of them). * The point is assumed to be on the conic's boundary. @@ -1444,7 +1548,7 @@ public: /*! Build the data for hyperbolic arc, contaning the characterization of the * hyperbolic branch the arc is placed on. */ - void build_hyperbolic_arc_data(Curve_2& arc) { + void build_hyperbolic_arc_data(Curve_2& arc) const { // Let phi be the rotation angle of the conic from its canonic form. // We can write: // @@ -1537,6 +1641,132 @@ public: arc.sign_of_extra_data(target.x(), target.y())); arc.set_extra_data(extra_data); } + + /*! Find the x coordinates of the underlying conic at a given y coordinate. + * \param y The y coordinate. + * \param xs The output x coordinates. + * \pre The vector xs must be allocated at the size of 2. + * \return The number of x coordinates computed (either 0, 1 or 2). + */ + int conic_get_x_coordinates(const Curve_2& arc, + const Algebraic& y, Algebraic* xs) const { + // Solve the quadratic equation for a given y and find the x values: + // r*x^2 + (t*y + u)*x + (s*y^2 + v*y + w) = 0 + Algebraic A = m_nt_traits->convert(arc.r()); + Algebraic B = + m_nt_traits->convert(arc.t())*y + m_nt_traits->convert(arc.u()); + Algebraic C = + (m_nt_traits->convert(arc.s())*y + m_nt_traits->convert(arc.v()))*y + + m_nt_traits->convert(arc.w()); + + return solve_quadratic_equation(A, B, C, xs[0], xs[1]); + } + + /*! Find the y coordinates of the underlying conic at a given x coordinate. + * \param x The x coordinate. + * \param ys The output y coordinates. + * \pre The vector ys must be allocated at the size of 2. + * \return The number of y coordinates computed (either 0, 1 or 2). + */ + int conic_get_y_coordinates(const Curve_2& arc, + const Algebraic& x, Algebraic* ys) const { + // Solve the quadratic equation for a given x and find the y values: + // s*y^2 + (t*x + v)*y + (r*x^2 + u*x + w) = 0 + Algebraic A = m_nt_traits->convert(arc.s()); + Algebraic B = + m_nt_traits->convert(arc.t())*x + m_nt_traits->convert(arc.v()); + Algebraic C = + (m_nt_traits->convert(arc.r())*x + m_nt_traits->convert(arc.u()))*x + + m_nt_traits->convert(arc.w()); + + return solve_quadratic_equation(A, B, C, ys[0], ys[1]); + } + + /*! Solve the given quadratic equation: Ax^2 + B*x + C = 0. + * \param x_minus The root obtained from taking -sqrt(discriminant). + * \param x_plus The root obtained from taking -sqrt(discriminant). + * \return The number of disticnt solutions to the equation. + */ + int solve_quadratic_equation(const Algebraic& A, + const Algebraic& B, + const Algebraic& C, + Algebraic& x_minus, Algebraic& x_plus) const { + // Check if we actually have a linear equation. + if (CGAL::sign(A) == ZERO) { + if (CGAL::sign(B) == ZERO) return 0; + x_minus = x_plus = -C / B; + return 1; + } + + // Compute the discriminant and act according to its sign. + const Algebraic disc = B*B - 4*A*C; + Sign sign_disc = CGAL::sign(disc); + + // Check whether there are no real-valued solutions: + if (sign_disc == NEGATIVE) return 0; + else if (sign_disc == ZERO) { + // One distinct solution: + x_minus = x_plus = -B / (2*A); + return 1; + } + + // Compute the two distinct solutions: + Algebraic _2A = 2*A; + Nt_traits nt_traits; + Algebraic sqrt_disc = m_nt_traits->sqrt(disc); + + x_minus = -(B + sqrt_disc) / _2A; + x_plus = (sqrt_disc - B) / _2A; + return 2; + } + + /*! Find all points on the arc with a given x-coordinate. + * \param p A placeholder for the x-coordinate. + * \param ps The point on the arc at x(p). + * \pre The vector ps should be allocated at the size of 2. + * \return The number of points found. + */ + int points_at_x(const Curve_2& arc, const Point_2& p, Point_2* ps) const { + // Get the y coordinates of the points on the conic. + Algebraic ys[2]; + int n = conic_get_y_coordinates(arc, p.x(), ys); + + // Find all the points that are contained in the arc. + int m = 0; + + for (int i = 0; i < n; ++i) { + ps[m] = Point_2(p.x(), ys[i]); + if (arc.is_full_conic() || is_between_endpoints(arc, ps[m])) ++m; + } + + // Return the number of points on the arc. + CGAL_assertion(m <= 2); + return m; + } + + /*! Find all points on the arc with a given y-coordinate. + * \param p A placeholder for the y-coordinate. + * \param ps The point on the arc at x(p). + * \pre The vector ps should be allocated at the size of 2. + * \return The number of points found. + */ + int points_at_y(const Curve_2& arc, const Point_2& p, Point_2* ps) const { + // Get the y coordinates of the points on the conic. + Algebraic xs[2]; + int n = conic_get_x_coordinates(arc, p.y(), xs); + + // Find all the points that are contained in the arc. + int m = 0; + + for (int i = 0; i < n; ++i) { + ps[m] = Point_2(xs[i], p.y()); + if (arc.is_full_conic() || is_between_endpoints(arc, ps[m])) ++m; + } + + // Return the number of points on the arc. + CGAL_assertion(m <= 2); + return m; + } }; #include diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h index de483e224ac..76a2f846916 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h @@ -61,27 +61,6 @@ public: typedef typename Alg_kernel::Point_2 Point_2; typedef _Conic_point_2 Conic_point_2; -protected: - Integer m_r; // - Integer m_s; // The coefficients of the supporting conic curve: - Integer m_t; // - Integer m_u; // - Integer m_v; // r*x^2 + s*y^2 + t*xy + u*x + v*y +w = 0 . - Integer m_w; // - - Orientation m_orient; // The orientation of the conic. - - // Bit masks for the m_info field. - enum { - IS_VALID = 0, - IS_FULL_CONIC, - LAST_INFO, - }; - - int m_info; // does the arc represent a full conic curve. - Conic_point_2 m_source; // the source of the arc (if not a full curve). - Conic_point_2 m_target; // the target of the arc (if not a full curve). - /*! \struct * For arcs whose base is a hyperbola we store the axis (a*x + b*y + c = 0) * which separates the two bracnes of the hyperbola. We also store the side @@ -97,9 +76,29 @@ protected: Sign side; }; + // Bit masks for the m_info field. + enum { + IS_VALID = 0, + IS_FULL_CONIC, + LAST_INFO, + }; + +protected: + Integer m_r; // + Integer m_s; // The coefficients of the supporting conic curve: + Integer m_t; // + Integer m_u; // + Integer m_v; // r*x^2 + s*y^2 + t*xy + u*x + v*y +w = 0 . + Integer m_w; // + + Orientation m_orient; // The orientation of the conic. + int m_info; // does the arc represent a full conic curve. + Conic_point_2 m_source; // the source of the arc (if not a full curve). + Conic_point_2 m_target; // the target of the arc (if not a full curve). Extra_data* m_extra_data; // The extra data stored with the arc // (may be nullptr). +public: /// \name Flag manipulation functions. //@{ template @@ -864,7 +863,7 @@ public: /*! Obtain the extra data. */ - const Extra_data* extra_data() const { return m_extra_data(); } + const Extra_data* extra_data() const { return m_extra_data; } /*! Obtain a bounding box for the conic arc. * \return The bounding box. @@ -952,37 +951,13 @@ public: /*! Set the source point of the conic arc. * \param ps The new source point. - * \pre The arc is not a full conic curve. - * ps must lie on the supporting conic curve. */ - void set_source(const Point_2& ps) - { - CGAL_precondition(! is_full_conic()); - CGAL_precondition(is_on_supporting_conic(ps)); - CGAL_precondition(Alg_kernel().orientation_2_object() - (m_source, ps, m_target) == m_orient || - Alg_kernel().orientation_2_object() - (ps, m_source, m_target) == m_orient); - - m_source = ps; - } + void set_source(const Point_2& ps) { m_source = ps; } /*! Set the target point of the conic arc. * \param pt The new source point. - * \pre The arc is not a full conic curve. - * pt must lie on the supporting conic curve. */ - void set_target(const Point_2& pt) - { - CGAL_precondition(! is_full_conic()); - CGAL_precondition(is_on_supporting_conic(pt)); - CGAL_precondition(Alg_kernel().orientation_2_object() - (m_source, pt, m_target) == m_orient || - Alg_kernel().orientation_2_object() - (m_source, m_target, pt) == m_orient); - - m_target = pt; - } + void set_target(const Point_2& pt) { m_target = pt; } //@} @@ -1369,7 +1344,7 @@ private: } //@} -protected: +public: /// \name Auxiliary functions. //@{ @@ -1381,15 +1356,12 @@ protected: */ Sign sign_of_extra_data(const Algebraic& px, const Algebraic& py) const { CGAL_assertion(m_extra_data != nullptr); - if (m_extra_data == nullptr) return ZERO; - - Algebraic val = (m_extra_data->a*px + m_extra_data->b*py + - m_extra_data->c); - + Algebraic val = m_extra_data->a*px + m_extra_data->b*py + m_extra_data->c; return CGAL::sign(val); } +protected: /*! Check whether the given point lies on the supporting conic of the arc. * \param p The query point. * \return true if p lies on the supporting conic; (false) otherwise. From 74755488323bcf921080cdffb30c8f8c9f80906f Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 25 May 2022 10:48:01 +0300 Subject: [PATCH 013/105] Enhanced --- .../examples/Arrangement_on_surface_2/draw_arr.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/draw_arr.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/draw_arr.cpp index ba20b15dc92..757035b98e5 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/draw_arr.cpp +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/draw_arr.cpp @@ -18,6 +18,8 @@ int main() { CGAL::insert(arr, ctr_xcv(Point(1,-1), Point(1,1))); CGAL::insert(arr, ctr_xcv(Point(1,1), Point(-1,1))); CGAL::insert(arr, ctr_xcv(Point(-1,1), Point(-1,-1))); + CGAL::insert(arr, ctr_xcv(Point(-2,-1), Point(-1,-1))); + CGAL::insert(arr, ctr_xcv(Point(2,-1), Point(1,-1))); CGAL::draw(arr); From 8890a779eb8d36dd35f8c4f9ec97c705bb9286bf Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 25 May 2022 10:48:14 +0300 Subject: [PATCH 014/105] ixed drawing of 2D arrangements --- .../include/CGAL/draw_arrangement_2.h | 166 ++++++++++++++---- 1 file changed, 130 insertions(+), 36 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h index 9b52b282c74..70dc3b61cc5 100644 --- a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h +++ b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h @@ -6,44 +6,69 @@ #include #include #include +#include namespace CGAL { // Viewer class for Polygon_2 -template -class Arr_2_viewer_qt : public Basic_viewer_qt { +template +class Arr_2_basic_viewer_qt : public Basic_viewer_qt { + typedef GeometryTraits_2 Gt; + typedef CGAL::Arrangement_2 Arr; typedef Basic_viewer_qt Base; - typedef Arrangement_2 Arr; typedef typename Arr::Point_2 Point; + typedef typename Arr::Vertex_const_handle Vertex_const_handle; + typedef typename Arr::Halfedge_const_handle Halfedge_const_handle; typedef typename Arr::Face_const_handle Face_const_handle; + typedef typename Arr::Ccb_halfedge_const_circulator + Ccb_halfedge_const_circulator; public: /// Construct the viewer. /// @param arr the arrangement to view /// @param title the title of the window - Arr_2_viewer_qt(QWidget* parent, const Arr& arr, - const char* title = "2D Arrangement Basic Viewer") : + Arr_2_basic_viewer_qt(QWidget* parent, const Arr& arr, + const char* title = "2D Arrangement Basic Viewer") : // First draw: vertices; edges, faces; multi-color; no inverse normal Base(parent, title, true, true, true, false, false), m_arr(arr) - { add_elements(); } + {} + + //! + void add_elements() { + clear(); + if (m_arr.is_empty()) return; + CGAL::IO::Color c(75,160,255); + for (auto it = m_arr.unbounded_faces_begin(); + it != m_arr.unbounded_faces_end(); ++it) + add_face(it, c); + for (auto it = m_arr.edges_begin(); it != m_arr.edges_end(); ++it) + add_edge(it); + for (auto it = m_arr.vertices_begin(); it != m_arr.vertices_end(); ++it) + add_vertex(it); + } protected: //! - void add_ccb(typename Arr::Ccb_halfedge_const_circulator circ, bool has_area = true) { + virtual void add_ccb(Ccb_halfedge_const_circulator circ) { + std::cout << "1 add_ccb\n"; typename Arr::Ccb_halfedge_const_circulator curr = circ; - do { - typename Arr::Halfedge_const_handle e = curr; - add_segment(e->source()->point(), e->target()->point()); - add_point(e->source()->point()); - if (has_area) add_point_in_face(e->source()->point()); - } while (++curr != circ); + do this->add_point_in_face(curr->source()->point()); + while (++curr != circ); } //! - void add_face(Face_const_handle face, CGAL::IO::Color c) { + virtual void add_edge(Halfedge_const_handle e) + { this->add_segment(e->source()->point(), e->target()->point()); } + + //! + virtual void add_vertex(Vertex_const_handle v) + { this->add_point(v->point()); } + + //! + void add_face(Face_const_handle face, CGAL::IO::Color color) { if (! face->is_unbounded()) { - face_begin(c); + face_begin(color); add_ccb(face->outer_ccb()); for (auto iv = face->isolated_vertices_begin(); iv != face->isolated_vertices_end(); ++iv) @@ -51,28 +76,21 @@ protected: face_end(); } - std::map visited; - for (auto it = face->inner_ccbs_begin(); it != face->inner_ccbs_end(); ++it) { - auto new_face = (*it)->twin()->face(); - if (new_face == face) { - add_ccb(*it, false); - continue; - } - if (visited.find(new_face) != visited.end()) continue; - visited[new_face] = true; - add_face(new_face, c); + for (auto it = face->inner_ccbs_begin(); it != face->inner_ccbs_end(); ++it) + { + std::map visited; + auto curr = *it; + do { + auto new_face = curr->twin()->face(); + if (new_face == face) continue; + if (visited.find(new_face) == visited.end()) { + visited[new_face] = true; + add_face(new_face, color); + } + } while (++curr != *it); } } - //! - void add_elements() { - clear(); - if (m_arr.is_empty()) return; - CGAL::IO::Color c(75,160,255); - for (auto it = m_arr.unbounded_faces_begin(); it != m_arr.unbounded_faces_end(); ++it) - add_face(it, c); - } - //! virtual void keyPressEvent(QKeyEvent* e) { // Test key pressed: @@ -90,9 +108,84 @@ protected: } protected: - const Arrangement_2& m_arr; + //! The arrangement to draw + const Arr& m_arr; }; +//! Basic viewer of a 2D arrangement. +template +class Arr_2_viewer_qt : public Arr_2_basic_viewer_qt { +public: + typedef GeometryTraits_2 Gt; + typedef CGAL::Arrangement_2 Arr; + typedef Arr_2_basic_viewer_qt Base; + typedef typename Arr::Point_2 Point; + typedef typename Arr::Halfedge_const_handle Halfedge_const_handle; + typedef typename Arr::Face_const_handle Face_const_handle; + typedef typename Arr::Ccb_halfedge_const_circulator + Ccb_halfedge_const_circulator; + + /// Construct the viewer. + /// @param arr the arrangement to view + /// @param title the title of the window + Arr_2_viewer_qt(QWidget* parent, const Arr& arr, + const char* title = "2D Arrangement Basic Viewer") : + Base(parent, arr, title) + {} +}; + +//! +template +class Arr_2_viewer_qt, + Dcel> : + public Arr_2_basic_viewer_qt, Dcel> { +public: + typedef Arr_conic_traits_2 Gt; + typedef CGAL::Arrangement_2 Arr; + typedef Arr_2_basic_viewer_qt Base; + typedef typename Arr::Point_2 Point; + typedef typename Arr::Halfedge_const_handle Halfedge_const_handle; + typedef typename Arr::Face_const_handle Face_const_handle; + typedef typename Arr::Ccb_halfedge_const_circulator + Ccb_halfedge_const_circulator; + + /// Construct the viewer. + /// @param arr the arrangement to view + /// @param title the title of the window + Arr_2_viewer_qt(QWidget* parent, const Arr& arr, + const char* title = "2D Arrangement Basic Viewer") : + Base(parent, arr, title) + {} + + //! + virtual void add_ccb(Ccb_halfedge_const_circulator circ) { + const auto* traits = this->m_arr.geometry_traits(); + auto approx = traits->approximate_2_object(); + typename Arr::Ccb_halfedge_const_circulator curr = circ; + do { + std::vector polyline; + approx(curr->curve(), 10, std::back_inserter(polyline)); + for (const auto& p : polyline) this->add_point_in_face(p); + } while (++curr != circ); + } + + //! + virtual void add_edge(Halfedge_const_handle e) { + const auto* traits = this->m_arr.geometry_traits(); + auto approx = traits->approximate_2_object(); + std::vector polyline; + approx(e->curve(), 10, std::back_inserter(polyline)); + + auto it = polyline.begin(); + auto prev = it++; + for (; it != polyline.end(); prev = it++) + this->add_segment(*prev, *it); + } +}; + +//! template void draw(const CGAL::Arrangement_2& arr, const char* title = "2D Arrangement Basic Viewer") { @@ -104,7 +197,8 @@ void draw(const CGAL::Arrangement_2& arr, int argc = 1; const char* argv[2] = {"t2_viewer", nullptr}; QApplication app(argc, const_cast(argv)); - Arr_2_viewer_qtmainwindow(app.activeWindow(), arr, title); + Arr_2_viewer_qt mainwindow(app.activeWindow(), arr, title); + mainwindow.add_elements(); mainwindow.show(); app.exec(); } From ac0ea63bbeab1afdda46195a910e7d5ace2e7c33 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 25 May 2022 10:48:55 +0300 Subject: [PATCH 015/105] Cleaned up --- .../Arr_geometry_traits/Conic_x_monotone_arc_2.h | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h index 5de01b56875..ed59662b14f 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h @@ -1033,6 +1033,12 @@ public: bool is_upper() const { return test_flag(FACING_UP); } bool is_lower() const { return test_flag(FACING_DOWN); } + + /*! Check whether the arc is a special segment connecting two algebraic + * endpoints (and has no undelying integer conic coefficients). + */ + bool is_special_segment() const { return test_flag(IS_SPECIAL_SEGMENT); } + //@} private: @@ -1147,12 +1153,6 @@ private: else if (res == SMALLER) set_flag(FACING_DOWN); } - /*! Check if the arc is a special segment connecting two algebraic endpoints - * (and has no undelying integer conic coefficients). - */ - bool is_special_segment() const - { return test_flag(IS_SPECIAL_SEGMENT); } - /*! Check whether the given point lies on the supporting conic of the arc. * \param px The x-coordinate of query point. * \param py The y-coordinate of query point. @@ -1461,7 +1461,6 @@ private: * \return Whether we found an overlap. */ bool compute_overlap(const Self& arc, Self& overlap) const { - std::cout << "compute_overlap()\n"; // Check if the two arcs are identical. if (equals(arc)) { overlap = arc; From 151132c88e06b5e3349a6bf5b90c459e3b28e2c0 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 25 May 2022 10:49:32 +0300 Subject: [PATCH 016/105] Fixed computation of approximate polyline --- .../Arrangement_on_surface_2/conics.cpp | 20 ++-- .../include/CGAL/Arr_conic_traits_2.h | 109 +++++++++++++++++- 2 files changed, 117 insertions(+), 12 deletions(-) diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conics.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conics.cpp index 6720bb7a8d2..a1ee7ec3102 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conics.cpp +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conics.cpp @@ -10,7 +10,9 @@ #include "arr_print.h" int main() { - Arrangement arr; + Traits traits; + Arrangement arr(&traits); + auto ctr_cv = traits.construct_curve_2_object(); #if 0 // Insert a hyperbolic arc (C1), supported by the hyperbola y = 1/x @@ -18,26 +20,28 @@ int main() { // The arc is counterclockwise oriented. insert(arr, Conic_arc(0, 0, 1, 0, 0, -1, CGAL::COUNTERCLOCKWISE, Point(Rational(1,4), 4), Point(2, Rational(1,2)))); +#endif // Insert a full ellipse (C2), which is (x/4)^2 + (y/2)^2 = 0 rotated by // phi = 36.87 degrees (such that sin(phi) = 0.6, cos(phi) = 0.8), // yielding: 58x^2 + 72y^2 - 48xy - 360 = 0. insert(arr, Conic_arc(58, 72, -48, 0, 0, -360)); -#endif - - // Insert the segment (C3) (1, 1) -- (0, -3). - insert(arr, Conic_arc(Rat_segment(Rat_point(1, 1), Rat_point(0, -3)))); #if 0 + // Insert the segment (C3) (1, 1) -- (0, -3). + Conic_arc c3 = ctr_cv(Rat_segment(Rat_point(1, 1), Rat_point(0, -3))); + insert(arr, c3); + // Insert a circular arc (C4) supported by the circle x^2 + y^2 = 5^2, // with (-3, 4) and (4, 3) as its endpoints. We want the arc to be // clockwise-oriented, so it passes through (0, 5) as well. Conic_arc c4(Rat_point(-3, 4), Rat_point(0, 5), Rat_point(4, 3)); insert(arr, c4); -#endif // Insert a full unit circle (C5) that is centered at (0, 4). - insert(arr, Conic_arc(Rat_circle(Rat_point(0,4), 1))); + Conic_arc c5(Conic_arc(Rat_circle(Rat_point(0,4), 1))); + insert(arr, c5); +#endif #if 0 // Insert a parabolic arc (C6) supported by the parabola y = -x^2 with @@ -53,7 +57,9 @@ int main() { 0, 0, 0, 0, 1, 2); // the line: y = -2. insert(arr, c6); +#endif +#if 0 // Insert the right half of the circle centered at (4, 2.5) whose radius // is 1/2 (therefore its squared radius is 1/4) (C7). Rat_circle circ7(Rat_point(4, Rational(5,2)), Rational(1,4)); diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index b36d32fbec3..792fee1bab5 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -25,7 +25,9 @@ #include #include #include +#include +#include #include #include #include @@ -601,11 +603,13 @@ public: /// \name Functor definitions for the landmarks point-location strategy. //@{ - typedef double Approximate_number_type; + using Approximate_number_type = double; + using Approximate_kernel = CGAL::Cartesian; + using Approximate_point_2 = Approximate_kernel::Point_2; class Approximate_2 { public: - /*! Return an approximation of a point coordinate. + /*! Obtain an approximation of a point coordinate. * \param p The exact point. * \param i The coordinate index (either 0 or 1). * \pre i is either 0 or 1. @@ -613,16 +617,111 @@ public: * approximation of p's y-coordinate (if i == 1). */ Approximate_number_type operator()(const Point_2& p, int i) const { - CGAL_precondition(i == 0 || i == 1); + CGAL_precondition((i == 0) || (i == 1)); if (i == 0) return CGAL::to_double(p.x()); else return CGAL::to_double(p.y()); } + + /*! Obtain an approximation of a point. + */ + Approximate_point_2 operator()(const Point_2& p) const + { return std::make_pair(operator()(p, 0), operator()(p, 1)); } + + /*! Obtain an approximation of an x-monotone curve. + */ + template + OutputIterator operator()(const X_monotone_curve_2& arc, size_t size, + OutputIterator oi) const { + auto xs = CGAL::to_double(arc.source().x()); + auto ys = CGAL::to_double(arc.source().y()); + auto xt = CGAL::to_double(arc.target().x()); + auto yt = CGAL::to_double(arc.target().y()); + if (arc.orientation() == COLLINEAR) { + *oi++ = Approximate_point_2(xs, ys); + *oi++ = Approximate_point_2(xt, yt); + return oi; + } + auto r = CGAL::to_double(arc.r()); + auto s = CGAL::to_double(arc.s()); + auto t = CGAL::to_double(arc.t()); + auto u = CGAL::to_double(arc.u()); + auto v = CGAL::to_double(arc.v()); + auto w = CGAL::to_double(arc.w()); + std::cout << r << "," << s << "," << t << "," << u << "," << v << "," << w + << std::endl; + { + // Compute the cos and sin of the rotation angle + // In case of a circle, cost == 1 and sint = 0 + double cost(1), sint(0); + + if (r != s) { + auto tan_2t = t / (r - s); + auto cos_2t = std::sqrt(1 / (tan_2t*tan_2t + 1)); + cost = std::sqrt((1 + cos_2t) / 2); + sint = std::sqrt((1 - cos_2t) / 2); + } + std::cout << "sint, cost: " << sint << "," << cost << std::endl; + + // Compute the coefficients of the unrotated ellipse + auto r_m = r * cost*cost + t*cost*sint + s*sint*sint; + auto t_m = 0; + auto s_m = r * sint*sint - t*cost*sint + s*cost*cost; + auto u_m = u*cost + v*sint; + auto v_m = - u*sint + v*cost; + auto w_m = w; + + std::cout << r_m << "," << s_m << "," << t_m << "," + << u_m << "," << v_m << "," << w_m << std::endl; + + // Compute the center of the inversly rotated ellipse: + auto cx_m = -u_m / (2*r_m); + auto cy_m = -v_m / (2*s_m); + + // Compute the radi of the ellipse: + auto numerator = -4*w_m*r_m*s_m + s_m*u_m*u_m + r_m*v_m*v_m; + auto a = std::sqrt(numerator / (4*r_m*r_m*s_m)); + auto b = std::sqrt(numerator / (4*r_m*s_m*s_m)); + std::cout << "a, b: " << a << "," << b << std::endl; + + // Compute the center (cx,cy) of the ellipse, rotating back: + auto cx = cx_m*cost - cy_m*sint; + auto cy = cx_m*sint + cy_m*cost; + std::cout << "center: " << cx << "," << cy << std::endl; + + // Compute the parameters ts and tt such that + // source == (x(ts),y(ts)), and + // target == (x(tt),y(tt)) + auto xds = xs - cx; + auto yds = ys - cy; + auto ts = std::atan2(a*(cost*yds - sint*xds),b*(sint*yds + cost*xds)); + auto xdt = xt - cx; + auto ydt = yt - cy; + auto tt = std::atan2(a*(cost*ydt - sint*xdt),b*(sint*ydt + cost*xdt)); + + auto delta = std::abs(tt - ts) / (size-1); + double t((arc.orientation() == COUNTERCLOCKWISE) ? ts : tt); + + *oi++ = (arc.orientation() == COUNTERCLOCKWISE) ? + Approximate_point_2(xs, ys) : Approximate_point_2(xt, yt); + t += delta; + for (size_t i = 1; i < size-1; ++i) { + auto x = a*std::cos(t)*cost - b*std::sin(t)*sint + cx; + auto y = a*std::cos(t)*sint + b*std::sin(t)*cost + cy; + std::cout << "t, (x, y): " << t << ", (" << x << "," << y << ")" + << std::endl; + *oi++ = Approximate_point_2(x, y); + t += delta; + } + *oi++ = (arc.orientation() == COUNTERCLOCKWISE) ? + Approximate_point_2(xt, yt) : Approximate_point_2(xs, ys); + } + return oi; + } }; /*! Obtain an Approximate_2 functor object. */ - Approximate_2 approximate_2_object () const - { return Approximate_2(); } + Approximate_2 approximate_2_object() const { return Approximate_2(); } //! Functor class Construct_x_monotone_curve_2 { From 986746b1dd0cc2255fc8d78117a5a92722f129c2 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Thu, 26 May 2022 00:06:57 +0300 Subject: [PATCH 017/105] Fixed arrangement basic drawing code --- .../include/CGAL/Arr_conic_traits_2.h | 35 +++++++-- .../include/CGAL/draw_arrangement_2.h | 71 +++++++++++++++---- 2 files changed, 88 insertions(+), 18 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index 792fee1bab5..d98b2832424 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -27,6 +27,8 @@ #include #include +#include + #include #include #include @@ -642,6 +644,10 @@ public: *oi++ = Approximate_point_2(xt, yt); return oi; } + if (arc.orientation() == CLOCKWISE) { + std::swap(xs, xt); + std::swap(ys, yt); + } auto r = CGAL::to_double(arc.r()); auto s = CGAL::to_double(arc.s()); auto t = CGAL::to_double(arc.t()); @@ -650,6 +656,9 @@ public: auto w = CGAL::to_double(arc.w()); std::cout << r << "," << s << "," << t << "," << u << "," << v << "," << w << std::endl; + std::cout << "curve: (" << xs << "," << ys + << ") => (" << xt << "," << yt << ")" + << std::endl; { // Compute the cos and sin of the rotation angle // In case of a circle, cost == 1 and sint = 0 @@ -695,15 +704,30 @@ public: auto xds = xs - cx; auto yds = ys - cy; auto ts = std::atan2(a*(cost*yds - sint*xds),b*(sint*yds + cost*xds)); + if (ts < 0) ts += 2*M_PI; auto xdt = xt - cx; auto ydt = yt - cy; auto tt = std::atan2(a*(cost*ydt - sint*xdt),b*(sint*ydt + cost*xdt)); + std::cout << "xdt, ydt, tt: " << xdt << "," << ydt << ", " << tt << std::endl; + if (tt < 0) tt += 2*M_PI; + std::cout << "ts,tt: " << ts << "," << tt << std::endl; - auto delta = std::abs(tt - ts) / (size-1); - double t((arc.orientation() == COUNTERCLOCKWISE) ? ts : tt); + namespace bm = boost::math; + auto ratio = b/a; + auto k = 1 - (ratio*ratio); + auto ps = std::atan2(b*std::tan(ts), a); + if (ps < 0) ps += 2*M_PI; + auto ds = a*bm::ellint_2(k, ps); + auto pt = std::atan2(b*std::tan(tt), a); + if (pt < 0) pt += 2*M_PI; + auto dt = a*bm::ellint_2(k, pt); + std::cout << "ps,pt: " << ps << ", " << pt << std::endl; + std::cout << "ds,dt: " << ds << ", " << dt << std::endl; - *oi++ = (arc.orientation() == COUNTERCLOCKWISE) ? - Approximate_point_2(xs, ys) : Approximate_point_2(xt, yt); + if (tt < ts) tt += 2*M_PI; + auto delta = (tt - ts) / (size-1); + auto t(ts); + *oi++ = Approximate_point_2(xs, ys); t += delta; for (size_t i = 1; i < size-1; ++i) { auto x = a*std::cos(t)*cost - b*std::sin(t)*sint + cx; @@ -713,8 +737,7 @@ public: *oi++ = Approximate_point_2(x, y); t += delta; } - *oi++ = (arc.orientation() == COUNTERCLOCKWISE) ? - Approximate_point_2(xt, yt) : Approximate_point_2(xs, ys); + *oi++ = Approximate_point_2(xt, yt); } return oi; } diff --git a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h index 70dc3b61cc5..7870c111562 100644 --- a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h +++ b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h @@ -1,7 +1,7 @@ #ifndef CGAL_DRAW_ARRANGEMENT_2_H #define CGAL_DRAW_ARRANGEMENT_2_H -#include +#include #include #include @@ -42,8 +42,12 @@ public: for (auto it = m_arr.unbounded_faces_begin(); it != m_arr.unbounded_faces_end(); ++it) add_face(it, c); + + // Add edges that do not separe faces. for (auto it = m_arr.edges_begin(); it != m_arr.edges_end(); ++it) - add_edge(it); + if (it->face() == it->twin()->face()) add_edge(it); + + // Add all points for (auto it = m_arr.vertices_begin(); it != m_arr.vertices_end(); ++it) add_vertex(it); } @@ -51,10 +55,11 @@ public: protected: //! virtual void add_ccb(Ccb_halfedge_const_circulator circ) { - std::cout << "1 add_ccb\n"; - typename Arr::Ccb_halfedge_const_circulator curr = circ; - do this->add_point_in_face(curr->source()->point()); - while (++curr != circ); + auto curr = circ; + do { + this->add_point_in_face(curr->source()->point()); + add_edge(curr); + } while (++curr != circ); } //! @@ -78,7 +83,7 @@ protected: for (auto it = face->inner_ccbs_begin(); it != face->inner_ccbs_end(); ++it) { - std::map visited; + std::unordered_map visited; auto curr = *it; do { auto new_face = curr->twin()->face(); @@ -163,12 +168,55 @@ public: virtual void add_ccb(Ccb_halfedge_const_circulator circ) { const auto* traits = this->m_arr.geometry_traits(); auto approx = traits->approximate_2_object(); - typename Arr::Ccb_halfedge_const_circulator curr = circ; + auto cmp_xy = traits->compare_xy_2_object(); + auto cmp_y = traits->compare_y_at_x_right_2_object(); + + // Find the first halfedge directed from left to right + auto curr = circ; + do if (curr->direction() == CGAL::ARR_LEFT_TO_RIGHT) break; + while (++curr != circ); + Halfedge_const_handle ext = curr; + + // Find the halfedge incident to the lexicographically smallest vertex, + // such that there is no other halfedge underneath. do { + // Discard edges not directed from left to right: + if (curr->direction() != CGAL::ARR_LEFT_TO_RIGHT) continue; + + + auto res = cmp_xy(curr->source()->point(), ext->source()->point()); + + // Discard the edges inciden to a point strictly larger than the point + // incident to the stored extreme halfedge: + if (res == LARGER) continue; + + // Store the edge inciden to a point strictly smaller: + if (res == SMALLER) { + ext = curr; + continue; + } + + // The incident points are equal; compare the halfedges themselves: + if (cmp_y(curr->curve(), ext->curve(), curr->source()->point()) == + SMALLER) + ext = curr; + } while (++curr != circ); + + // Iterate, starting from the lexicographically smallest vertex + curr = ext; + do { + while (curr->face() == curr->twin()->face()) + curr = curr->twin()->next(); std::vector polyline; approx(curr->curve(), 10, std::back_inserter(polyline)); - for (const auto& p : polyline) this->add_point_in_face(p); - } while (++curr != circ); + auto it = polyline.begin(); + auto prev = it++; + for (; it != polyline.end(); prev = it++) { + this->add_segment(*prev, *it); + this->add_point_in_face(*prev); + } + curr = curr->next(); + } while (curr != ext); } //! @@ -180,8 +228,7 @@ public: auto it = polyline.begin(); auto prev = it++; - for (; it != polyline.end(); prev = it++) - this->add_segment(*prev, *it); + for (; it != polyline.end(); prev = it++) this->add_segment(*prev, *it); } }; From f2b2005102b2fb12a7d6881019d0582f49165d99 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Thu, 26 May 2022 11:48:32 +0300 Subject: [PATCH 018/105] Enhanced --- .../examples/Arrangement_on_surface_2/draw_arr.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/draw_arr.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/draw_arr.cpp index 757035b98e5..d43858da296 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/draw_arr.cpp +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/draw_arr.cpp @@ -14,12 +14,20 @@ int main() { Arrangement_2 arr(&traits); auto ctr_xcv = traits.construct_x_monotone_curve_2_object(); + CGAL::insert(arr, ctr_xcv(Point(-2,-2), Point(2,-2))); + CGAL::insert(arr, ctr_xcv(Point(2,-2), Point(2,2))); + CGAL::insert(arr, ctr_xcv(Point(2,2), Point(-2,2))); + CGAL::insert(arr, ctr_xcv(Point(-2,2), Point(-2,-2))); + CGAL::insert(arr, ctr_xcv(Point(-1,-1), Point(1,-1))); CGAL::insert(arr, ctr_xcv(Point(1,-1), Point(1,1))); CGAL::insert(arr, ctr_xcv(Point(1,1), Point(-1,1))); CGAL::insert(arr, ctr_xcv(Point(-1,1), Point(-1,-1))); - CGAL::insert(arr, ctr_xcv(Point(-2,-1), Point(-1,-1))); - CGAL::insert(arr, ctr_xcv(Point(2,-1), Point(1,-1))); + + CGAL::insert(arr, ctr_xcv(Point(-2,-2), Point(-2,-4))); + CGAL::insert(arr, ctr_xcv(Point(2,-2), Point(4,-2))); + + CGAL::insert(arr, ctr_xcv(Point(0,0), Point(0,-3))); CGAL::draw(arr); From 1bb77e8ba9b92e7c7aa43d0810c6518a5e2b8d02 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Thu, 26 May 2022 11:48:39 +0300 Subject: [PATCH 019/105] Fixed drawing 2d arrangements --- .../include/CGAL/draw_arrangement_2.h | 280 ++++++++++-------- 1 file changed, 158 insertions(+), 122 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h index 7870c111562..64155dabc4b 100644 --- a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h +++ b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h @@ -2,6 +2,7 @@ #define CGAL_DRAW_ARRANGEMENT_2_H #include +#include #include #include @@ -17,6 +18,7 @@ class Arr_2_basic_viewer_qt : public Basic_viewer_qt { typedef CGAL::Arrangement_2 Arr; typedef Basic_viewer_qt Base; typedef typename Arr::Point_2 Point; + typedef typename Arr::X_monotone_curve_2 X_monotone_curve; typedef typename Arr::Vertex_const_handle Vertex_const_handle; typedef typename Arr::Halfedge_const_handle Halfedge_const_handle; typedef typename Arr::Face_const_handle Face_const_handle; @@ -38,136 +40,25 @@ public: void add_elements() { clear(); if (m_arr.is_empty()) return; - CGAL::IO::Color c(75,160,255); for (auto it = m_arr.unbounded_faces_begin(); it != m_arr.unbounded_faces_end(); ++it) - add_face(it, c); + add_face(it, Face_const_handle()); // Add edges that do not separe faces. for (auto it = m_arr.edges_begin(); it != m_arr.edges_end(); ++it) - if (it->face() == it->twin()->face()) add_edge(it); + if (it->face() == it->twin()->face()) draw_curve(it->curve()); // Add all points for (auto it = m_arr.vertices_begin(); it != m_arr.vertices_end(); ++it) - add_vertex(it); + draw_point(it->point()); } protected: - //! - virtual void add_ccb(Ccb_halfedge_const_circulator circ) { - auto curr = circ; - do { - this->add_point_in_face(curr->source()->point()); - add_edge(curr); - } while (++curr != circ); - } - - //! - virtual void add_edge(Halfedge_const_handle e) - { this->add_segment(e->source()->point(), e->target()->point()); } - - //! - virtual void add_vertex(Vertex_const_handle v) - { this->add_point(v->point()); } - - //! - void add_face(Face_const_handle face, CGAL::IO::Color color) { - if (! face->is_unbounded()) { - face_begin(color); - add_ccb(face->outer_ccb()); - for (auto iv = face->isolated_vertices_begin(); - iv != face->isolated_vertices_end(); ++iv) - add_point(iv->point()); - face_end(); - } - - for (auto it = face->inner_ccbs_begin(); it != face->inner_ccbs_end(); ++it) - { - std::unordered_map visited; - auto curr = *it; - do { - auto new_face = curr->twin()->face(); - if (new_face == face) continue; - if (visited.find(new_face) == visited.end()) { - visited[new_face] = true; - add_face(new_face, color); - } - } while (++curr != *it); - } - } - - //! - virtual void keyPressEvent(QKeyEvent* e) { - // Test key pressed: - // const ::Qt::KeyboardModifiers modifiers = e->modifiers(); - // if ((e->key()==Qt::Key_PageUp) && (modifiers==Qt::NoButton)) { ... } - - // Call: * add_elements() if the model changed, followed by - // * redraw() if some viewing parameters changed that implies some - // modifications of the buffers - // (eg. type of normal, color/mono) - // * update() just to update the drawing - - // Call the base method to process others/classicals key - Base::keyPressEvent(e); - } - -protected: - //! The arrangement to draw - const Arr& m_arr; -}; - -//! Basic viewer of a 2D arrangement. -template -class Arr_2_viewer_qt : public Arr_2_basic_viewer_qt { -public: - typedef GeometryTraits_2 Gt; - typedef CGAL::Arrangement_2 Arr; - typedef Arr_2_basic_viewer_qt Base; - typedef typename Arr::Point_2 Point; - typedef typename Arr::Halfedge_const_handle Halfedge_const_handle; - typedef typename Arr::Face_const_handle Face_const_handle; - typedef typename Arr::Ccb_halfedge_const_circulator - Ccb_halfedge_const_circulator; - - /// Construct the viewer. - /// @param arr the arrangement to view - /// @param title the title of the window - Arr_2_viewer_qt(QWidget* parent, const Arr& arr, - const char* title = "2D Arrangement Basic Viewer") : - Base(parent, arr, title) - {} -}; - -//! -template -class Arr_2_viewer_qt, - Dcel> : - public Arr_2_basic_viewer_qt, Dcel> { -public: - typedef Arr_conic_traits_2 Gt; - typedef CGAL::Arrangement_2 Arr; - typedef Arr_2_basic_viewer_qt Base; - typedef typename Arr::Point_2 Point; - typedef typename Arr::Halfedge_const_handle Halfedge_const_handle; - typedef typename Arr::Face_const_handle Face_const_handle; - typedef typename Arr::Ccb_halfedge_const_circulator - Ccb_halfedge_const_circulator; - - /// Construct the viewer. - /// @param arr the arrangement to view - /// @param title the title of the window - Arr_2_viewer_qt(QWidget* parent, const Arr& arr, - const char* title = "2D Arrangement Basic Viewer") : - Base(parent, arr, title) - {} - - //! - virtual void add_ccb(Ccb_halfedge_const_circulator circ) { + /*! Find the halfedge incident to the lexicographically smallest vertex + * along the CCB, such that there is no other halfedge underneath. + */ + Halfedge_const_handle find_smallest(Ccb_halfedge_const_circulator circ) { const auto* traits = this->m_arr.geometry_traits(); - auto approx = traits->approximate_2_object(); auto cmp_xy = traits->compare_xy_2_object(); auto cmp_y = traits->compare_y_at_x_right_2_object(); @@ -202,11 +93,154 @@ public: ext = curr; } while (++curr != circ); - // Iterate, starting from the lexicographically smallest vertex - curr = ext; + return ext; + } + + //! + virtual void draw_region(Ccb_halfedge_const_circulator circ) { + CGAL::IO::Color color(std::rand()%256, std::rand()%256, std::rand()%256); + this->face_begin(color); + + auto ext = find_smallest(circ); + auto curr = ext; do { + // Skip halfedges that are "antenas": while (curr->face() == curr->twin()->face()) curr = curr->twin()->next(); + + this->add_point_in_face(curr->source()->point()); + draw_curve(curr->curve()); + curr = curr->next(); + } while (curr != ext); + + this->face_end(); + } + + //! + virtual void draw_curve(const X_monotone_curve& curve) { + const auto* traits = this->m_arr.geometry_traits(); + auto ctr_min = traits->construct_min_vertex_2_object(); + auto ctr_max = traits->construct_max_vertex_2_object(); + this->add_segment(ctr_min(curve), ctr_max(curve)); + } + + //! + virtual void draw_point(const Point& p) { this->add_point(p); } + + //! + void add_ccb(Ccb_halfedge_const_circulator circ, Face_const_handle parent) { + std::unordered_map visited; + auto face = circ->face(); + auto curr = circ; + do { + auto new_face = curr->twin()->face(); + if ((new_face == face) || (new_face == parent)) continue; + if (visited.find(new_face) != visited.end()) continue; + visited[new_face] = true; + add_face(new_face, face); + } while (++curr != circ); + } + + //! + void add_face(Face_const_handle face, Face_const_handle parent) { + for (auto it = face->outer_ccbs_begin(); it != face->outer_ccbs_end(); ++it) + { + draw_region(*it); + add_ccb(*it, parent); + } + + for (auto it = face->inner_ccbs_begin(); it != face->inner_ccbs_end(); ++it) + add_ccb(*it, parent); + } + + //! + virtual void keyPressEvent(QKeyEvent* e) { + // Test key pressed: + // const ::Qt::KeyboardModifiers modifiers = e->modifiers(); + // if ((e->key()==Qt::Key_PageUp) && (modifiers==Qt::NoButton)) { ... } + + // Call: * add_elements() if the model changed, followed by + // * redraw() if some viewing parameters changed that implies some + // modifications of the buffers + // (eg. type of normal, color/mono) + // * update() just to update the drawing + + // Call the base method to process others/classicals key + Base::keyPressEvent(e); + } + +protected: + //! The arrangement to draw + const Arr& m_arr; +}; + +//! Basic viewer of a 2D arrangement. +template +class Arr_2_viewer_qt : public Arr_2_basic_viewer_qt { +public: + typedef GeometryTraits_2 Gt; + typedef CGAL::Arrangement_2 Arr; + typedef Arr_2_basic_viewer_qt Base; + typedef typename Arr::Point_2 Point; + typedef typename Arr::X_monotone_curve_2 X_monotone_curve; + typedef typename Arr::Halfedge_const_handle Halfedge_const_handle; + typedef typename Arr::Face_const_handle Face_const_handle; + typedef typename Arr::Ccb_halfedge_const_circulator + Ccb_halfedge_const_circulator; + + /// Construct the viewer. + /// @param arr the arrangement to view + /// @param title the title of the window + Arr_2_viewer_qt(QWidget* parent, const Arr& arr, + const char* title = "2D Arrangement Basic Viewer") : + Base(parent, arr, title) + {} +}; + +//! +template +class Arr_2_viewer_qt, + Dcel> : + public Arr_2_basic_viewer_qt, Dcel> { +public: + typedef Arr_conic_traits_2 Gt; + typedef CGAL::Arrangement_2 Arr; + typedef Arr_2_basic_viewer_qt Base; + typedef typename Arr::Point_2 Point; + typedef typename Arr::X_monotone_curve_2 X_monotone_curve; + typedef typename Arr::Halfedge_const_handle Halfedge_const_handle; + typedef typename Arr::Face_const_handle Face_const_handle; + typedef typename Arr::Ccb_halfedge_const_circulator + Ccb_halfedge_const_circulator; + + /// Construct the viewer. + /// @param arr the arrangement to view + /// @param title the title of the window + Arr_2_viewer_qt(QWidget* parent, const Arr& arr, + const char* title = "2D Arrangement Basic Viewer") : + Base(parent, arr, title) + {} + + //! + virtual void draw_region(Ccb_halfedge_const_circulator circ) { + CGAL::IO::Color color(std::rand()%256, std::rand()%256, std::rand()%256); + this->face_begin(color); + + const auto* traits = this->m_arr.geometry_traits(); + auto approx = traits->approximate_2_object(); + + // Find the lexicographically smallest halfedge: + auto ext = this->find_smallest(circ); + + // Iterate, starting from the lexicographically smallest vertex: + auto curr = ext; + do { + // Skip halfedges that are "antenas": + while (curr->face() == curr->twin()->face()) + curr = curr->twin()->next(); + std::vector polyline; approx(curr->curve(), 10, std::back_inserter(polyline)); auto it = polyline.begin(); @@ -217,14 +251,16 @@ public: } curr = curr->next(); } while (curr != ext); + + this->face_end(); } //! - virtual void add_edge(Halfedge_const_handle e) { + virtual void draw_curve(const X_monotone_curve& curve) { const auto* traits = this->m_arr.geometry_traits(); auto approx = traits->approximate_2_object(); std::vector polyline; - approx(e->curve(), 10, std::back_inserter(polyline)); + approx(curve, 10, std::back_inserter(polyline)); auto it = polyline.begin(); auto prev = it++; From d5f66f614ea7aa33817b805aa3db274c5b5d1f76 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Thu, 26 May 2022 19:40:14 +0300 Subject: [PATCH 020/105] Fixed drawing 2D arrangements --- .../include/CGAL/draw_arrangement_2.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h index 64155dabc4b..82270ff35f2 100644 --- a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h +++ b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h @@ -143,14 +143,14 @@ protected: //! void add_face(Face_const_handle face, Face_const_handle parent) { - for (auto it = face->outer_ccbs_begin(); it != face->outer_ccbs_end(); ++it) - { - draw_region(*it); - add_ccb(*it, parent); - } - for (auto it = face->inner_ccbs_begin(); it != face->inner_ccbs_end(); ++it) add_ccb(*it, parent); + + for (auto it = face->outer_ccbs_begin(); it != face->outer_ccbs_end(); ++it) + { + add_ccb(*it, parent); + draw_region(*it); + } } //! @@ -242,7 +242,7 @@ public: curr = curr->twin()->next(); std::vector polyline; - approx(curr->curve(), 10, std::back_inserter(polyline)); + approx(curr->curve(), std::back_inserter(polyline), 10); auto it = polyline.begin(); auto prev = it++; for (; it != polyline.end(); prev = it++) { @@ -260,7 +260,7 @@ public: const auto* traits = this->m_arr.geometry_traits(); auto approx = traits->approximate_2_object(); std::vector polyline; - approx(curve, 10, std::back_inserter(polyline)); + approx(curve, std::back_inserter(polyline), 10); auto it = polyline.begin(); auto prev = it++; From d4471a5b074d01d14643bd957128de86c32f9687 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Thu, 26 May 2022 20:18:09 +0300 Subject: [PATCH 021/105] Further clean up; suppress construction of local kernel, etc. --- .../include/CGAL/Arr_conic_traits_2.h | 365 +++++++++++++----- .../CGAL/Arr_geometry_traits/Conic_arc_2.h | 17 +- 2 files changed, 286 insertions(+), 96 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index d98b2832424..b5fd7b23037 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -132,6 +132,19 @@ public: //@{ class Compare_x_2 { + protected: + using Traits = Arr_conic_traits_2; + + /*! The traits (in case it has state) */ + const Traits& m_traits; + + /*! Constructor + * \param traits the traits. + */ + Compare_x_2(const Traits& traits) : m_traits(traits) {} + + friend class Arr_conic_traits_2; + public: /*! Compare the x-coordinates of two points. * \param p1 The first point. @@ -141,16 +154,26 @@ public: * EQUAL if x(p1) = x(p2). */ Comparison_result operator() (const Point_2& p1, const Point_2& p2) const - { - Alg_kernel ker; - return (ker.compare_x_2_object()(p1, p2)); - } + { return m_traits.m_alg_kernel->compare_x_2_object()(p1, p2); } }; /*! Obtain a Compare_x_2 functor object. */ - Compare_x_2 compare_x_2_object () const { return Compare_x_2(); } + Compare_x_2 compare_x_2_object() const { return Compare_x_2(*this); } class Compare_xy_2 { + protected: + using Traits = Arr_conic_traits_2; + + /*! The traits (in case it has state) */ + const Traits& m_traits; + + /*! Constructor + * \param traits the traits. + */ + Compare_xy_2(const Traits& traits) : m_traits(traits) {} + + friend class Arr_conic_traits_2; + public: /*! Compares two points lexigoraphically: by x, then by y. * \param p1 The first point. @@ -159,15 +182,12 @@ public: * SMALLER if x(p1) < x(p2), or if x(p1) = x(p2) and y(p1) < y(p2); * EQUAL if the two points are equal. */ - Comparison_result operator()(const Point_2& p1, const Point_2& p2) const { - Alg_kernel ker; - return ker.compare_xy_2_object()(p1, p2); - } + Comparison_result operator()(const Point_2& p1, const Point_2& p2) const + { return m_traits.m_alg_kernel->compare_xy_2_object()(p1, p2); } }; /*! Obtain a Compare_xy_2 functor object. */ - Compare_xy_2 compare_xy_2_object() const - { return Compare_xy_2(); } + Compare_xy_2 compare_xy_2_object() const { return Compare_xy_2(*this); } class Construct_min_vertex_2 { public: @@ -212,6 +232,19 @@ public: { return Is_vertical_2(); } class Compare_y_at_x_2 { + protected: + using Traits = Arr_conic_traits_2; + + /*! The traits (in case it has state) */ + const Traits& m_traits; + + /*! Constructor + * \param traits the traits. + */ + Compare_y_at_x_2(const Traits& traits) : m_traits(traits) {} + + friend class Arr_conic_traits_2; + public: /*! Return the location of the given point with respect to the input curve. * \param cv The curve. @@ -221,20 +254,19 @@ public: * LARGER if y(p) > cv(x(p)), i.e. the point is above the curve; * EQUAL if p lies on the curve. */ - Comparison_result operator()(const Point_2 & p, - const X_monotone_curve_2 & cv) const + Comparison_result operator()(const Point_2& p, const X_monotone_curve_2& cv) + const { - Alg_kernel ker; + const auto alg_kernel = m_traits.m_alg_kernel; + auto cmp_y = alg_kernel->compare_y_2_object(); if (cv.is_vertical()) { // A special treatment for vertical segments: // In case p has the same x c-ordinate of the vertical segment, compare // it to the segment endpoints to determine its position. - Comparison_result res1 = ker.compare_y_2_object()(p, cv.left()); - Comparison_result res2 = ker.compare_y_2_object()(p, cv.right()); - - if (res1 == res2) return res1; - else return EQUAL; + Comparison_result res1 = cmp_y(p, cv.left()); + Comparison_result res2 = cmp_y(p, cv.right()); + return (res1 == res2) ? res1 : EQUAL; } // Check whether the point is exactly on the curve. @@ -244,32 +276,41 @@ public: Comparison_result x_res; Point_2 q; - if ((x_res = ker.compare_x_2_object()(p, cv.left())) == EQUAL) { - q = cv.left(); - } + auto cmp_x = alg_kernel->compare_x_2_object(); + if ((x_res = cmp_x(p, cv.left())) == EQUAL) q = cv.left(); else { CGAL_precondition (x_res != SMALLER); - if ((x_res = ker.compare_x_2_object()(p, cv.right())) == EQUAL) { - q = cv.right(); - } + if ((x_res = cmp_x(p, cv.right())) == EQUAL) q = cv.right(); else { CGAL_precondition(x_res != LARGER); - q = cv.point_at_x (p); } } // Compare p with the a point of the curve with the same x coordinate. - return (ker.compare_y_2_object()(p, q)); + return cmp_y(p, q); } }; /*! Obtain a Compare_y_at_x_2 functor object. */ Compare_y_at_x_2 compare_y_at_x_2_object() const - { return Compare_y_at_x_2(); } + { return Compare_y_at_x_2(*this); } class Compare_y_at_x_left_2 { + protected: + using Traits = Arr_conic_traits_2; + + /*! The traits (in case it has state) */ + const Traits& m_traits; + + /*! Constructor + * \param traits the traits. + */ + Compare_y_at_x_left_2(const Traits& traits) : m_traits(traits) {} + + friend class Arr_conic_traits_2; + public: /*! Compares the y value of two x-monotone curves immediately to the left * of their intersection point. @@ -290,15 +331,14 @@ public: CGAL_precondition(cv1.contains_point(p) && cv2.contains_point(p)); - CGAL_precondition_code(Alg_kernel ker;); - CGAL_precondition(ker.compare_xy_2_object()(p, cv1.left()) == LARGER && - ker.compare_xy_2_object()(p, cv2.left()) == LARGER); + CGAL_precondition_code(const auto ker = m_traits.m_alg_kernel); + CGAL_precondition(ker->compare_xy_2_object()(p, cv1.left()) == LARGER && + ker->compare_xy_2_object()(p, cv2.left()) == LARGER); // If one of the curves is vertical, it is below the other one. if (cv1.is_vertical()) { // Check whether both are vertical: - if (cv2.is_vertical()) return EQUAL; - else return SMALLER; + return (cv2.is_vertical()) ? EQUAL : SMALLER; } else if (cv2.is_vertical()) return LARGER; @@ -309,7 +349,7 @@ public: /*! Obtain a Compare_y_at_x_left_2 functor object. */ Compare_y_at_x_left_2 compare_y_at_x_left_2_object() const - { return Compare_y_at_x_left_2(); } + { return Compare_y_at_x_left_2(*this); } class Compare_y_at_x_right_2 { public: @@ -337,8 +377,7 @@ public: // If one of the curves is vertical, it is above the other one. if (cv1.is_vertical()) { // Check whether both are vertical: - if (cv2.is_vertical()) return EQUAL; - else return LARGER; + return (cv2.is_vertical()) ? EQUAL : LARGER; } else if (cv2.is_vertical()) return SMALLER; @@ -353,7 +392,8 @@ public: class Equal_2 { public: - /*! Check whether the two x-monotone curves are the same (have the same graph). + /*! Check whether the two x-monotone curves are the same (have the same + * graph). * \param cv1 The first curve. * \param cv2 The second curve. * \return (true) if the two curves are the same; (false) otherwise. @@ -389,7 +429,18 @@ public: * A functor for subdividing curves into x-monotone curves. */ class Make_x_monotone_2 { - typedef Arr_conic_traits_2 Self; + protected: + using Traits = Arr_conic_traits_2; + + /*! The traits (in case it has state) */ + const Traits& m_traits; + + /*! Constructor + * \param traits the traits. + */ + Make_x_monotone_2(const Traits& traits) : m_traits(traits) {} + + friend class Arr_conic_traits_2; public: /*! Subdivide a given conic curve (or conic arc) into x-monotone subcurves @@ -407,15 +458,12 @@ public: // Increment the serial number of the curve cv, which will serve as its // unique identifier. - auto index = Self::get_index(); + auto index = Traits::get_index(); Conic_id conic_id(index); // Find the points of vertical tangency to cv and act accordingly. typename Curve_2::Point_2 vtan_ps[2]; - int n_vtan_ps; - - n_vtan_ps = cv.vertical_tangency_points(vtan_ps); - + auto n_vtan_ps = cv.vertical_tangency_points(vtan_ps); if (n_vtan_ps == 0) { // In case the given curve is already x-monotone: *oi++ = Make_x_monotone_result(X_monotone_curve_2(cv, conic_id)); @@ -457,17 +505,14 @@ public: // tangnecy points (or both lies above it). int ind_first = 0; int ind_second = 1; - Alg_kernel ker; - typename Alg_kernel::Line_2 line = - ker.construct_line_2_object()(vtan_ps[0], vtan_ps[1]); - const Comparison_result start_pos = - ker.compare_y_at_x_2_object()(cv.source(), line); - const Comparison_result order_vpts = - ker.compare_x_2_object()(vtan_ps[0], vtan_ps[1]); + auto ker = m_traits.m_alg_kernel; + auto cmp_y_at_x_2 = ker->compare_y_at_x_2_object(); + auto line = ker->construct_line_2_object()(vtan_ps[0], vtan_ps[1]); + auto start_pos = cmp_y_at_x_2(cv.source(), line); + auto order_vpts = ker->compare_x_2_object()(vtan_ps[0], vtan_ps[1]); - CGAL_assertion(start_pos != EQUAL && - ker.compare_y_at_x_2_object()(cv.target(), - line) == start_pos); + CGAL_assertion((start_pos != EQUAL) && + (cmp_y_at_x_2(cv.target(), line) == start_pos)); CGAL_assertion(order_vpts != EQUAL); if (((cv.orientation() == COUNTERCLOCKWISE) && @@ -501,7 +546,7 @@ public: /*! Obtain a Make_x_monotone_2 functor object. */ Make_x_monotone_2 make_x_monotone_2_object() const - { return Make_x_monotone_2(); } + { return Make_x_monotone_2(*this); } class Split_2 { public: @@ -522,11 +567,11 @@ public: class Intersect_2 { private: - Intersection_map& _inter_map; // The map of intersection points. + Intersection_map& m_inter_map; // The map of intersection points. public: /*! Constructor. */ - Intersect_2(Intersection_map& map) : _inter_map(map) {} + Intersect_2(Intersection_map& map) : m_inter_map(map) {} /*! Find the intersections of the two given curves and insert them to the * given output iterator. As two segments may itersect only once, only a @@ -540,7 +585,7 @@ public: OutputIterator operator()(const X_monotone_curve_2& cv1, const X_monotone_curve_2& cv2, OutputIterator oi) const - { return cv1.intersect(cv2, _inter_map, oi); } + { return cv1.intersect(cv2, m_inter_map, oi); } }; /*! Obtain an Intersect_2 functor object. */ @@ -554,8 +599,8 @@ public: * \return (true) if the two curves are mergeable - if they are supported * by the same line and share a common endpoint; (false) otherwise. */ - bool operator() (const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2) const + bool operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2) const { return cv1.can_merge_with(cv2); } }; @@ -568,15 +613,15 @@ public: */ class Merge_2 { protected: - typedef Arr_conic_traits_2 Traits; + using Traits = Arr_conic_traits_2; /*! The traits (in case it has state) */ - const Traits* m_traits; + const Traits& m_traits; /*! Constructor * \param traits the traits (in case it has state) */ - Merge_2(const Traits* traits) : m_traits(traits) {} + Merge_2(const Traits& traits) : m_traits(traits) {} friend class Arr_conic_traits_2; @@ -599,7 +644,7 @@ public: }; /*! Obtain a Merge_2 functor object. */ - Merge_2 merge_2_object() const { return Merge_2(this); } + Merge_2 merge_2_object() const { return Merge_2(*this); } //@} @@ -610,6 +655,19 @@ public: using Approximate_point_2 = Approximate_kernel::Point_2; class Approximate_2 { + protected: + using Traits = Arr_conic_traits_2; + + /*! The traits (in case it has state) */ + const Traits& m_traits; + + /*! Constructor + * \param traits the traits. + */ + Approximate_2(const Traits& traits) : m_traits(traits) {} + + friend class Arr_conic_traits_2; + public: /*! Obtain an approximation of a point coordinate. * \param p The exact point. @@ -631,10 +689,78 @@ public: { return std::make_pair(operator()(p, 0), operator()(p, 1)); } /*! Obtain an approximation of an x-monotone curve. + * + * ELLIPSE + * ------- + * The general equation of an ellipse is: + * r·𝑥^2 + s·𝑦^2 + t·𝑥·𝑦 + u·𝑥 + v·𝑦 + w = 0 + * where 4·r·s−t^2 > 0 + * We eliminate t so that the x·y term vanishes, applying an inverse + * rotation. Then, we compute the radi and the center. Finaly, we rotate + * back. The angle of rotation is given by: + * 𝑡𝑎𝑛(2𝜃) = 𝐵 / (𝐴−𝐶) + * Then + * 𝑐𝑜𝑠(2𝜃) = sqrt((1 + 𝑐𝑜𝑠(2𝜃))/2) + * 𝑠𝑖𝑛(2𝜃) = sqrt((1 - 𝑐𝑜𝑠(2𝜃))/2) + * The coefficients of the new ellipse are given by: + * r′ = r·𝑐𝑜𝑠(𝜃)^2 + s·𝑠𝑖𝑛(𝜃)^2 + t·𝑐𝑜𝑠(𝜃)·𝑠𝑖𝑛(𝜃) + * s′ = r·𝑠𝑖𝑛(𝜃)^2 + s·𝑐𝑜𝑠(𝜃)^2 − t·𝑐𝑜𝑠(𝜃)·𝑠𝑖𝑛(𝜃) + * t′ = 0 + * u′ = u·𝑐𝑜𝑠(𝜃) + v·𝑠𝑖𝑛(𝜃) + * v′ = −u·𝑠𝑖𝑛(𝜃) + v·𝑐𝑜𝑠(𝜃) + * w′ = w + * After writing this equation in the form: + * (𝑥′ − 𝐶𝑥′)^2 (𝑦′ − 𝐶𝑦′)^2 + * ----------- + ------------ = 1 + * 𝑎^2 𝑏^2 + * We get: + * u′ + * 𝐶𝑥′ = ---- + * 2·r′ + * + * v′ + * 𝐶𝑦′ = ---- + * 2·s′ + * + * −4·w′·r′·s′ + s′·u′2 + r′·v′2 + * a^2 = ---------------------------- + * 4·r′^2·s′ + * + * −4·w′·r′·s′ + s′·u′2 + r′·v′2 + * b^2 = ---------------------------- + * 4·r′·s′^2 + * + * Rotate back about angle 𝜃 to find the coordinates of the center: + * 𝐶𝑥 = 𝐶𝑥′·𝑐𝑜𝑠𝜃 − 𝐶𝑦′·𝑠𝑖𝑛𝜃 + * 𝐶𝑦 = 𝐶𝑥′·𝑠𝑖𝑛𝜃 + 𝐶𝑦′·𝑐𝑜𝑠𝜃 + * + * The parametric formula of an ellipse centered at the origin with major + * axis parallel to the x-axis and minor axis parallel to the y-axis is: + * 𝑥(𝛼) = a·𝑐𝑜𝑠(𝛼) + * 𝑦(𝛼) = b·𝑠𝑖𝑛(𝛼) + * where a is the major radius and b is the minor radius. + * + * The rotation transformation is fiven by + * 𝑥 = 𝑥(𝑡)·𝑐𝑜𝑠(𝜃) − 𝑦(𝑡)·𝑠𝑖𝑛(𝜃) + * 𝑦 = 𝑥(𝑡)·𝑠𝑖𝑛(𝜃) + 𝑦(𝑡)·𝑐𝑜𝑠(𝜃) + * Where 𝜃 is the rotation angle + * + * Combining the above we get + * 𝑥(𝛼) = a·𝑐𝑜𝑠(𝛼)·𝑐𝑜𝑠(𝜃) − b·𝑠𝑖𝑛(𝛼)·𝑠𝑖𝑛(𝜃) + * 𝑦(𝛼) = a·𝑐𝑜𝑠(𝛼)·𝑠𝑖𝑛(𝜃) + b·𝑠𝑖𝑛(𝛼)·𝑐𝑜𝑠(𝜃) + * + * To shift any equation from the center we add 𝐶𝑥 to the 𝑥 equation and 𝐶𝑦 + * to the 𝑦 equation. Therefore the equation of a Rotated Ellipse is: + * 𝑥(𝛼) = a·𝑐𝑜𝑠(𝛼)·𝑐𝑜𝑠(𝜃) − b·𝑠𝑖𝑛(𝛼)·𝑠𝑖𝑛(𝜃) + 𝐶𝑥 + * 𝑦(𝛼) = a·𝑐𝑜𝑠(𝛼)·𝑠𝑖𝑛(𝜃) + b·𝑠𝑖𝑛(𝛼)·𝑐𝑜𝑠(𝜃) + 𝐶𝑦 + * + * @param density the density of the generated approximation. By default + * this value is 1, which implies that approximately every segment + * spans a unit length. */ template - OutputIterator operator()(const X_monotone_curve_2& arc, size_t size, - OutputIterator oi) const { + OutputIterator operator()(const X_monotone_curve_2& arc, OutputIterator oi, + double density = 1) const { auto xs = CGAL::to_double(arc.source().x()); auto ys = CGAL::to_double(arc.source().y()); auto xt = CGAL::to_double(arc.target().x()); @@ -708,23 +834,19 @@ public: auto xdt = xt - cx; auto ydt = yt - cy; auto tt = std::atan2(a*(cost*ydt - sint*xdt),b*(sint*ydt + cost*xdt)); - std::cout << "xdt, ydt, tt: " << xdt << "," << ydt << ", " << tt << std::endl; if (tt < 0) tt += 2*M_PI; + if (tt < ts) tt += 2*M_PI; std::cout << "ts,tt: " << ts << "," << tt << std::endl; namespace bm = boost::math; auto ratio = b/a; - auto k = 1 - (ratio*ratio); - auto ps = std::atan2(b*std::tan(ts), a); - if (ps < 0) ps += 2*M_PI; - auto ds = a*bm::ellint_2(k, ps); - auto pt = std::atan2(b*std::tan(tt), a); - if (pt < 0) pt += 2*M_PI; - auto dt = a*bm::ellint_2(k, pt); - std::cout << "ps,pt: " << ps << ", " << pt << std::endl; + auto k = std::sqrt(1 - (ratio*ratio)); + auto ds = a*bm::ellint_2(k, ts); + auto dt = a*bm::ellint_2(k, tt); std::cout << "ds,dt: " << ds << ", " << dt << std::endl; + auto len = dt - ds; + auto size = static_cast(len*density); - if (tt < ts) tt += 2*M_PI; auto delta = (tt - ts) / (size-1); auto t(ts); *oi++ = Approximate_point_2(xs, ys); @@ -744,7 +866,7 @@ public: }; /*! Obtain an Approximate_2 functor object. */ - Approximate_2 approximate_2_object() const { return Approximate_2(); } + Approximate_2 approximate_2_object() const { return Approximate_2(*this); } //! Functor class Construct_x_monotone_curve_2 { @@ -766,7 +888,7 @@ public: //! Constructor of conic arcs class Construct_curve_2 { protected: - typedef Arr_conic_traits_2 Traits; + using Traits = Arr_conic_traits_2; /*! The traits (in case it has state) */ const Traits& m_traits; @@ -776,7 +898,7 @@ public: */ Construct_curve_2(const Traits& traits) : m_traits(traits) {} - friend class Arr_conic_traits_2; + friend class Arr_conic_traits_2; public: /*! Construct an empty curve. @@ -802,7 +924,9 @@ public: rat_coeffs[3] = u; rat_coeffs[4] = v; rat_coeffs[5] = w; - set_full(rat_coeffs, true); + Curve_2 arc; + m_traits.set_full(arc, rat_coeffs, true); + return arc; } /*! Construct a conic arc that lies on the conic: @@ -852,7 +976,7 @@ public: const auto alg_kernel = m_traits.m_alg_kernel; auto source = Point_2(nt_traits->convert(x1), nt_traits->convert(y1)); auto target = Point_2(nt_traits->convert(x3), nt_traits->convert(y3)); - arc.set_enpoints(source, target); + arc.set_endpoints(source, target); // Make sure that the source and the taget are not the same. CGAL_precondition(alg_kernel->compare_xy_2_object()(source, target) != @@ -899,7 +1023,7 @@ public: // the source and the target points, the orientation is positive (going // counterclockwise). // Otherwise, it is negative (going clockwise). - auto orient_f = m_alg_kernel.orientation_2_object(); + auto orient_f = alg_kernel->orientation_2_object(); Point_2 p_mid = Point_2(nt_traits->convert(x2), nt_traits->convert(y2)); auto orient = (orient_f(source, p_mid, target) == LEFT_TURN) ? @@ -907,7 +1031,7 @@ public: arc.set_orientation(orient); // Set the arc properties (no need to compute the orientation). - set(arc, rat_coeffs); + m_traits.set(arc, rat_coeffs); return arc; } @@ -1268,7 +1392,7 @@ public: Rat_point_2 center = rat_kernel->construct_center_2_object()(circ); Rational x0 = center.x(); Rational y0 = center.y(); - Rational R_sqr = rat_kernel->compute_squared_radius_2_object()(circ); + Rational r_sqr = rat_kernel->compute_squared_radius_2_object()(circ); // Produce the correponding conic: if the circle center is (x0,y0) // and its squared radius is R^2, that its equation is: @@ -1284,12 +1408,76 @@ public: rat_coeffs[2] = zero; rat_coeffs[3] = minus_two*x0; rat_coeffs[4] = minus_two*y0; - rat_coeffs[5] = x0*x0 + y0*y0 - R_sqr; + rat_coeffs[5] = x0*x0 + y0*y0 - r_sqr; // Set the arc to be the full conic (no need to compute the orientation). - m_traits.set_full(arc.rat_coeffs, false); + m_traits.set_full(arc, rat_coeffs, false); return arc; } + + /*! Construct a conic arc that lies on a given circle: + * C: (x - x0)^2 + (y - y0)^2 = R^2 + * \param orient The orientation of the circle. + * \param source The source point. + * \param target The target point. + * \pre The source and the target must be on the conic boundary and must + * not be the same. + */ + Curve_2 operator()(const Rat_circle_2& circ, const Orientation& orient, + const Point_2& source, const Point_2& target) const { + // Make sure that the source and the taget are not the same. + CGAL_precondition(Alg_kernel().compare_xy_2_object()(source, target) != + EQUAL); + CGAL_precondition(orient != COLLINEAR); + + Curve_2 arc; + arc.set_endpoints(source, target); + arc.set_orientation(orient); + + // Get the circle properties. + const auto rat_kernel = m_traits.m_rat_kernel; + Rat_point_2 center = rat_kernel->construct_center_2_object()(circ); + Rational x0 = center.x(); + Rational y0 = center.y(); + Rational r_sqr = rat_kernel->compute_squared_radius_2_object()(circ); + + // Produce the correponding conic: if the circle center is (x0,y0) + // and it squared radius is R^2, that its equation is: + // x^2 + y^2 - 2*x0*x - 2*y0*y + (x0^2 + y0^2 - R^2) = 0 + // Since this equation describes a curve with a negative (clockwise) + // orientation, we multiply it by -1 if nece_Conic_arc_2 ssary to obtain a + // positive (counterclockwise) orientation. + const Rational zero(0); + Rational rat_coeffs[6]; + + if (arc.orientation() == COUNTERCLOCKWISE) { + const Rational minus_one(-1); + const Rational two(2); + + rat_coeffs[0] = minus_one; + rat_coeffs[1] = minus_one; + rat_coeffs[2] = zero; + rat_coeffs[3] = two*x0; + rat_coeffs[4] = two*y0; + rat_coeffs[5] = r_sqr - x0*x0 - y0*y0; + } + else { + const Rational one(1); + const Rational minus_two(-2); + + rat_coeffs[0] = one; + rat_coeffs[1] = one; + rat_coeffs[2] = zero; + rat_coeffs[3] = minus_two*x0; + rat_coeffs[4] = minus_two*y0; + rat_coeffs[5] = x0*x0 + y0*y0 - r_sqr; + } + + // Set the arc properties (no need to compute the orientation). + m_traits.set(arc, rat_coeffs); + + return arc; + } }; /*! Obtain a Construct_curve_2 functor object. */ @@ -1334,7 +1522,7 @@ public: class Trim_2 { protected: - typedef Arr_conic_traits_2 Traits; + using Traits = Arr_conic_traits_2; /*! The traits (in case it has state) */ const Traits& m_traits; @@ -1344,8 +1532,9 @@ public: */ Trim_2(const Traits& traits) : m_traits(traits) {} - public: friend class Arr_conic_traits_2; + + public: /*!\brief * Returns a trimmed version of an arc * @@ -1545,6 +1734,8 @@ public: v = -int_coeffs[4]; w = -int_coeffs[5]; } + arc.set_coefficients(r, s, t, u, v, w); + std::cout << "s: " << s << std::endl; // Make sure the conic is a non-degenerate ellipse: // The coefficients should satisfy (4rs - t^2) > 0. diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h index 76a2f846916..bd1fee2360b 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h @@ -127,8 +127,8 @@ public: Integer u, Integer v, Integer w) { m_r = r; - s = m_s; - t = m_t; + m_s = s; + m_t = t; m_u = u; m_v = v; m_w = w; @@ -975,7 +975,7 @@ public: // Calculate the vertical tangency points of the supporting conic. Point_2 ps[2]; - int n = conic_vertical_tangency_points(ps); + auto n = conic_vertical_tangency_points(ps); // Return only the points that are contained in the arc interior. int m = 0; @@ -1511,22 +1511,21 @@ protected: } // Pair the x and y coordinates and obtain the vertical tangency points. - int n = 0; - int i, j; + int n(0); - for (i = 0; i < n_xs; ++i) { + for (int i = 0; i < n_xs; ++i) { if (n_ys == 1) { ps[n] = Point_2(xs[i], ys[0]); - n++; + ++n; } else { - for (j = 0; j < n_ys; j++) { + for (int j = 0; j < n_ys; j++) { if (CGAL::compare(nt_traits.convert(two*m_s) * ys[j], -(nt_traits.convert(m_t) * xs[i] + nt_traits.convert(m_v))) == EQUAL) { ps[n] = Point_2(xs[i], ys[j]); - n++; + ++n; break; } } From 00c5bd495d11bcda0639e1fb167b8920a50aa834 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Mon, 30 May 2022 18:59:54 +0300 Subject: [PATCH 022/105] Continued cleaning up. --- .../conic_multiplicities.cpp | 15 +- .../Arrangement_on_surface_2/conics.cpp | 51 +- .../polycurve_conic.cpp | 73 +- .../include/CGAL/Arr_conic_traits_2.h | 1267 ++++++++++++++--- .../CGAL/Arr_geometry_traits/Conic_arc_2.h | 709 +-------- .../CGAL/Arr_geometry_traits/Conic_point_2.h | 39 +- .../Conic_x_monotone_arc_2.h | 668 ++------- .../Arrangement_on_surface_2/IO_base_test.h | 121 +- .../conic_traits_adapter.cpp | 41 +- 9 files changed, 1410 insertions(+), 1574 deletions(-) diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conic_multiplicities.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conic_multiplicities.cpp index 158ce153703..752f6e21f9d 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conic_multiplicities.cpp +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conic_multiplicities.cpp @@ -14,7 +14,10 @@ typedef CGAL::Arr_naive_point_location Naive_pl; int main() { - Arrangement arr; + Traits traits; + auto ctr_cv = traits.construct_curve_2_object(); + + Arrangement arr(&traits); Naive_pl pl(arr); // Insert a hyperbolic arc, supported by the hyperbola y = x^2/(1-x) @@ -22,18 +25,20 @@ int main() { // Note that the arc is counterclockwise oriented. Point ps1(-1, Rational(1,2)); Point pt1(Rational(1,2), Rational(1,2)); - Conic_arc cv1(1, 0, 1, 0, -1, 0, CGAL::COUNTERCLOCKWISE, ps1, pt1); - insert(arr, cv1, pl); + Conic_arc cv1 = ctr_cv(1, 0, 1, 0, -1, 0, CGAL::COUNTERCLOCKWISE, ps1, pt1); + // insert(arr, cv1, pl); +#if 0 // Insert the bottom half of the circle centered at (0, 1/2) whose radius // is 1/2 (therefore its squared radius is 1/4). Rat_circle circ2(Rat_point(0, Rational(1,2)), Rational(1,4)); Point ps2(-Rational(1,2), Rational(1,2)); Point pt2(Rational(1,2), Rational(1,2)); - Conic_arc cv2(circ2, CGAL::COUNTERCLOCKWISE, ps2, pt2); + Conic_arc cv2 = ctr_cv(circ2, CGAL::COUNTERCLOCKWISE, ps2, pt2); insert(arr, cv2, pl); +#endif - print_arrangement (arr); + print_arrangement(arr); return 0; } diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conics.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conics.cpp index a1ee7ec3102..3eea95f1127 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conics.cpp +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conics.cpp @@ -18,43 +18,46 @@ int main() { // Insert a hyperbolic arc (C1), supported by the hyperbola y = 1/x // (or: xy - 1 = 0) with the endpoints (1/4, 4) and (2, 1/2). // The arc is counterclockwise oriented. - insert(arr, Conic_arc(0, 0, 1, 0, 0, -1, CGAL::COUNTERCLOCKWISE, - Point(Rational(1,4), 4), Point(2, Rational(1,2)))); + insert(arr, ctr_cv(0, 0, 1, 0, 0, -1, CGAL::COUNTERCLOCKWISE, + Point(Rational(1,4), 4), Point(2, Rational(1,2)))); #endif +#if 0 // Insert a full ellipse (C2), which is (x/4)^2 + (y/2)^2 = 0 rotated by // phi = 36.87 degrees (such that sin(phi) = 0.6, cos(phi) = 0.8), // yielding: 58x^2 + 72y^2 - 48xy - 360 = 0. - insert(arr, Conic_arc(58, 72, -48, 0, 0, -360)); - -#if 0 - // Insert the segment (C3) (1, 1) -- (0, -3). - Conic_arc c3 = ctr_cv(Rat_segment(Rat_point(1, 1), Rat_point(0, -3))); - insert(arr, c3); - - // Insert a circular arc (C4) supported by the circle x^2 + y^2 = 5^2, - // with (-3, 4) and (4, 3) as its endpoints. We want the arc to be - // clockwise-oriented, so it passes through (0, 5) as well. - Conic_arc c4(Rat_point(-3, 4), Rat_point(0, 5), Rat_point(4, 3)); - insert(arr, c4); - - // Insert a full unit circle (C5) that is centered at (0, 4). - Conic_arc c5(Conic_arc(Rat_circle(Rat_point(0,4), 1))); - insert(arr, c5); + insert(arr, ctr_cv(58, 72, -48, 0, 0, -360)); #endif #if 0 + // Insert the segment (C3) (1, 1) -- (0, -3). + insert(arr, ctr_cv(Rat_segment(Rat_point(1, 1), Rat_point(0, -3)))); +#endif + +#if 0 + // Insert a circular arc (C4) supported by the circle x^2 + y^2 = 5^2, + // with (-3, 4) and (4, 3) as its endpoints. We want the arc to be + // clockwise-oriented, so it passes through (0, 5) as well. + insert(arr, ctr_cv(Rat_point(-3, 4), Rat_point(0, 5), Rat_point(4, 3))); +#endif + +#if 0 + // Insert a full unit circle (C5) that is centered at (0, 4). + insert(arr, ctr_cv(Rat_circle(Rat_point(0,4), 1))); +#endif + +#if 1 // Insert a parabolic arc (C6) supported by the parabola y = -x^2 with // endpoints (-sqrt(3),-3) (~(-1.73,-3)) and (sqrt(2),-2) (~(1.41,-2)). // Since the x-coordinates of the endpoints cannot be acccurately represented, // we specify them as the intersections of the parabola with the lines // y = -3 and y = -2, respectively. The arc is clockwise-oriented. Conic_arc c6 = - Conic_arc(1, 0, 0, 0, 1, 0, CGAL::CLOCKWISE, // The parabola. - Point(-1.73, -3), // approximation of the source. - 0, 0, 0, 0, 1, 3, // the line: y = -3. - Point(1.41, -2), // approximation of the target. - 0, 0, 0, 0, 1, 2); // the line: y = -2. + ctr_cv(1, 0, 0, 0, 1, 0, CGAL::CLOCKWISE, // The parabola. + Point(-1.73, -3), // approximation of the source. + 0, 0, 0, 0, 1, 3, // the line: y = -3. + Point(1.41, -2), // approximation of the target. + 0, 0, 0, 0, 1, 2); // the line: y = -2. insert(arr, c6); #endif @@ -63,7 +66,7 @@ int main() { // Insert the right half of the circle centered at (4, 2.5) whose radius // is 1/2 (therefore its squared radius is 1/4) (C7). Rat_circle circ7(Rat_point(4, Rational(5,2)), Rational(1,4)); - insert(arr, Conic_arc(circ7, CGAL::CLOCKWISE, Point(4, 3), Point(4, 2))); + insert(arr, ctr_cv(circ7, CGAL::CLOCKWISE, Point(4, 3), Point(4, 2))); #endif print_arrangement_size(arr); diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/polycurve_conic.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/polycurve_conic.cpp index 7513e6bff7a..c8b1d76b38e 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/polycurve_conic.cpp +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/polycurve_conic.cpp @@ -27,7 +27,10 @@ typedef Polycurve_conic_traits_2::Curve_2 Polycurve; typedef CGAL::Arrangement_2 Polycurve_conic_arrangment; int main() { - Polycurve_conic_traits_2 traits; + Traits sub_traits; + Polycurve_conic_traits_2 traits(&sub_traits); + auto ctr_sub_cv = sub_traits.construct_curve_2_object(); + auto ctr_sub_xcv = sub_traits.construct_x_monotone_curve_2_object(); // Polycurve construction functors auto ctr_xpolycurve = traits.construct_x_monotone_curve_2_object(); @@ -39,29 +42,29 @@ int main() { // Create polycurves // y=x^2 - Conic_arc c3(1,0,0,0,-1,0,CGAL::COUNTERCLOCKWISE, - Point(Algebraic(0), Algebraic(0)), - Point(Algebraic(3), Algebraic(9))); - Conic_arc c4(1,0,0,0,-1,0,CGAL::COUNTERCLOCKWISE, - Point(Algebraic(3), Algebraic(9)), - Point(Algebraic(5), Algebraic(25))); - Conic_arc c5(0,1,0,1,0,0, CGAL::COUNTERCLOCKWISE, - Point(Algebraic(-25), Algebraic(-5)), - Point(Algebraic(0), Algebraic(0))); + Conic_arc c3 = ctr_sub_cv(1,0,0,0,-1,0,CGAL::COUNTERCLOCKWISE, + Point(Algebraic(0), Algebraic(0)), + Point(Algebraic(3), Algebraic(9))); + Conic_arc c4 = ctr_sub_cv(1,0,0,0,-1,0,CGAL::COUNTERCLOCKWISE, + Point(Algebraic(3), Algebraic(9)), + Point(Algebraic(5), Algebraic(25))); + Conic_arc c5 = ctr_sub_cv(0,1,0,1,0,0, CGAL::COUNTERCLOCKWISE, + Point(Algebraic(-25), Algebraic(-5)), + Point(Algebraic(0), Algebraic(0))); - Conic_arc c6(1,1,0,6,-26,162,CGAL::COUNTERCLOCKWISE, - Point(Algebraic(-7), Algebraic(13)), - Point(Algebraic(-3), Algebraic(9))); - Conic_arc c7(1,0,0,0,-1,0,CGAL::COUNTERCLOCKWISE, - Point(Algebraic(-3), Algebraic(9)), - Point(Algebraic(0), Algebraic(0))); - Conic_arc c8(0,1,0,-1,0,0, CGAL::COUNTERCLOCKWISE, - Point(Algebraic(0), Algebraic(0)), - Point(Algebraic(4), Algebraic(-2))); + Conic_arc c6 = ctr_sub_cv(1,1,0,6,-26,162,CGAL::COUNTERCLOCKWISE, + Point(Algebraic(-7), Algebraic(13)), + Point(Algebraic(-3), Algebraic(9))); + Conic_arc c7 = ctr_sub_cv(1,0,0,0,-1,0,CGAL::COUNTERCLOCKWISE, + Point(Algebraic(-3), Algebraic(9)), + Point(Algebraic(0), Algebraic(0))); + Conic_arc c8 = ctr_sub_cv(0,1,0,-1,0,0, CGAL::COUNTERCLOCKWISE, + Point(Algebraic(0), Algebraic(0)), + Point(Algebraic(4), Algebraic(-2))); - Conic_arc c9(1,0,0,0,-1,0,CGAL::COUNTERCLOCKWISE, - Point(Algebraic(-5), Algebraic(25)), - Point(Algebraic(5), Algebraic(25))); + Conic_arc c9 = ctr_sub_cv(1,0,0,0,-1,0,CGAL::COUNTERCLOCKWISE, + Point(Algebraic(-5), Algebraic(25)), + Point(Algebraic(5), Algebraic(25))); // Construct poly-curve conic_curves.clear(); @@ -69,12 +72,12 @@ int main() { Polycurve conic_polycurve_1 = ctr_polycurve(conic_curves.begin(), conic_curves.end()); - Conic_arc c11(0,1,0,-1,0,0,CGAL::COUNTERCLOCKWISE, - Point(Algebraic(25), Algebraic(-5)), - Point(Algebraic(0), Algebraic(0))); - Conic_arc c12(1,0,0,0,-1,0,CGAL::COUNTERCLOCKWISE, - Point(Algebraic(0), Algebraic(0)), - Point(Algebraic(5), Algebraic(25))); + Conic_arc c11 = ctr_sub_cv(0,1,0,-1,0,0,CGAL::COUNTERCLOCKWISE, + Point(Algebraic(25), Algebraic(-5)), + Point(Algebraic(0), Algebraic(0))); + Conic_arc c12 = ctr_sub_cv(1,0,0,0,-1,0,CGAL::COUNTERCLOCKWISE, + Point(Algebraic(0), Algebraic(0)), + Point(Algebraic(5), Algebraic(25))); // Construct poly-curve conic_curves.clear(); @@ -84,12 +87,12 @@ int main() { ctr_polycurve(conic_curves.begin(), conic_curves.end()); // Construct x-monotone conic curves from conic curves - X_monotone_conic_arc xc3(c3); - X_monotone_conic_arc xc4(c4); - X_monotone_conic_arc xc5(c5); - X_monotone_conic_arc xc6(c6); - X_monotone_conic_arc xc7(c7); - X_monotone_conic_arc xc8(c8); + X_monotone_conic_arc xc3 = ctr_sub_xcv(c3); + X_monotone_conic_arc xc4 = ctr_sub_xcv(c4); + X_monotone_conic_arc xc5 = ctr_sub_xcv(c5); + X_monotone_conic_arc xc6 = ctr_sub_xcv(c6); + X_monotone_conic_arc xc7 = ctr_sub_xcv(c7); + X_monotone_conic_arc xc8 = ctr_sub_xcv(c8); // Construct x-monotone poly-curve from x-monotone conic curves. xmono_conic_curves_2.clear(); @@ -98,7 +101,7 @@ int main() { xmono_conic_curves_2.push_back(xc4); X_monotone_polycurve conic_x_mono_polycurve_1 = ctr_xpolycurve(xmono_conic_curves_2.begin(), - xmono_conic_curves_2.end()); + xmono_conic_curves_2.end()); // Construct x-monotone poly-curve. xmono_conic_curves_2.clear(); diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index b5fd7b23037..faa0591dc37 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -195,8 +195,8 @@ public: * \param cv The curve. * \return The left endpoint. */ - const Point_2& operator()(const X_monotone_curve_2 & cv) const - { return cv.left(); } + const Point_2& operator()(const X_monotone_curve_2& xcv) const + { return xcv.left(); } }; /*! Obtain a Construct_min_vertex_2 functor object. */ @@ -209,8 +209,8 @@ public: * \param cv The curve. * \return The right endpoint. */ - const Point_2& operator()(const X_monotone_curve_2 & cv) const - { return cv.right(); } + const Point_2& operator()(const X_monotone_curve_2& xcv) const + { return xcv.right(); } }; /*! Obtain a Construct_max_vertex_2 functor object. */ @@ -228,8 +228,7 @@ public: }; /*! Obtain an Is_vertical_2 functor object. */ - Is_vertical_2 is_vertical_2_object() const - { return Is_vertical_2(); } + Is_vertical_2 is_vertical_2_object() const { return Is_vertical_2(); } class Compare_y_at_x_2 { protected: @@ -254,11 +253,10 @@ public: * LARGER if y(p) > cv(x(p)), i.e. the point is above the curve; * EQUAL if p lies on the curve. */ - Comparison_result operator()(const Point_2& p, const X_monotone_curve_2& cv) - const + Comparison_result operator()(const Point_2& p, + const X_monotone_curve_2& cv) const { - const auto alg_kernel = m_traits.m_alg_kernel; - auto cmp_y = alg_kernel->compare_y_2_object(); + auto cmp_y = m_traits.m_alg_kernel->compare_y_2_object(); if (cv.is_vertical()) { // A special treatment for vertical segments: @@ -273,24 +271,104 @@ public: if (cv.contains_point(p)) return EQUAL; // Obtain a point q on the x-monotone arc with the same x coordinate as p. - Comparison_result x_res; Point_2 q; - auto cmp_x = alg_kernel->compare_x_2_object(); - if ((x_res = cmp_x(p, cv.left())) == EQUAL) q = cv.left(); + auto cmp_x = m_traits.m_alg_kernel->compare_x_2_object(); + Comparison_result x_res_left = cmp_x(p, cv.left()); + if (x_res_left == EQUAL) q = cv.left(); else { - CGAL_precondition (x_res != SMALLER); - - if ((x_res = cmp_x(p, cv.right())) == EQUAL) q = cv.right(); + CGAL_precondition(x_res_left != SMALLER); + auto x_res_right = cmp_x(p, cv.right()); + if (x_res_right == EQUAL) q = cv.right(); else { - CGAL_precondition(x_res != LARGER); - q = cv.point_at_x (p); + CGAL_precondition(x_res_right != LARGER); + q = point_at_x(cv, p); } } // Compare p with the a point of the curve with the same x coordinate. return cmp_y(p, q); } + + private: + /*! Compute a point on the arc with the same x-coordiante as the given + * point. + * \param p The given point. + * \pre The arc is not vertical and p is in the x-range of the arc. + * \return A point on the arc with the same x-coordiante as p. + */ + Point_2 point_at_x(const X_monotone_curve_2& xcv, const Point_2& p) const { + // Make sure that p is in the x-range of the arc. + CGAL_precondition(! xcv.test_flag(X_monotone_curve_2::IS_VERTICAL_SEGMENT)); + + CGAL_precondition_code(auto cmp_x = m_traits.m_alg_kernel->compare_x_2_object()); + CGAL_precondition((cmp_x(p, xcv.left()) != SMALLER) && + (cmp_x(p, xcv.right()) != LARGER)); + + if (xcv.is_special_segment()) { + // In case of a special segment, the equation of the supported line + // (a*x + b*y + c) = 0 is stored with the extra data field, and we + // simply have: + const auto& extra_data = xcv.extra_data(); + Algebraic y = -(extra_data->a*p.x() + extra_data->c) / extra_data->b; + + // Return the computed point. + return Point_2(p.x(), y); + } + + // Compute the y-coordinate according to the degree of the supporting + // conic curve. + Algebraic y; + + if (xcv.degree_mask() == xcv.flag_mask(X_monotone_curve_2::DEGREE_1)) { + // In case of a linear curve, the y-coordinate is a simple linear + // expression of x(p) (note that v is not 0 as the arc is not vertical): + // y = -(u*x(p) + w) / v + y = -(xcv.alg_u()*p.x() + xcv.alg_w()) / xcv.alg_v(); + } + else if (xcv.orientation() == COLLINEAR) { + const auto& extra_data = xcv.extra_data(); + CGAL_assertion(extra_data != nullptr); + + // In this case the equation of the supporting line is given by the + // extra data structure. + y = -(extra_data->a * p.x() + extra_data->c) / extra_data->b; + } + else { + CGAL_assertion(xcv.degree_mask() == xcv.flag_mask(X_monotone_curve_2::DEGREE_2)); + + // In this case the y-coordinate is one of solutions to the quadratic + // equation: + // s*y^2 + (t*x(p) + v)*y + (r*x(p)^2 + u*x(p) + w) = 0 + Algebraic A = xcv.alg_s(); + Algebraic B = xcv.alg_t()*p.x() + xcv.alg_v(); + Algebraic C = (xcv.alg_r()*p.x() + xcv.alg_u())*p.x() + xcv.alg_w(); + + if (CGAL::sign(xcv.s()) == ZERO) { + // In this case A is 0 and we have a linear equation. + CGAL_assertion(CGAL::sign(B) != ZERO); + + y = -C / B; + } + else { + // Solve the quadratic equation. + Algebraic disc = B*B - 4*A*C; + + CGAL_assertion(CGAL::sign(disc) != NEGATIVE); + + // We take either the root involving -sqrt(disc) or +sqrt(disc) + // based on the information flags. + auto nt_traits = m_traits.m_nt_traits; + y = (xcv.test_flag(X_monotone_curve_2::PLUS_SQRT_DISC_ROOT)) ? + (nt_traits->sqrt(disc) - B) / (2*A) : + -(B + nt_traits->sqrt(disc)) / (2*A); + } + } + + // Return the computed point. + return Point_2(p.x(), y); + } + }; /*! Obtain a Compare_y_at_x_2 functor object. */ @@ -314,37 +392,164 @@ public: public: /*! Compares the y value of two x-monotone curves immediately to the left * of their intersection point. - * \param cv1 The first curve. - * \param cv2 The second curve. + * \param xcv1 The first curve. + * \param xcv2 The second curve. * \param p The intersection point. * \pre The point p lies on both curves, and both of them must be also be * defined (lexicographically) to its left. - * \return The relative position of cv1 with respect to cv2 immdiately to + * \return The relative position of xcv1 with respect to xcv2 immdiately to * the left of p: SMALLER, LARGER or EQUAL. */ - Comparison_result operator()(const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2, + Comparison_result operator()(const X_monotone_curve_2& xcv1, + const X_monotone_curve_2& xcv2, const Point_2& p) const { // Make sure that p lies on both curves, and that both are defined to its // left (so their left endpoint is lexicographically smaller than p). - CGAL_precondition(cv1.contains_point(p) && - cv2.contains_point(p)); + CGAL_precondition(xcv1.contains_point(p) && + xcv2.contains_point(p)); CGAL_precondition_code(const auto ker = m_traits.m_alg_kernel); - CGAL_precondition(ker->compare_xy_2_object()(p, cv1.left()) == LARGER && - ker->compare_xy_2_object()(p, cv2.left()) == LARGER); + CGAL_precondition(ker->compare_xy_2_object()(p, xcv1.left()) == LARGER && + ker->compare_xy_2_object()(p, xcv2.left()) == LARGER); // If one of the curves is vertical, it is below the other one. - if (cv1.is_vertical()) { + if (xcv1.is_vertical()) { // Check whether both are vertical: - return (cv2.is_vertical()) ? EQUAL : SMALLER; + return (xcv2.is_vertical()) ? EQUAL : SMALLER; } - else if (cv2.is_vertical()) return LARGER; + else if (xcv2.is_vertical()) return LARGER; // Compare the two curves immediately to the left of p: - return cv1.compare_to_left(cv2, p); + return compare_to_left(xcv1, xcv2, p); } + + private: + /*! Compare to arcs immediately to the leftt of their intersection point. + * \param arc The compared arc. + * \param p The reference intersection point. + * \return The relative position of the arcs to the left of p. + * \pre Both arcs we compare are not vertical segments. + */ + Comparison_result compare_to_left(const X_monotone_curve_2& xcv1, + const X_monotone_curve_2& xcv2, + const Point_2& p) + const + { + CGAL_precondition(! xcv1.test_flag(X_monotone_curve_2::IS_VERTICAL_SEGMENT) && + ! xcv2.test_flag(X_monotone_curve_2::IS_VERTICAL_SEGMENT)); + + // In case one arc is facing upwards and another facing downwards, it is + // clear that the one facing upward is above the one facing downwards. + if (m_traits.has_same_supporting_conic(xcv1, xcv2)) { + if (xcv1.test_flag(X_monotone_curve_2::FACING_UP) && + xcv2.test_flag(X_monotone_curve_2::FACING_DOWN)) + return LARGER; + else if (xcv1.test_flag(X_monotone_curve_2::FACING_DOWN) && + xcv2.test_flag(X_monotone_curve_2::FACING_UP)) + return SMALLER; + + // In this case the two arcs overlap. + CGAL_assertion(xcv1.facing_mask() == xcv2.facing_mask()); + + return EQUAL; + } + + // Compare the slopes of the two arcs at p, using their first-order + // partial derivatives. + Algebraic slope1_numer, slope1_denom; + Algebraic slope2_numer, slope2_denom; + + xcv1.derive_by_x_at(p, 1, slope1_numer, slope1_denom); + xcv2.derive_by_x_at(p, 1, slope2_numer, slope2_denom); + + // Check if any of the slopes is vertical. + const bool is_vertical_slope1 = (CGAL::sign (slope1_denom) == ZERO); + const bool is_vertical_slope2 = (CGAL::sign (slope2_denom) == ZERO); + + if (! is_vertical_slope1 && ! is_vertical_slope2) { + // The two derivatives at p are well-defined: use them to determine + // which arc is above the other (the one with a larger slope is below). + Comparison_result slope_res = CGAL::compare(slope2_numer*slope1_denom, + slope1_numer*slope2_denom); + + if (slope_res != EQUAL) return slope_res; + + // Use the second-order derivative. + xcv1.derive_by_x_at(p, 2, slope1_numer, slope1_denom); + xcv2.derive_by_x_at(p, 2, slope2_numer, slope2_denom); + + slope_res = CGAL::compare(slope1_numer*slope2_denom, + slope2_numer*slope1_denom); + + if (slope_res != EQUAL) return (slope_res); + + // Use the third-order derivative. + xcv1.derive_by_x_at(p, 3, slope1_numer, slope1_denom); + xcv2.derive_by_x_at(p, 3, slope2_numer, slope2_denom); + + slope_res = CGAL::compare(slope2_numer*slope1_denom, + slope1_numer*slope2_denom); + + // \todo Handle higher-order derivatives: + CGAL_assertion(slope_res != EQUAL); + + return slope_res; + } + else if (! is_vertical_slope2) { + // The first arc has a vertical slope at p: check whether it is + // facing upwards or downwards and decide accordingly. + CGAL_assertion(xcv1.facing_mask() != 0); + + return (xcv1.test_flag(X_monotone_curve_2::FACING_UP)) ? LARGER : SMALLER; + } + else if (! is_vertical_slope1) { + // The second arc has a vertical slope at p_int: check whether it is + // facing upwards or downwards and decide accordingly. + CGAL_assertion(xcv2.facing_mask() != 0); + + return (xcv2.test_flag(X_monotone_curve_2::FACING_UP)) ? SMALLER : LARGER; + } + + // The two arcs have vertical slopes at p_int: + // First check whether one is facing up and one down. In this case the + // comparison result is trivial. + if (xcv1.test_flag(X_monotone_curve_2::FACING_UP) && + xcv2.test_flag(X_monotone_curve_2::FACING_DOWN)) + return LARGER; + else if (xcv1.test_flag(X_monotone_curve_2::FACING_DOWN) && + xcv2.test_flag(X_monotone_curve_2::FACING_UP)) + return SMALLER; + + // Compute the second-order derivative by y and act according to it. + xcv1.derive_by_y_at(p, 2, slope1_numer, slope1_denom); + xcv2.derive_by_y_at(p, 2, slope2_numer, slope2_denom); + + Comparison_result slope_res = + CGAL::compare(slope2_numer*slope1_denom, slope1_numer*slope2_denom); + + // If necessary, use the third-order derivative by y. + if (slope_res == EQUAL) { + // \todo Check this! + xcv1.derive_by_y_at(p, 3, slope1_numer, slope1_denom); + xcv2.derive_by_y_at(p, 3, slope2_numer, slope2_denom); + + slope_res = + CGAL::compare(slope2_numer*slope1_denom, slope1_numer*slope2_denom); + } + + // \todo Handle higher-order derivatives: + CGAL_assertion(slope_res != EQUAL); + + // Check whether both are facing up. + if (xcv1.test_flag(X_monotone_curve_2::FACING_UP) && + xcv2.test_flag(X_monotone_curve_2::FACING_UP)) + return ((slope_res == LARGER) ? SMALLER : LARGER); + + // Both are facing down. + return slope_res; + } + }; /*! Obtain a Compare_y_at_x_left_2 functor object. */ @@ -352,57 +557,202 @@ public: { return Compare_y_at_x_left_2(*this); } class Compare_y_at_x_right_2 { + protected: + using Traits = Arr_conic_traits_2; + + /*! The traits (in case it has state) */ + const Traits& m_traits; + + /*! Constructor + * \param traits the traits. + */ + Compare_y_at_x_right_2(const Traits& traits) : m_traits(traits) {} + + friend class Arr_conic_traits_2; + public: /*! Compares the y value of two x-monotone curves immediately to the right * of their intersection point. - * \param cv1 The first curve. - * \param cv2 The second curve. + * \param xcv1 The first curve. + * \param xcv2 The second curve. * \param p The intersection point. * \pre The point p lies on both curves, and both of them must be also be * defined (lexicographically) to its right. - * \return The relative position of cv1 with respect to cv2 immdiately to + * \return The relative position of xcv1 with respect to xcv2 immdiately to * the right of p: SMALLER, LARGER or EQUAL. */ - Comparison_result operator()(const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2, + Comparison_result operator()(const X_monotone_curve_2& xcv1, + const X_monotone_curve_2& xcv2, const Point_2& p) const { // Make sure that p lies on both curves, and that both are defined to its // left (so their left endpoint is lexicographically smaller than p). - CGAL_precondition(cv1.contains_point(p) && cv2.contains_point(p)); - CGAL_precondition_code(Alg_kernel ker;); - CGAL_precondition(ker.compare_xy_2_object()(p, cv1.right()) == SMALLER && - ker.compare_xy_2_object()(p, cv2.right()) == SMALLER); + CGAL_precondition(xcv1.contains_point(p) && xcv2.contains_point(p)); + CGAL_precondition_code(const auto ker = m_traits.m_alg_kernel); + CGAL_precondition_code(auto cmp_xy = ker->compare_xy_2_object()); + CGAL_precondition(cmp_xy(p, xcv1.right()) == SMALLER && + cmp_xy(p, xcv2.right()) == SMALLER); // If one of the curves is vertical, it is above the other one. - if (cv1.is_vertical()) { + if (xcv1.is_vertical()) // Check whether both are vertical: - return (cv2.is_vertical()) ? EQUAL : LARGER; - } - else if (cv2.is_vertical()) return SMALLER; + return (xcv2.is_vertical()) ? EQUAL : LARGER; + else if (xcv2.is_vertical()) return SMALLER; // Compare the two curves immediately to the right of p: - return cv1.compare_to_right(cv2, p); + return compare_to_right(xcv1, xcv2, p); } + + private: + /*! Compare to arcs immediately to the right of their intersection point. + * \param arc The compared arc. + * \param p The reference intersection point. + * \return The relative position of the arcs to the right of p. + * \pre Both arcs we compare are not vertical segments. + */ + Comparison_result compare_to_right(const X_monotone_curve_2& xcv1, + const X_monotone_curve_2& xcv2, + const Point_2& p) const { + CGAL_precondition(! xcv1.test_flag(X_monotone_curve_2::IS_VERTICAL_SEGMENT) && + ! xcv2.test_flag(X_monotone_curve_2::IS_VERTICAL_SEGMENT)); + + // In case one arc is facing upwards and another facing downwards, it is + // clear that the one facing upward is above the one facing downwards. + if (m_traits.has_same_supporting_conic(xcv1, xcv2)) { + if (xcv1.test_flag(X_monotone_curve_2::FACING_UP) && + xcv2.test_flag(X_monotone_curve_2::FACING_DOWN)) + return LARGER; + else if (xcv1.test_flag(X_monotone_curve_2::FACING_DOWN) && + xcv2.test_flag(X_monotone_curve_2::FACING_UP)) + return SMALLER; + + // In this case the two arcs overlap. + CGAL_assertion(xcv1.facing_mask() == xcv2.facing_mask()); + return EQUAL; + } + + // Compare the slopes of the two arcs at p, using their first-order + // partial derivatives. + Algebraic slope1_numer, slope1_denom; + Algebraic slope2_numer, slope2_denom; + + xcv1.derive_by_x_at(p, 1, slope1_numer, slope1_denom); + xcv2.derive_by_x_at(p, 1, slope2_numer, slope2_denom); + + // Check if any of the slopes is vertical. + const bool is_vertical_slope1 = (CGAL::sign(slope1_denom) == ZERO); + const bool is_vertical_slope2 = (CGAL::sign(slope2_denom) == ZERO); + + if (! is_vertical_slope1 && ! is_vertical_slope2) { + // The two derivatives at p are well-defined: use them to determine + // which arc is above the other (the one with a larger slope is below). + Comparison_result slope_res = + CGAL::compare(slope1_numer*slope2_denom, slope2_numer*slope1_denom); + + if (slope_res != EQUAL) return (slope_res); + + // Use the second-order derivative. + xcv1.derive_by_x_at(p, 2, slope1_numer, slope1_denom); + xcv2.derive_by_x_at(p, 2, slope2_numer, slope2_denom); + + slope_res = + CGAL::compare(slope1_numer*slope2_denom, slope2_numer*slope1_denom); + + if (slope_res != EQUAL) return (slope_res); + + // Use the third-order derivative. + xcv1.derive_by_x_at(p, 3, slope1_numer, slope1_denom); + xcv2.derive_by_x_at(p, 3, slope2_numer, slope2_denom); + + slope_res = + CGAL::compare(slope1_numer*slope2_denom, slope2_numer*slope1_denom); + + // \todo Handle higher-order derivatives: + CGAL_assertion(slope_res != EQUAL); + + return slope_res; + } + else if (! is_vertical_slope2) { + // The first arc has a vertical slope at p: check whether it is + // facing upwards or downwards and decide accordingly. + CGAL_assertion(xcv1.facing_mask() != 0); + + return (xcv1.test_flag(X_monotone_curve_2::FACING_UP)) ? LARGER : SMALLER; + } + else if (! is_vertical_slope1) { + // The second arc has a vertical slope at p_int: check whether it is + // facing upwards or downwards and decide accordingly. + CGAL_assertion(xcv2.facing_mask() != 0); + + return (xcv2.test_flag(X_monotone_curve_2::FACING_UP)) ? SMALLER : LARGER; + } + + // The two arcs have vertical slopes at p_int: + // First check whether one is facing up and one down. In this case the + // comparison result is trivial. + if (xcv1.test_flag(X_monotone_curve_2::FACING_UP) && + xcv2.test_flag(X_monotone_curve_2::FACING_DOWN)) return LARGER; + else if (xcv1.test_flag(X_monotone_curve_2::FACING_DOWN) && + xcv2.test_flag(X_monotone_curve_2::FACING_UP)) return SMALLER; + + // Compute the second-order derivative by y and act according to it. + xcv1.derive_by_y_at(p, 2, slope1_numer, slope1_denom); + xcv2.derive_by_y_at(p, 2, slope2_numer, slope2_denom); + + Comparison_result slope_res = + CGAL::compare(slope1_numer*slope2_denom, slope2_numer*slope1_denom); + + // If necessary, use the third-order derivative by y. + if (slope_res == EQUAL) { + // \todo Check this! + xcv1.derive_by_y_at(p, 3, slope1_numer, slope1_denom); + xcv2.derive_by_y_at(p, 3, slope2_numer, slope2_denom); + + slope_res = + CGAL::compare(slope2_numer*slope1_denom, slope1_numer*slope2_denom); + } + + // \todo Handle higher-order derivatives: + CGAL_assertion(slope_res != EQUAL); + + if (xcv1.test_flag(X_monotone_curve_2::FACING_UP) && + xcv2.test_flag(X_monotone_curve_2::FACING_UP)) + return (slope_res == LARGER) ? SMALLER : LARGER; // both are facing up + return slope_res; // both are facing down + } + }; /*! Obtain a Compare_y_at_x_right_2 functor object. */ Compare_y_at_x_right_2 compare_y_at_x_right_2_object() const - { return Compare_y_at_x_right_2(); } + { return Compare_y_at_x_right_2(*this); } class Equal_2 { + protected: + using Traits = Arr_conic_traits_2; + + /*! The traits (in case it has state) */ + const Traits& m_traits; + + /*! Constructor + * \param traits the traits. + */ + Equal_2(const Traits& traits) : m_traits(traits) {} + + friend class Arr_conic_traits_2; + public: /*! Check whether the two x-monotone curves are the same (have the same * graph). - * \param cv1 The first curve. - * \param cv2 The second curve. + * \param xcv1 The first curve. + * \param xcv2 The second curve. * \return (true) if the two curves are the same; (false) otherwise. */ - bool operator()(const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2) const + bool operator()(const X_monotone_curve_2& xcv1, + const X_monotone_curve_2& xcv2) const { - if (&cv1 == &cv2) return true; - return cv1.equals(cv2); + if (&xcv1 == &xcv2) return true; + return xcv1.equals(xcv2); } /*! Check whether the two points are the same. @@ -412,14 +762,12 @@ public: */ bool operator()(const Point_2& p1, const Point_2& p2) const { if (&p1 == &p2) return (true); - - Alg_kernel ker; - return(ker.compare_xy_2_object()(p1, p2) == EQUAL); + return(m_traits.m_alg_kernel->compare_xy_2_object()(p1, p2) == EQUAL); } }; /*! Obtain an Equal_2 functor object. */ - Equal_2 equal_2_object() const { return Equal_2(); } + Equal_2 equal_2_object() const { return Equal_2(*this); } //@} /// \name Intersections, subdivisions, and mergings @@ -456,6 +804,8 @@ public: typedef boost::variant Make_x_monotone_result; + auto ctr_xcv = m_traits.construct_x_monotone_curve_2_object(); + // Increment the serial number of the curve cv, which will serve as its // unique identifier. auto index = Traits::get_index(); @@ -466,7 +816,7 @@ public: auto n_vtan_ps = cv.vertical_tangency_points(vtan_ps); if (n_vtan_ps == 0) { // In case the given curve is already x-monotone: - *oi++ = Make_x_monotone_result(X_monotone_curve_2(cv, conic_id)); + *oi++ = Make_x_monotone_result(ctr_xcv(cv, conic_id)); return oi; } @@ -478,23 +828,19 @@ public: // In case the curve is a full conic, split it into two x-monotone // arcs, one going from ps[0] to ps[1], and the other from ps[1] to // ps[0]. - *oi++ = Make_x_monotone_result(X_monotone_curve_2(cv, vtan_ps[0], - vtan_ps[1], - conic_id)); - *oi++ = Make_x_monotone_result(X_monotone_curve_2(cv, vtan_ps[1], - vtan_ps[0], - conic_id)); + *oi++ = Make_x_monotone_result(ctr_xcv(cv, vtan_ps[0], + vtan_ps[1], conic_id)); + *oi++ = Make_x_monotone_result(ctr_xcv(cv, vtan_ps[1], + vtan_ps[0], conic_id)); } else { if (n_vtan_ps == 1) { // Split the arc into two x-monotone sub-curves: one going from the // arc source to ps[0], and the other from ps[0] to the target. - *oi++ = Make_x_monotone_result(X_monotone_curve_2(cv, cv.source(), - vtan_ps[0], - conic_id)); - *oi++ = Make_x_monotone_result(X_monotone_curve_2(cv, vtan_ps[0], - cv.target(), - conic_id)); + *oi++ = Make_x_monotone_result(ctr_xcv(cv, cv.source(), + vtan_ps[0], conic_id)); + *oi++ = Make_x_monotone_result(ctr_xcv(cv, vtan_ps[0], + cv.target(), conic_id)); } else { CGAL_assertion(n_vtan_ps == 2); @@ -524,19 +870,16 @@ public: } // Split the arc into three x-monotone sub-curves. - *oi++ = Make_x_monotone_result(X_monotone_curve_2(cv, cv.source(), - vtan_ps[ind_first], - conic_id)); + *oi++ = Make_x_monotone_result(ctr_xcv(cv, cv.source(), + vtan_ps[ind_first], + conic_id)); - *oi++ = Make_x_monotone_result(X_monotone_curve_2(cv, - vtan_ps[ind_first], - vtan_ps[ind_second], - conic_id)); + *oi++ = Make_x_monotone_result(ctr_xcv(cv, vtan_ps[ind_first], + vtan_ps[ind_second], + conic_id)); - *oi++ = Make_x_monotone_result(X_monotone_curve_2(cv, - vtan_ps[ind_second], - cv.target(), - conic_id)); + *oi++ = Make_x_monotone_result(ctr_xcv(cv, vtan_ps[ind_second], + cv.target(), conic_id)); } } @@ -549,6 +892,19 @@ public: { return Make_x_monotone_2(*this); } class Split_2 { + protected: + using Traits = Arr_conic_traits_2; + + /*! The traits (in case it has state) */ + const Traits& m_traits; + + /*! Constructor + * \param traits the traits. + */ + Split_2(const Traits& traits) : m_traits(traits) {} + + friend class Arr_conic_traits_2; + public: /*! Split a given x-monotone curve at a given point into two sub-curves. * \param cv The curve to split @@ -557,13 +913,57 @@ public: * \param c2 Output: The right resulting subcurve (p is its left endpoint). * \pre p lies on cv but is not one of its end-points. */ - void operator()(const X_monotone_curve_2& cv, const Point_2 & p, - X_monotone_curve_2& c1, X_monotone_curve_2& c2) const - { cv.split(p, c1, c2); } + void operator()(const X_monotone_curve_2& xcv, const Point_2 & p, + X_monotone_curve_2& xcv1, X_monotone_curve_2& xcv2) const + { split(xcv, p, xcv1, xcv2); } + + private: + /*! Split the arc into two at a given split point. + * \param p The split point. + * \param xcv1 Output: The first resulting arc, lying to the left of p. + * \param xcv2 Output: The first resulting arc, lying to the right of p. + * \pre p lies in the interior of the arc (not one of its endpoints). + */ + void split(const X_monotone_curve_2& xcv, const Point_2& p, + X_monotone_curve_2& xcv1, X_monotone_curve_2& xcv2) const { + // Make sure that p lies on the interior of the arc. + CGAL_precondition_code(auto eq = m_traits.m_alg_kernel->equal_2_object()); + CGAL_precondition(xcv.contains_point(p) && + ! eq(p, xcv.source()) && ! eq(p, xcv.target())); + + // Make copies of the current arc. + xcv1 = xcv; + xcv2 = xcv; + + // Assign the endpoints of the arc. + if (xcv.test_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT)) { + // The arc is directed from left to right, so p becomes xcv1's target + // and xcv2's source. + xcv1.set_target(p); + xcv2.set_source(p); + + if (! p.is_generating_conic(xcv.id())) { + xcv1.target().set_generating_conic(xcv.id()); + xcv2.source().set_generating_conic(xcv.id()); + } + } + else { + // The arc is directed from right to left, so p becomes xcv2's target + // and xcv1's source. + xcv1.set_source(p); + xcv2.set_target(p); + + if (! p.is_generating_conic(xcv.id())) { + xcv1.source().set_generating_conic(xcv.id()); + xcv2.target().set_generating_conic(xcv.id()); + } + } + } + }; /*! Obtain a Split_2 functor object. */ - Split_2 split_2_object() const { return Split_2(); } + Split_2 split_2_object() const { return Split_2(*this); } class Intersect_2 { private: @@ -592,6 +992,19 @@ public: Intersect_2 intersect_2_object() const { return (Intersect_2(inter_map)); } class Are_mergeable_2 { + protected: + using Traits = Arr_conic_traits_2; + + /*! The traits (in case it has state) */ + const Traits& m_traits; + + /*! Constructor + * \param traits the traits (in case it has state) + */ + Are_mergeable_2(const Traits& traits) : m_traits(traits) {} + + friend class Arr_conic_traits_2; + public: /*! Check whether it is possible to merge two given x-monotone curves. * \param cv1 The first curve. @@ -599,14 +1012,32 @@ public: * \return (true) if the two curves are mergeable - if they are supported * by the same line and share a common endpoint; (false) otherwise. */ - bool operator()(const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2) const - { return cv1.can_merge_with(cv2); } + bool operator()(const X_monotone_curve_2& xcv1, + const X_monotone_curve_2& xcv2) const + { return can_merge_with(xcv1, xcv2); } + + private: + /*! Check whether it is possible to merge the arc with the given arc. + * \param arc The query arc. + * \return (true) if it is possible to merge the two arcs; + * (false) otherwise. + */ + bool can_merge_with(const X_monotone_curve_2& xcv1, + const X_monotone_curve_2& xcv2) const { + // In order to merge the two arcs, they should have the same supporting + // conic. + if (! m_traits.has_same_supporting_conic(xcv1, xcv2)) return false; + + // Check if the left endpoint of one curve is the right endpoint of the + // other. + auto eq = m_traits.m_alg_kernel->equal_2_object(); + return (eq(xcv1.right(), xcv2.left()) || eq(xcv1.left(), xcv2.right())); + } }; /*! Obtain an Are_mergeable_2 functor object. */ Are_mergeable_2 are_mergeable_2_object() const - { return Are_mergeable_2(); } + { return Are_mergeable_2(*this); } /*! \class Merge_2 * A functor that merges two x-monotone arcs into one. @@ -632,14 +1063,37 @@ public: * \param c Output: The merged curve. * \pre The two curves are mergeable. */ - void operator()(const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2, - X_monotone_curve_2& c) const + void operator()(const X_monotone_curve_2& xcv1, + const X_monotone_curve_2& xcv2, + X_monotone_curve_2& xcv) const { - CGAL_precondition(m_traits->are_mergeable_2_object()(cv2, cv1)); + CGAL_precondition(m_traits.are_mergeable_2_object()(xcv2, xcv1)); + xcv = xcv1; + merge(xcv, xcv2); + } - c = cv1; - c.merge (cv2); + private: + /*! Merge the current arc with the given arc. + * \param arc The arc to merge with. + * \pre The two arcs are mergeable. + */ + void merge(X_monotone_curve_2& xcv1, const X_monotone_curve_2& xcv2) const { + // Check whether we should extend the arc to the left or to the right. + auto eq = m_traits.m_alg_kernel->equal_2_object(); + if (eq(xcv1.right(), xcv2.left())) { + // Extend the arc to the right. + if (xcv1.test_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT)) + xcv1.set_target(xcv2.right()); + else xcv1.set_source(xcv2.right()); + } + else { + CGAL_precondition(eq(xcv1.left(), xcv2.right())); + + // Extend the arc to the left. + if (xcv1.test_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT)) + xcv1.set_source(xcv2.left()); + else xcv1.set_target(xcv2.left()); + } } }; @@ -689,9 +1143,37 @@ public: { return std::make_pair(operator()(p, 0), operator()(p, 1)); } /*! Obtain an approximation of an x-monotone curve. - * - * ELLIPSE - * ------- + */ + template + OutputIterator operator()(const X_monotone_curve_2& arc, OutputIterator oi, + double density = 1) const { + if (arc.orientation() == COLLINEAR) + return approximate_segment(arc, oi, density); + CGAL::Sign sign_conic = CGAL::sign(4*arc.r()*arc.s() - arc.t()*arc.t()); + if (sign_conic == POSITIVE) + return approximate_hyperbola(arc, oi, density); + if (sign_conic == NEGATIVE) + return approximate_ellipse(arc, oi, density); + return approximate_parabola(arc, oi, density); + } + + private: + /*! Handle segments. + */ + template + OutputIterator approximate_segment(const X_monotone_curve_2& arc, + OutputIterator oi, + double density = 1) const { + auto xs = CGAL::to_double(arc.source().x()); + auto ys = CGAL::to_double(arc.source().y()); + auto xt = CGAL::to_double(arc.target().x()); + auto yt = CGAL::to_double(arc.target().y()); + *oi++ = Approximate_point_2(xs, ys); + *oi++ = Approximate_point_2(xt, yt); + return oi; + } + + /*! Handle ellipses. * The general equation of an ellipse is: * r·𝑥^2 + s·𝑦^2 + t·𝑥·𝑦 + u·𝑥 + v·𝑦 + w = 0 * where 4·r·s−t^2 > 0 @@ -759,17 +1241,13 @@ public: * spans a unit length. */ template - OutputIterator operator()(const X_monotone_curve_2& arc, OutputIterator oi, - double density = 1) const { + OutputIterator approximate_ellipse(const X_monotone_curve_2& arc, + OutputIterator oi, + double density = 1) const { auto xs = CGAL::to_double(arc.source().x()); auto ys = CGAL::to_double(arc.source().y()); auto xt = CGAL::to_double(arc.target().x()); auto yt = CGAL::to_double(arc.target().y()); - if (arc.orientation() == COLLINEAR) { - *oi++ = Approximate_point_2(xs, ys); - *oi++ = Approximate_point_2(xt, yt); - return oi; - } if (arc.orientation() == CLOCKWISE) { std::swap(xs, xt); std::swap(ys, yt); @@ -785,82 +1263,148 @@ public: std::cout << "curve: (" << xs << "," << ys << ") => (" << xt << "," << yt << ")" << std::endl; - { - // Compute the cos and sin of the rotation angle - // In case of a circle, cost == 1 and sint = 0 - double cost(1), sint(0); + // Compute the cos and sin of the rotation angle + // In case of a circle, cost == 1 and sint = 0 + double cost(1), sint(0); - if (r != s) { - auto tan_2t = t / (r - s); - auto cos_2t = std::sqrt(1 / (tan_2t*tan_2t + 1)); - cost = std::sqrt((1 + cos_2t) / 2); - sint = std::sqrt((1 - cos_2t) / 2); - } - std::cout << "sint, cost: " << sint << "," << cost << std::endl; - - // Compute the coefficients of the unrotated ellipse - auto r_m = r * cost*cost + t*cost*sint + s*sint*sint; - auto t_m = 0; - auto s_m = r * sint*sint - t*cost*sint + s*cost*cost; - auto u_m = u*cost + v*sint; - auto v_m = - u*sint + v*cost; - auto w_m = w; - - std::cout << r_m << "," << s_m << "," << t_m << "," - << u_m << "," << v_m << "," << w_m << std::endl; - - // Compute the center of the inversly rotated ellipse: - auto cx_m = -u_m / (2*r_m); - auto cy_m = -v_m / (2*s_m); - - // Compute the radi of the ellipse: - auto numerator = -4*w_m*r_m*s_m + s_m*u_m*u_m + r_m*v_m*v_m; - auto a = std::sqrt(numerator / (4*r_m*r_m*s_m)); - auto b = std::sqrt(numerator / (4*r_m*s_m*s_m)); - std::cout << "a, b: " << a << "," << b << std::endl; - - // Compute the center (cx,cy) of the ellipse, rotating back: - auto cx = cx_m*cost - cy_m*sint; - auto cy = cx_m*sint + cy_m*cost; - std::cout << "center: " << cx << "," << cy << std::endl; - - // Compute the parameters ts and tt such that - // source == (x(ts),y(ts)), and - // target == (x(tt),y(tt)) - auto xds = xs - cx; - auto yds = ys - cy; - auto ts = std::atan2(a*(cost*yds - sint*xds),b*(sint*yds + cost*xds)); - if (ts < 0) ts += 2*M_PI; - auto xdt = xt - cx; - auto ydt = yt - cy; - auto tt = std::atan2(a*(cost*ydt - sint*xdt),b*(sint*ydt + cost*xdt)); - if (tt < 0) tt += 2*M_PI; - if (tt < ts) tt += 2*M_PI; - std::cout << "ts,tt: " << ts << "," << tt << std::endl; - - namespace bm = boost::math; - auto ratio = b/a; - auto k = std::sqrt(1 - (ratio*ratio)); - auto ds = a*bm::ellint_2(k, ts); - auto dt = a*bm::ellint_2(k, tt); - std::cout << "ds,dt: " << ds << ", " << dt << std::endl; - auto len = dt - ds; - auto size = static_cast(len*density); - - auto delta = (tt - ts) / (size-1); - auto t(ts); - *oi++ = Approximate_point_2(xs, ys); - t += delta; - for (size_t i = 1; i < size-1; ++i) { - auto x = a*std::cos(t)*cost - b*std::sin(t)*sint + cx; - auto y = a*std::cos(t)*sint + b*std::sin(t)*cost + cy; - std::cout << "t, (x, y): " << t << ", (" << x << "," << y << ")" - << std::endl; - *oi++ = Approximate_point_2(x, y); - t += delta; - } - *oi++ = Approximate_point_2(xt, yt); + if (r != s) { + auto tan_2t = t / (r - s); + auto cos_2t = std::sqrt(1 / (tan_2t*tan_2t + 1)); + cost = std::sqrt((1 + cos_2t) / 2); + sint = std::sqrt((1 - cos_2t) / 2); } + std::cout << "sint, cost: " << sint << "," << cost << std::endl; + + // Compute the coefficients of the unrotated ellipse + auto r_m = r * cost*cost + t*cost*sint + s*sint*sint; + auto t_m = 0; + auto s_m = r * sint*sint - t*cost*sint + s*cost*cost; + auto u_m = u*cost + v*sint; + auto v_m = - u*sint + v*cost; + auto w_m = w; + + std::cout << r_m << "," << s_m << "," << t_m << "," + << u_m << "," << v_m << "," << w_m << std::endl; + + // Compute the center of the inversly rotated ellipse: + auto cx_m = -u_m / (2*r_m); + auto cy_m = -v_m / (2*s_m); + + // Compute the radi of the ellipse: + auto numerator = -4*w_m*r_m*s_m + s_m*u_m*u_m + r_m*v_m*v_m; + auto a = std::sqrt(numerator / (4*r_m*r_m*s_m)); + auto b = std::sqrt(numerator / (4*r_m*s_m*s_m)); + std::cout << "a, b: " << a << "," << b << std::endl; + + // Compute the center (cx,cy) of the ellipse, rotating back: + auto cx = cx_m*cost - cy_m*sint; + auto cy = cx_m*sint + cy_m*cost; + std::cout << "center: " << cx << "," << cy << std::endl; + + // Compute the parameters ps and pt such that + // source == (x(ps),y(ps)), and + // target == (x(pt),y(pt)) + auto xds = xs - cx; + auto yds = ys - cy; + auto ps = std::atan2(a*(cost*yds - sint*xds),b*(sint*yds + cost*xds)); + if (ps < 0) ps += 2*M_PI; + auto xdt = xt - cx; + auto ydt = yt - cy; + auto pt = std::atan2(a*(cost*ydt - sint*xdt),b*(sint*ydt + cost*xdt)); + if (pt < 0) pt += 2*M_PI; + if (pt < ps) pt += 2*M_PI; + std::cout << "ps,pt: " << ps << "," << pt << std::endl; + + namespace bm = boost::math; + auto ratio = b/a; + auto k = std::sqrt(1 - (ratio*ratio)); + auto ds = a*bm::ellint_2(k, ps); + auto dt = a*bm::ellint_2(k, pt); + std::cout << "ds,dt: " << ds << ", " << dt << std::endl; + auto len = dt - ds; + auto size = static_cast(len*density); + + auto delta = (pt - ps) / (size-1); + auto p(ps); + *oi++ = Approximate_point_2(xs, ys); + p += delta; + for (size_t i = 1; i < size-1; ++i) { + auto x = a*std::cos(p)*cost - b*std::sin(p)*sint + cx; + auto y = a*std::cos(p)*sint + b*std::sin(p)*cost + cy; + std::cout << "t, (x, y): " << t << ", (" << x << "," << y << ")" + << std::endl; + *oi++ = Approximate_point_2(x, y); + t += delta; + } + *oi++ = Approximate_point_2(xt, yt); + return oi; + } + + /*! Handle parabolas. + */ + template + OutputIterator approximate_parabola(const X_monotone_curve_2& arc, + OutputIterator oi, + double density = 1) const { + auto xs = CGAL::to_double(arc.source().x()); + auto ys = CGAL::to_double(arc.source().y()); + auto xt = CGAL::to_double(arc.target().x()); + auto yt = CGAL::to_double(arc.target().y()); + if (arc.orientation() == CLOCKWISE) { + std::swap(xs, xt); + std::swap(ys, yt); + } + auto r = CGAL::to_double(arc.r()); + auto s = CGAL::to_double(arc.s()); + auto t = CGAL::to_double(arc.t()); + auto u = CGAL::to_double(arc.u()); + auto v = CGAL::to_double(arc.v()); + auto w = CGAL::to_double(arc.w()); + std::cout << r << "," << s << "," << t << "," << u << "," << v << "," << w + << std::endl; + std::cout << "curve: (" << xs << "," << ys + << ") => (" << xt << "," << yt << ")" + << std::endl; + // Compute the cos and sin of the rotation angle + // In case of a circle, cost == 1 and sint = 0 + double cost(1), sint(0); + + if (r != s) { + auto tan_2t = t / (r - s); + auto cos_2t = std::sqrt(1 / (tan_2t*tan_2t + 1)); + cost = std::sqrt((1 + cos_2t) / 2); + sint = std::sqrt((1 - cos_2t) / 2); + } + std::cout << "sint, cost: " << sint << "," << cost << std::endl; + + // Compute the coefficients of the unrotated ellipse + auto r_m = r * cost*cost + t*cost*sint + s*sint*sint; + auto t_m = 0; + auto s_m = r * sint*sint - t*cost*sint + s*cost*cost; + auto u_m = u*cost + v*sint; + auto v_m = - u*sint + v*cost; + auto w_m = w; + + std::cout << r_m << "," << s_m << "," << t_m << "," + << u_m << "," << v_m << "," << w_m << std::endl; + + *oi++ = Approximate_point_2(xs, ys); + *oi++ = Approximate_point_2(xt, yt); + return oi; + } + + /*! Handle hyperbolas. + */ + template + OutputIterator approximate_hyperbola(const X_monotone_curve_2& arc, + OutputIterator oi, + double density = 1) const { + auto xs = CGAL::to_double(arc.source().x()); + auto ys = CGAL::to_double(arc.source().y()); + auto xt = CGAL::to_double(arc.target().x()); + auto yt = CGAL::to_double(arc.target().y()); + *oi++ = Approximate_point_2(xs, ys); + *oi++ = Approximate_point_2(xt, yt); return oi; } }; @@ -870,20 +1414,151 @@ public: //! Functor class Construct_x_monotone_curve_2 { + using Traits = Arr_conic_traits_2; + + /*! The traits (in case it has state) */ + const Traits& m_traits; + + /*! Constructor + * \param traits the traits. + */ + Construct_x_monotone_curve_2(const Traits& traits) : m_traits(traits) {} + + friend class Arr_conic_traits_2; + public: + /*! Construct an x-monotone arc from a conic arc. + * \param cv The given (Curve_2) curve. + * \pre cv is x-monotone. + */ + X_monotone_curve_2 operator()(const Curve_2& cv) const { + X_monotone_curve_2 xcv(cv); + CGAL_precondition(xcv.is_valid() && xcv.is_x_monotone()); + m_traits.set_x_monotone(xcv); + return xcv; + } + + /*! Construct an x-monotone arc from a conic arc. + * \param xcv The given (Curve_2) curve. + * \param id The ID of the base curve. + */ + X_monotone_curve_2 operator()(const Curve_2& cv, const Conic_id& id) const + { + X_monotone_curve_2 xcv(cv, id); + CGAL_precondition(xcv.is_valid() && id.is_valid()); + m_traits.set_x_monotone(xcv); + return xcv; + } + + /*! Construct an x-monotone sub-arc from a conic arc. + * \param arc The given (base) arc. + * \param source The source point. + * \param target The target point. + * \param id The ID of the base arc. + */ + X_monotone_curve_2 operator()(const Curve_2& cv, + const Point_2& source, const Point_2& target, + const Conic_id& id) const + { + // Set the two endpoints. + X_monotone_curve_2 xcv(cv, id); + xcv.set_source(source); + xcv.set_target(target); + CGAL_precondition(xcv.is_valid() && id.is_valid()); + m_traits.set_x_monotone(xcv); + return xcv; + } + /*! Return an x-monotone curve connecting the two given endpoints. * \param p The first point. * \param q The second point. * \pre p and q must not be the same. * \return A segment connecting p and q. */ - X_monotone_curve_2 operator()(const Point_2& p, const Point_2& q) const - { return (X_monotone_curve_2(p, q)); } + X_monotone_curve_2 operator()(const Point_2& source, + const Point_2& target) const { + X_monotone_curve_2 xcv(source, target); + xcv.set_flag(X_monotone_curve_2::DEGREE_1); + auto cmp_xy = m_traits.m_alg_kernel->compare_xy_2_object(); + Comparison_result dir_res = cmp_xy(source, target); + if (dir_res == SMALLER) + xcv.set_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT); + + // Check if the segment is vertical. + if (CGAL::sign(xcv.extra_data()->b) == ZERO) + xcv.set_flag(X_monotone_curve_2::IS_VERTICAL_SEGMENT); + + // Mark that this is a special segment. + xcv.set_flag(X_monotone_curve_2::IS_SPECIAL_SEGMENT); + return xcv; + } + + /*! Construct a special segment of a given line connecting to given + * endpoints. + * \param a, b, c The coefficients of the supporting line (ax + by + c = 0). + * \param source The source point. + * \param target The target point. + */ + X_monotone_curve_2 operator()(const Algebraic& a, + const Algebraic& b, + const Algebraic& c, + const Point_2& source, + const Point_2& target) const { + X_monotone_curve_2 xcv(); + // Make sure the two endpoints lie on the supporting line. + CGAL_precondition + (CGAL::sign(a*source.x() + b*source.y() + c) == CGAL::ZERO); + + CGAL_precondition + (CGAL::sign(a*target.x() + b*target.y() + c) == CGAL::ZERO); + + // Set the basic properties and clear the m_info bits. + xcv.set_source(source); + xcv.set_target(target); + xcv.set_orientation(COLLINEAR); + xcv.reset_flags(); // inavlid arc + + // Check if the arc is directed right (the target is lexicographically + // greater than the source point), or to the left. + auto cmp_x = m_traits.m_alg_kernel->compare_x_2_object(); + Comparison_result res = cmp_x(source, target); + + xcv.set_flag(Curve_2::IS_VALID); + xcv.set_flag(X_monotone_curve_2::DEGREE_1); + if (res == EQUAL) { + // Mark that the segment is vertical. + xcv.set_flag(X_monotone_curve_2::IS_VERTICAL_SEGMENT); + + // Compare the endpoints lexicographically. + auto cmp_y = m_traits.m_alg_kernel->compare_y_2_object(); + res = cmp_y(source, target); + + CGAL_precondition(res != EQUAL); + if (res == EQUAL) { + xcv.reset_flags(); // inavlid arc + return xcv; + } + } + + if (res == SMALLER) xcv.set_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT); + + // Store the coefficients of the line. + auto extra_data = new typename Curve_2::Extra_data; + extra_data->a = a; + extra_data->b = b; + extra_data->c = c; + extra_data->side = ZERO; + xcv.set_extra_data(extra_data); + + // Mark that this is a special segment. + xcv.set_flag(X_monotone_curve_2::IS_SPECIAL_SEGMENT); + return xcv; + } }; /*! Obtain a Construct_x_monotone_curve_2 functor object. */ Construct_x_monotone_curve_2 construct_x_monotone_curve_2_object () const - { return Construct_x_monotone_curve_2(); } + { return Construct_x_monotone_curve_2(*this); } //! Constructor of conic arcs class Construct_curve_2 { @@ -943,14 +1618,14 @@ public: const Point_2& source, const Point_2& target) const { // Make sure that the source and the taget are not the same. const auto alg_kernel = m_traits.m_alg_kernel; - CGAL_precondition(alg_kernel->compare_xy_2_object()(source, target) != - EQUAL); + CGAL_precondition_code(auto eq = alg_kernel->compare_xy_2_object()); + CGAL_precondition(eq(source, target) != EQUAL); // Set the arc properties (no need to compute the orientation). Rational rat_coeffs[6] = {r, s, t, u, v, w}; Curve_2 arc; arc.set_orientation(orient); arc.set_endpoints(source, target); - set(arc, rat_coeffs); + m_traits.set(arc, rat_coeffs); return arc; } @@ -1198,7 +1873,7 @@ public: // Compute the x- and y-coordinates of intersection points of the base // conic and the k'th auxiliary conic. - int n_xs = compute_resultant_roots(nt_traits, + int n_xs = compute_resultant_roots(*nt_traits, base_coeffs[0], base_coeffs[1], base_coeffs[2], base_coeffs[3], base_coeffs[4], @@ -1211,7 +1886,7 @@ public: deg_aux, xs); - int n_ys = compute_resultant_roots(nt_traits, + int n_ys = compute_resultant_roots(*nt_traits, base_coeffs[1], base_coeffs[0], base_coeffs[2], base_coeffs[4], base_coeffs[3], @@ -1287,7 +1962,7 @@ public: } // Set the arc properties (no need to compute the orientation). - set(arc, rat_coeffs); + m_traits.set(arc, rat_coeffs); return arc; } @@ -1496,7 +2171,7 @@ public: * \return SMALLER if the curve is directed right; * LARGER if the curve is directed left. */ - Comparison_result operator() (const X_monotone_curve_2& cv) const { + Comparison_result operator()(const X_monotone_curve_2& cv) const { if (cv.is_directed_right()) return SMALLER; else return LARGER; } @@ -1564,9 +2239,55 @@ public: //check if the orientation conforms to the src and tgt. if( (xcv.is_directed_right() && compare_x_2(src, tgt) == LARGER) || (! xcv.is_directed_right() && compare_x_2(src, tgt) == SMALLER) ) - return (xcv.trim(tgt, src)); - else return (xcv.trim(src, tgt)); + return (trim(xcv, tgt, src)); + else return (trim(xcv, src, tgt)); } + + private: + /*! Trim the arc given its new endpoints. + * \param ps The new source point. + * \param pt The new target point. + * \return The new trimmed arc. + * \pre Both ps and pt lies on the arc and must conform with the current + * direction of the arc. + */ + X_monotone_curve_2 trim(const X_monotone_curve_2& xcv, + const Point_2& ps, + const Point_2& pt) const { + // Make sure that both ps and pt lie on the arc. + CGAL_precondition(xcv.contains_point(ps) && xcv.contains_point(pt)); + + // Make sure that the endpoints conform with the direction of the arc. + auto cmp_xy = m_traits.m_alg_kernel->compare_xy_2_object(); + if (! ((xcv.test_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT) && + (cmp_xy()(ps, pt) == SMALLER)) || + (xcv.test_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT) && + (cmp_xy(ps, pt) == LARGER)))) + { + // We are allowed to change the direction only in case of a segment. + CGAL_assertion(xcv.orientation() == COLLINEAR); + xcv.flip_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT); + } + + // Make a copy of the current arc and assign its endpoints. + auto eq = m_traits.m_alg_kernel->equal_2_object()(); + if (! eq(ps, xcv.source())) { + xcv.set_source(ps); + + if (! ps.is_generating_conic(xcv.id())) + xcv.m_source.set_generating_conic(xcv.id()); + } + + if (! eq(pt, xcv.target())) { + xcv.set_target(pt); + + if (! pt.is_generating_conic(xcv.id())) + xcv.m_target.set_generating_conic(xcv.id()); + } + + return xcv; + } + }; /*! Obtain a Trim_2 functor object. */ @@ -1735,7 +2456,6 @@ public: w = -int_coeffs[5]; } arc.set_coefficients(r, s, t, u, v, w); - std::cout << "s: " << s << std::endl; // Make sure the conic is a non-degenerate ellipse: // The coefficients should satisfy (4rs - t^2) > 0. @@ -1947,12 +2667,12 @@ public: // of the hyperbola. const auto& source = arc.source(); const auto& target = arc.target(); + arc.set_extra_data(extra_data); extra_data->side = arc.sign_of_extra_data(source.x(), source.y()); CGAL_assertion(extra_data->side != ZERO); CGAL_assertion(extra_data->side == arc.sign_of_extra_data(target.x(), target.y())); - arc.set_extra_data(extra_data); } /*! Find the x coordinates of the underlying conic at a given y coordinate. @@ -2080,6 +2800,169 @@ public: CGAL_assertion(m <= 2); return m; } + + /*! Set the properties of the x-monotone conic arc (for the usage of the + * constructors). + */ + void set_x_monotone(X_monotone_curve_2& xcv) const { + // Convert the coefficients of the supporting conic to algebraic numbers. + auto alg_r = m_nt_traits->convert(xcv.r()); + auto alg_s = m_nt_traits->convert(xcv.s()); + auto alg_t = m_nt_traits->convert(xcv.t()); + auto alg_u = m_nt_traits->convert(xcv.u()); + auto alg_v = m_nt_traits->convert(xcv.v()); + auto alg_w = m_nt_traits->convert(xcv.w()); + xcv.set_alg_coefficients(alg_r, alg_s, alg_t, alg_u, alg_v, alg_w); + + // Set the generating conic ID for the source and target points. + xcv.set_generating_conic(xcv.id()); + + // Update the m_info bits. + xcv.set_flag(Curve_2::IS_VALID); + xcv.reset_flag(Curve_2::IS_FULL_CONIC); + + // Check if the arc is directed right (the target is lexicographically + // greater than the source point), or to the left. + Comparison_result dir_res = + m_alg_kernel->compare_xy_2_object()(xcv.source(), xcv.target()); + CGAL_assertion(dir_res != EQUAL); + if (dir_res == SMALLER) xcv.set_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT); + + // Compute the degree of the underlying conic. + if ((CGAL::sign(xcv.r()) != ZERO) || + (CGAL::sign(xcv.s()) != ZERO) || + (CGAL::sign(xcv.t()) != ZERO)) + { + xcv.set_flag(X_monotone_curve_2::DEGREE_2); + + if (xcv.orientation() == COLLINEAR) { + xcv.set_flag(X_monotone_curve_2::IS_SPECIAL_SEGMENT); + + // Check whether the arc is a vertical segment: + auto cmp_x = m_alg_kernel->compare_x_2_object(); + if (cmp_x(xcv.source(), xcv.target()) == EQUAL) + xcv.set_flag(X_monotone_curve_2::IS_VERTICAL_SEGMENT); + return; + } + } + else { + CGAL_assertion((CGAL::sign(xcv.u()) != ZERO) || + (CGAL::sign(xcv.v()) != ZERO)); + + // The supporting curve is of the form: u*x + w = 0 + if (CGAL::sign(xcv.v()) == ZERO) + xcv.set_flag(X_monotone_curve_2::IS_VERTICAL_SEGMENT); + xcv.set_flag(X_monotone_curve_2::DEGREE_1); + return; + } + + if (xcv.orientation() == COLLINEAR) return; + + // Compute a midpoint between the source and the target and get the y-value + // of the arc at its x-coordiante. + Point_2 p_mid = + m_alg_kernel->construct_midpoint_2_object()(xcv.source(), xcv.target()); + Algebraic ys[2]; + CGAL_assertion_code(int n_ys = ) + conic_get_y_coordinates(xcv, p_mid.x(), ys); + + CGAL_assertion(n_ys != 0); + + // Check which solution lies on the x-monotone arc. + Point_2 p_arc_mid(p_mid.x(), ys[0]); + + if (is_strictly_between_endpoints(xcv, p_arc_mid)) { + // Mark that we should use the -sqrt(disc) root for points on this + // x-monotone arc. + xcv.reset_flag(X_monotone_curve_2::PLUS_SQRT_DISC_ROOT); + } + else { + CGAL_assertion(n_ys == 2); + p_arc_mid = Point_2(p_mid.x(), ys[1]); + CGAL_assertion(is_strictly_between_endpoints(xcv, p_arc_mid)); + + // Mark that we should use the +sqrt(disc) root for points on this + // x-monotone arc. + xcv.set_flag(X_monotone_curve_2::PLUS_SQRT_DISC_ROOT); + } + + // Check whether the conic is facing up or facing down: + // Check whether the arc (which is x-monotone of degree 2) lies above or + // below the segement that contects its two end-points (x1,y1) and (x2,y2). + // To do that, we find the y coordinate of a point on the arc whose x + // coordinate is (x1+x2)/2 and compare it to (y1+y2)/2. + auto cmp_y = m_alg_kernel->compare_y_2_object(); + Comparison_result res = cmp_y(p_arc_mid, p_mid); + + // If the arc is above the connecting segment, so it is facing upwards. + if (res == LARGER) xcv.set_flag(X_monotone_curve_2::FACING_UP); + // If the arc is below the connecting segment, so it is facing downwards. + else if (res == SMALLER) xcv.set_flag(X_monotone_curve_2::FACING_DOWN); + } + + /*! Check whether the two arcs have the same supporting conic. + * \param arc The compared arc. + * \return (true) if the two supporting conics are the same. + */ + bool has_same_supporting_conic(const X_monotone_curve_2& xcv1, + const X_monotone_curve_2& xcv2) const { + // Check if the two arcs originate from the same conic: + if ((xcv1.id() == xcv2.id()) && + xcv1.id().is_valid() && xcv2.id().is_valid()) + return true; + + // In case both arcs are collinear, check if they have the same + // supporting lines. + if ((xcv1.orientation() == COLLINEAR) && + (xcv2.orientation() == COLLINEAR)) { + // Construct the two supporting lines and compare them. + auto construct_line = m_alg_kernel->construct_line_2_object(); + typename Alg_kernel::Line_2 l1 = + construct_line(xcv1.source(), xcv1.target()); + typename Alg_kernel::Line_2 l2 = + construct_line(xcv2.source(), xcv2.target()); + auto equal = m_alg_kernel->equal_2_object(); + + if (equal(l1, l2)) return true; + + // Try to compare l1 with the opposite of l2. + l2 = construct_line(xcv2.target(), xcv2.source()); + + return equal(l1, l2); + } + else if ((xcv1.orientation() == COLLINEAR) || + (xcv2.orientation() == COLLINEAR)) { + // Only one arc is collinear, so the supporting curves cannot be the + // same: + return false; + } + + // Check whether the coefficients of the two supporting conics are equal + // up to a constant factor. + Integer factor1 = 1; + Integer factor2 = 1; + + if (CGAL::sign(xcv1.r()) != ZERO) factor1 = xcv1.r(); + else if (CGAL::sign(xcv1.s()) != ZERO) factor1 = xcv1.s(); + else if (CGAL::sign(xcv1.t()) != ZERO) factor1 = xcv1.t(); + else if (CGAL::sign(xcv1.u()) != ZERO) factor1 = xcv1.u(); + else if (CGAL::sign(xcv1.v()) != ZERO) factor1 = xcv1.v(); + else if (CGAL::sign(xcv1.w()) != ZERO) factor1 = xcv1.w(); + + if (CGAL::sign(xcv2.r()) != ZERO) factor2 = xcv2.r(); + else if (CGAL::sign(xcv2.s()) != ZERO) factor2 = xcv2.s(); + else if (CGAL::sign(xcv2.t()) != ZERO) factor2 = xcv2.t(); + else if (CGAL::sign(xcv2.u()) != ZERO) factor2 = xcv2.u(); + else if (CGAL::sign(xcv2.v()) != ZERO) factor2 = xcv2.v(); + else if (CGAL::sign(xcv2.w()) != ZERO) factor2 = xcv2.w(); + + return (CGAL::compare(xcv1.r() * factor2, xcv2.r() * factor1) == EQUAL && + CGAL::compare(xcv1.s() * factor2, xcv2.s() * factor1) == EQUAL && + CGAL::compare(xcv1.t() * factor2, xcv2.t() * factor1) == EQUAL && + CGAL::compare(xcv1.u() * factor2, xcv2.u() * factor1) == EQUAL && + CGAL::compare(xcv1.v() * factor2, xcv2.v() * factor1) == EQUAL && + CGAL::compare(xcv1.w() * factor2, xcv2.w() * factor1) == EQUAL); + } }; #include diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h index bd1fee2360b..ac9a63b356e 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h @@ -88,7 +88,7 @@ protected: Integer m_s; // The coefficients of the supporting conic curve: Integer m_t; // Integer m_u; // - Integer m_v; // r*x^2 + s*y^2 + t*xy + u*x + v*y +w = 0 . + Integer m_v; // r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0 Integer m_w; // Orientation m_orient; // The orientation of the conic. @@ -98,61 +98,11 @@ protected: Extra_data* m_extra_data; // The extra data stored with the arc // (may be nullptr). -public: - /// \name Flag manipulation functions. - //@{ - template - constexpr size_t flag_mask(const T flag) const { return 0x1 << flag; } - - void reset_flags() { m_info = 0; } - - template - void set_flag(const T flag) { m_info |= flag_mask(flag); } - - template - void reset_flag(const T flag) { m_info &= ~flag_mask(flag); } - - template - void flip_flag(const T flag) { m_info ^= flag_mask(flag);} - - template - bool test_flag(const T flag) const - { return (m_info & flag_mask(flag)); } - //@} - - /// \name Setters; only friends have the priviledge to use. - //@{ - - void set_coefficients(Integer r, Integer s, Integer t, - Integer u, Integer v, Integer w) { - - m_r = r; - m_s = s; - m_t = t; - m_u = u; - m_v = v; - m_w = w; - } - - void set_orientation(Orientation orient) { m_orient = orient; } - - void set_endpoints(const Conic_point_2& source, const Conic_point_2& target) { - m_source = source; - m_target = target; - } - - void set_extra_data(Extra_data* extra_data) { - m_extra_data = extra_data; - } - - //@} - public: /// \name Construction and destruction functions. //@{ - /*! - * Default constructor. + /*! Default constructor. */ _Conic_arc_2() : m_r(0), m_s(0), m_t(0), m_u(0), m_v(0), m_w(0), @@ -176,598 +126,6 @@ public: new Extra_data(*(arc.m_extra_data)) : nullptr; } - /*! Construct a conic arc which is the full conic: - * C: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0 - * \pre The conic C must be an ellipse (so 4rs - t^2 > 0). - */ - _Conic_arc_2(const Rational& r, const Rational& s, const Rational& t, - const Rational& u, const Rational& v, const Rational& w) : - m_info(0), - m_extra_data(nullptr) - { - // Make sure the given curve is an ellipse (4rs - t^2 should be positive). - CGAL_precondition(CGAL::sign(4*r*s - t*t) == POSITIVE); - - // Set the arc to be the full conic (and compute the orientation). - Rational rat_coeffs[6]; - - rat_coeffs[0] = r; - rat_coeffs[1] = s; - rat_coeffs[2] = t; - rat_coeffs[3] = u; - rat_coeffs[4] = v; - rat_coeffs[5] = w; - - set_full(rat_coeffs, true); - } - - /*! Construct a conic arc which lies on the conic: - * C: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0 - * \param orient The orientation of the arc (clockwise or counterclockwise). - * \param source The source point. - * \param target The target point. - * \pre The source and the target must be on the conic boundary and must - * not be the same. - */ - _Conic_arc_2(const Rational& r, const Rational& s, const Rational& t, - const Rational& u, const Rational& v, const Rational& w, - const Orientation& orient, - const Point_2& source, const Point_2& target) : - m_orient(orient), - m_info(0), - m_source(source), - m_target(target), - m_extra_data(nullptr) - { - // Make sure that the source and the taget are not the same. - CGAL_precondition(Alg_kernel().compare_xy_2_object()(source, target) != - EQUAL); - - // Set the arc properties (no need to compute the orientation). - Rational rat_coeffs[6]; - - rat_coeffs[0] = r; - rat_coeffs[1] = s; - rat_coeffs[2] = t; - rat_coeffs[3] = u; - rat_coeffs[4] = v; - rat_coeffs[5] = w; - - set(rat_coeffs); - } - - /*! Construct a segment conic arc from two endpoints. - * \param source the source point with rational coordinates. - */ - _Conic_arc_2(const Point_2& source, const Point_2& target) : - m_orient(COLLINEAR), - m_info(flag_mask(IS_VALID)), - m_source(source), - m_target(target), - m_extra_data(nullptr) - { - CGAL_precondition(Alg_kernel().compare_xy_2_object()(m_source, m_target) != - EQUAL); - - set_flag(IS_VALID); - - // Compose the equation of the underlying line. - const Algebraic x1 = source.x(); - const Algebraic y1 = source.y(); - const Algebraic x2 = target.x(); - const Algebraic y2 = target.y(); - - // The supporting line is A*x + B*y + C = 0, where: - // A = y2 - y1, B = x1 - x2, C = x2*y1 - x1*y2 - // We use the extra data field to store the equation of this line. - m_extra_data = new Extra_data; - m_extra_data->a = y2 - y1; - m_extra_data->b = x1 - x2; - m_extra_data->c = x2*y1 - x1*y2; - m_extra_data->side = ZERO; - } - - /*! Construct a conic arc from a given line segment. - * \param seg The line segment with rational endpoints. - */ - _Conic_arc_2(const Rat_segment_2& seg) : - m_orient(COLLINEAR), - m_info(0), - m_extra_data (nullptr) - { - // Set the source and target. - Rat_kernel ker; - Rat_point_2 source = ker.construct_vertex_2_object()(seg, 0); - Rat_point_2 target = ker.construct_vertex_2_object()(seg, 1); - Rational x1 = source.x(); - Rational y1 = source.y(); - Rational x2 = target.x(); - Rational y2 = target.y(); - Nt_traits nt_traits; - - m_source = Point_2(nt_traits.convert(x1), nt_traits.convert(y1)); - m_target = Point_2(nt_traits.convert(x2), nt_traits.convert(y2)); - - // Make sure that the source and the taget are not the same. - CGAL_precondition(Alg_kernel().compare_xy_2_object()(m_source, m_target) != - EQUAL); - - // The supporting conic is r=s=t=0, and u*x + v*y + w = 0 should hold - // for both the source (x1,y1) and the target (x2, y2). - const Rational zero(0); - const Rational one(1); - Rational rat_coeffs[6]; - - rat_coeffs[0] = zero; - rat_coeffs[1] = zero; - rat_coeffs[2] = zero; - - if (CGAL::compare(x1, x2) == EQUAL) { - // The supporting conic is a vertical line, of the form x = CONST. - rat_coeffs[3] = one; - rat_coeffs[4] = zero; - rat_coeffs[5] = -x1; - } - else { - // The supporting line is A*x + B*y + C = 0, where: - // - // A = y2 - y1, B = x1 - x2, C = x2*y1 - x1*y2 - // - rat_coeffs[3] = y2 - y1; - rat_coeffs[4] = x1 - x2; - rat_coeffs[5] = x2*y1 - x1*y2; - } - - // Set the arc properties (no need to compute the orientation). - set(rat_coeffs); - } - - /*! Construct a conic arc that is a full circle. - * \param circ The circle (with rational center and rational squared radius). - */ - _Conic_arc_2(const Rat_circle_2& circ) : - m_orient(CLOCKWISE), - m_info(0), - m_extra_data(nullptr) - { - // Get the circle properties. - Rat_kernel ker; - Rat_point_2 center = ker.construct_center_2_object()(circ); - Rational x0 = center.x(); - Rational y0 = center.y(); - Rational R_sqr = ker.compute_squared_radius_2_object()(circ); - - // Produce the correponding conic: if the circle center is (x0,y0) - // and its squared radius is R^2, that its equation is: - // x^2 + y^2 - 2*x0*x - 2*y0*y + (x0^2 + y0^2 - R^2) = 0 - // Note that this equation describes a curve with a negative (clockwise) - // orientation. - const Rational zero(0); - const Rational one(1); - const Rational minus_two(-2); - Rational rat_coeffs[6]; - - rat_coeffs[0] = one; - rat_coeffs[1] = one; - rat_coeffs[2] = zero; - rat_coeffs[3] = minus_two*x0; - rat_coeffs[4] = minus_two*y0; - rat_coeffs[5] = x0*x0 + y0*y0 - R_sqr; - - // Set the arc to be the full conic (no need to compute the orientation). - set_full(rat_coeffs, false); - } - - /*! Construct a conic arc that lies on a given circle: - * C: (x - x0)^2 + (y - y0)^2 = R^2 - * \param orient The orientation of the circle. - * \param source The source point. - * \param target The target point. - * \pre The source and the target must be on the conic boundary and must - * not be the same. - */ - _Conic_arc_2(const Rat_circle_2& circ, - const Orientation& orient, - const Point_2& source, const Point_2& target) : - m_orient(orient), - m_info(0), - m_source(source), - m_target(target), - m_extra_data(nullptr) - { - // Make sure that the source and the taget are not the same. - CGAL_precondition(Alg_kernel().compare_xy_2_object()(source, target) != - EQUAL); - CGAL_precondition(orient != COLLINEAR); - - // Get the circle properties. - Rat_kernel ker; - Rat_point_2 center = ker.construct_center_2_object()(circ); - Rational x0 = center.x(); - Rational y0 = center.y(); - Rational R_sqr = ker.compute_squared_radius_2_object()(circ); - - // Produce the correponding conic: if the circle center is (x0,y0) - // and it squared radius is R^2, that its equation is: - // x^2 + y^2 - 2*x0*x - 2*y0*y + (x0^2 + y0^2 - R^2) = 0 - // Since this equation describes a curve with a negative (clockwise) - // orientation, we multiply it by -1 if nece_Conic_arc_2 ssary to obtain a - // positive (counterclockwise) orientation. - const Rational zero(0); - Rational rat_coeffs[6]; - - if (m_orient == COUNTERCLOCKWISE) { - const Rational _minus_one(-1); - const Rational two(2); - - rat_coeffs[0] = _minus_one; - rat_coeffs[1] = _minus_one; - rat_coeffs[2] = zero; - rat_coeffs[3] = two*x0; - rat_coeffs[4] = two*y0; - rat_coeffs[5] = R_sqr - x0*x0 - y0*y0; - } - else { - const Rational one(1); - const Rational minus_two(-2); - - rat_coeffs[0] = one; - rat_coeffs[1] = one; - rat_coeffs[2] = zero; - rat_coeffs[3] = minus_two*x0; - rat_coeffs[4] = minus_two*y0; - rat_coeffs[5] = x0*x0 + y0*y0 - R_sqr; - } - - // Set the arc properties (no need to compute the orientation). - set(rat_coeffs); - } - - /*! Construct a conic arc that is a circular arc from given three points. - * \param p1 The arc source. - * \param p2 A point in the interior of the arc. - * \param p3 The arc target. - * \pre The three points must not be collinear. - */ - _Conic_arc_2(const Rat_point_2& p1, const Rat_point_2& p2, - const Rat_point_2& p3) : - m_info(0), - m_extra_data(nullptr) - { - // Set the source and target. - Rational x1 = p1.x(); - Rational y1 = p1.y(); - Rational x2 = p2.x(); - Rational y2 = p2.y(); - Rational x3 = p3.x(); - Rational y3 = p3.y(); - Nt_traits nt_traits; - - m_source = Point_2(nt_traits.convert (x1), nt_traits.convert(y1)); - m_target = Point_2(nt_traits.convert (x3), nt_traits.convert(y3)); - - // Make sure that the source and the taget are not the same. - CGAL_precondition(Alg_kernel().compare_xy_2_object()(m_source, m_target) != - EQUAL); - - // Compute the lines: A1*x + B1*y + C1 = 0, - // and: A2*x + B2*y + C2 = 0, - // where: - const Rational two = 2; - - const Rational A1 = two*(x1 - x2); - const Rational B1 = two*(y1 - y2); - const Rational C1 = y2*y2 - y1*y1 + x2*x2 - x1*x1; - - const Rational A2 = two*(x2 - x3); - const Rational B2 = two*(y2 - y3); - const Rational C2 = y3*y3 - y2*y2 + x3*x3 - x2*x2; - - // Compute the coordinates of the intersection point between the - // two lines, given by (Nx / D, Ny / D), where: - const Rational Nx = B1*C2 - B2*C1; - const Rational Ny = A2*C1 - A1*C2; - const Rational D = A1*B2 - A2*B1; - - // Make sure the three points are not collinear. - const bool points_collinear = (CGAL::sign(D) == ZERO); - - if (points_collinear) { - reset_flags(); // inavlid arc - return; - } - - // The equation of the underlying circle is given by: - Rational rat_coeffs[6]; - - rat_coeffs[0] = D*D; - rat_coeffs[1] = D*D; - rat_coeffs[2] = 0; - rat_coeffs[3] = -two*D*Nx; - rat_coeffs[4] = -two*D*Ny; - rat_coeffs[5] = - Nx*Nx + Ny*Ny - ((D*x2 - Nx)*(D*x2 - Nx) + (D*y2 - Ny)*(D*y2 - Ny)); - - // Determine the orientation: If the mid-point forms a left-turn with - // the source and the target points, the orientation is positive (going - // counterclockwise). - // Otherwise, it is negative (going clockwise). - Alg_kernel ker; - typename Alg_kernel::Orientation_2 orient_f = ker.orientation_2_object(); - - Point_2 p_mid = Point_2(nt_traits.convert(x2), nt_traits.convert(y2)); - - m_orient = (orient_f(m_source, p_mid, m_target) == LEFT_TURN) ? - COUNTERCLOCKWISE : CLOCKWISE; - - // Set the arc properties (no need to compute the orientation). - set(rat_coeffs); - } - - /*! Construct a conic arc from given five points, specified by the - * points p1, p2, p3, p4 and p5. - * \param p1 The source point of the given arc. - * \param p2,p3,p4 Points lying on the conic arc, between p1 and p5. - * \param p5 The target point of the given arc. - * \pre No three points are collinear. - */ - _Conic_arc_2(const Rat_point_2& p1, const Rat_point_2& p2, - const Rat_point_2& p3, const Rat_point_2& p4, - const Rat_point_2& p5) : - m_info(0), - m_extra_data(nullptr) - { - // Make sure that no three points are collinear. - Rat_kernel ker; - typename Rat_kernel::Orientation_2 orient_f = ker.orientation_2_object(); - const bool point_collinear = - (orient_f(p1, p2, p3) == COLLINEAR || - orient_f(p1, p2, p4) == COLLINEAR || - orient_f(p1, p2, p5) == COLLINEAR || - orient_f(p1, p3, p4) == COLLINEAR || - orient_f(p1, p3, p5) == COLLINEAR || - orient_f(p1, p4, p5) == COLLINEAR || - orient_f(p2, p3, p4) == COLLINEAR || - orient_f(p2, p3, p5) == COLLINEAR || - orient_f(p2, p4, p5) == COLLINEAR || - orient_f(p3, p4, p5) == COLLINEAR); - - if (point_collinear) { - reset_flags(); // inavlid arc - return; - } - - // Set the source and target. - Rational x1 = p1.x(); - Rational y1 = p1.y(); - Rational x5 = p5.x(); - Rational y5 = p5.y(); - Nt_traits nt_traits; - - m_source = Point_2(nt_traits.convert(x1), nt_traits.convert(y1)); - m_target = Point_2(nt_traits.convert(x5), nt_traits.convert(y5)); - - // Set a conic curve that passes through the five given point. - typename Rat_kernel::Conic_2 temp_conic; - Rational rat_coeffs[6]; - - temp_conic.set(p1, p2, p3, p4, p5); - - // Get the conic coefficients. - rat_coeffs[0] = temp_conic.r(); - rat_coeffs[1] = temp_conic.s(); - rat_coeffs[2] = temp_conic.t(); - rat_coeffs[3] = temp_conic.u(); - rat_coeffs[4] = temp_conic.v(); - rat_coeffs[5] = temp_conic.w(); - - // Determine the orientation: If one of the midpoints forms a left-turn - // with the source and the target points, the orientation is positive - // (going counterclockwise). - // Otherwise, it is negative (going clockwise). - const Orientation turn = orient_f(p1, p2, p5); - - if (turn == LEFT_TURN) { - m_orient = COUNTERCLOCKWISE; - CGAL_precondition(orient_f(p1, p3, p5) == LEFT_TURN && - orient_f(p1, p4, p5) == LEFT_TURN); - } - else { - m_orient = CLOCKWISE; - CGAL_precondition(orient_f(p1, p3, p5) != LEFT_TURN && - orient_f(p1, p4, p5) != LEFT_TURN); - } - - // Set the arc properties (no need to compute the orientation). - set(rat_coeffs); - - // Make sure that all midpoints are strictly between the - // source and the target. - Point_2 mp2 = Point_2(nt_traits.convert(p2.x()), nt_traits.convert(p2.y())); - Point_2 mp3 = Point_2(nt_traits.convert(p3.x()), nt_traits.convert(p3.y())); - Point_2 mp4 = Point_2(nt_traits.convert(p4.x()), nt_traits.convert(p4.y())); - - if (! is_strictly_between_endpoints(mp2) || - ! is_strictly_between_endpoints(mp3) || - ! is_strictly_between_endpoints(mp4)) - { - reset_flags(); // inavlid arc - } - } - - /*! Construct a conic arc that lies on a conic given by its coefficients: - * C: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0 - * The source and the target are specified by the intersection of the - * conic with: - * C_1: r_1*x^2 + s_1*y^2 + t_1*xy + u_1*x + v_1*y + w_1 = 0 - * C_2: r_2*x^2 + s_2*y^2 + t_2*xy + u_2*x + v_2*y + w_2 = 0 - * The user must also specify the source and the target with approximated - * coordinates. The actual intersection points that best fits the source - * (or the target) will be selected. - */ - _Conic_arc_2(const Rational& r, const Rational& s, const Rational& t, - const Rational& u, const Rational& v, const Rational& w, - const Orientation& orient, - const Point_2& app_source, - const Rational& r_1, const Rational& s_1, const Rational& t_1, - const Rational& u_1, const Rational& v_1, const Rational& w_1, - const Point_2& app_target, - const Rational& r_2, const Rational& s_2, const Rational& t_2, - const Rational& u_2, const Rational& v_2, const Rational& w_2) : - m_orient(orient), - m_info(0), - m_extra_data(nullptr) - { - // Create the integer coefficients of the base conic. - Rational rat_coeffs [6]; - Nt_traits nt_traits; - Integer base_coeffs[6]; - int deg_base; - - rat_coeffs[0] = r; - rat_coeffs[1] = s; - rat_coeffs[2] = t; - rat_coeffs[3] = u; - rat_coeffs[4] = v; - rat_coeffs[5] = w; - - nt_traits.convert_coefficients(rat_coeffs, rat_coeffs + 6, base_coeffs); - - if (CGAL::sign(base_coeffs[0]) == ZERO && - CGAL::sign(base_coeffs[1]) == ZERO && - CGAL::sign(base_coeffs[2]) == ZERO) - { - deg_base = 1; - } - else { - deg_base = 2; - } - - // Compute the endpoints. - Rational aux_rat_coeffs [6]; - Integer aux_coeffs[6]; - int deg_aux; - Algebraic xs[4]; - int n_xs; - Algebraic ys[4]; - int n_ys; - int i, j; - Algebraic val; - bool found; - double dx, dy; - double curr_dist; - double min_dist = -1; - int k; - - for (k = 1; k <= 2; ++k) { - // Get the integer coefficients of the k'th auxiliary conic curve. - aux_rat_coeffs[0] = (k == 1) ? r_1 : r_2; - aux_rat_coeffs[1] = (k == 1) ? s_1 : s_2; - aux_rat_coeffs[2] = (k == 1) ? t_1 : t_2; - aux_rat_coeffs[3] = (k == 1) ? u_1 : u_2; - aux_rat_coeffs[4] = (k == 1) ? v_1 : v_2; - aux_rat_coeffs[5] = (k == 1) ? w_1 : w_2; - - nt_traits.convert_coefficients(aux_rat_coeffs, aux_rat_coeffs + 6, - aux_coeffs); - - deg_aux = ((CGAL::sign(aux_coeffs[0]) == ZERO) && - (CGAL::sign(aux_coeffs[1]) == ZERO) && - (CGAL::sign(aux_coeffs[2]) == ZERO)) ? 1 : 2; - - // Compute the x- and y-coordinates of intersection points of the base - // conic and the k'th auxiliary conic. - n_xs = compute_resultant_roots(nt_traits, - base_coeffs[0], base_coeffs[1], - base_coeffs[2], - base_coeffs[3], base_coeffs[4], - base_coeffs[5], - deg_base, - aux_coeffs[0], aux_coeffs[1], - aux_coeffs[2], - aux_coeffs[3], aux_coeffs[4], - aux_coeffs[5], - deg_aux, - xs); - - n_ys = compute_resultant_roots(nt_traits, - base_coeffs[1], base_coeffs[0], - base_coeffs[2], - base_coeffs[4], base_coeffs[3], - base_coeffs[5], - deg_base, - aux_coeffs[1], aux_coeffs[0], - aux_coeffs[2], - aux_coeffs[4], aux_coeffs[3], - aux_coeffs[5], - deg_aux, - ys); - - // Find the intersection point which is nearest the given approximation - // and set it as the endpoint. - found = false; - for (i = 0; i < n_xs; ++i) { - for (j = 0; j < n_ys; ++j) { - // Check if the point (xs[i], ys[j]) lies on both conics. - val = nt_traits.convert(base_coeffs[0]) * xs[i]*xs[i] + - nt_traits.convert(base_coeffs[1]) * ys[j]*ys[j] + - nt_traits.convert(base_coeffs[2]) * xs[i]*ys[j] + - nt_traits.convert(base_coeffs[3]) * xs[i] + - nt_traits.convert(base_coeffs[4]) * ys[j] + - nt_traits.convert(base_coeffs[5]); - - if (CGAL::sign(val) != ZERO) continue; - - val = nt_traits.convert(aux_coeffs[0]) * xs[i]*xs[i] + - nt_traits.convert(aux_coeffs[1]) * ys[j]*ys[j] + - nt_traits.convert(aux_coeffs[2]) * xs[i]*ys[j] + - nt_traits.convert(aux_coeffs[3]) * xs[i] + - nt_traits.convert(aux_coeffs[4]) * ys[j] + - nt_traits.convert(aux_coeffs[5]); - - if (CGAL::sign(val) == ZERO) { - // Compute the distance of (xs[i], ys[j]) from the approximated - // endpoint. - if (k == 1) { - dx = CGAL::to_double (xs[i] - app_source.x()); - dy = CGAL::to_double (ys[j] - app_source.y()); - } - else { - dx = CGAL::to_double (xs[i] - app_target.x()); - dy = CGAL::to_double (ys[j] - app_target.y()); - } - - curr_dist = dx*dx + dy*dy; - - // Update the endpoint if (xs[i], ys[j]) is the nearest pair so - // far. - if (! found || curr_dist < min_dist) { - if (k == 1) m_source = Point_2 (xs[i], ys[j]); - else m_target = Point_2 (xs[i], ys[j]); - - min_dist = curr_dist; - found = true; - } - } - } - } - - if (! found) { - reset_flags(); // inavlid arc - return; - } - } - - // Make sure that the source and the target are not the same. - if (Alg_kernel().compare_xy_2_object()(m_source, m_target) == EQUAL) { - reset_flags(); // inavlid arc - return; - } - - // Set the arc properties (no need to compute the orientation). - set(rat_coeffs); - } - /*! Destructor. */ virtual ~_Conic_arc_2() { if (m_extra_data != nullptr) delete m_extra_data; } @@ -809,6 +167,10 @@ public: */ bool is_valid() const { return test_flag(IS_VALID); } + /*! Check whether the arc represents a full conic curve. + */ + bool is_full_conic() const { return test_flag(IS_FULL_CONIC); } + /*! Get the coefficients of the underlying conic. */ const Integer& r() const { return (m_r); } @@ -834,10 +196,6 @@ public: return (horizontal_tangency_points(htan_ps) == 0); } - /*! Check whether the arc represents a full conic curve. - */ - bool is_full_conic() const { return test_flag(IS_FULL_CONIC); } - /*! Obtain the arc's source. * \return The source point. * \pre The arc does not represent a full conic curve. @@ -944,9 +302,34 @@ public: // Return the resulting bounding box. return Bbox_2(x_min, y_min, x_max, y_max); } + //@} - /// \name Modifying functions. +public: + /// \name Flag manipulation functions. + //@{ + template + constexpr size_t flag_mask(const T flag) const { return 0x1 << flag; } + + void reset_flags() { m_info = 0; } + + template + void set_flag(const T flag) { m_info |= flag_mask(flag); } + + template + void reset_flag(const T flag) { m_info &= ~flag_mask(flag); } + + template + void flip_flag(const T flag) { m_info ^= flag_mask(flag);} + + template + bool test_flag(const T flag) const + { return (m_info & flag_mask(flag)); } + //@} + +public: + /// \name Modifying functions (setters); + // only friends have the priviledge to use. //@{ /*! Set the source point of the conic arc. @@ -959,6 +342,34 @@ public: */ void set_target(const Point_2& pt) { m_target = pt; } + /*! Set the coefficients. + */ + void set_coefficients(Integer r, Integer s, Integer t, + Integer u, Integer v, Integer w) { + + m_r = r; + m_s = s; + m_t = t; + m_u = u; + m_v = v; + m_w = w; + } + + /*! Set the orientation. + */ + void set_orientation(Orientation orient) { m_orient = orient; } + + /*! Set the endpoints. + */ + void set_endpoints(const Conic_point_2& source, const Conic_point_2& target) { + m_source = source; + m_target = target; + } + + /*! Set the extra data field. + */ + void set_extra_data(Extra_data* extra_data) { m_extra_data = extra_data; } + //@} /// \name Compute points on the arc. diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_point_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_point_2.h index 344c1bf6395..2e57b4269c4 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_point_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_point_2.h @@ -15,28 +15,28 @@ #include - /*! \file * Header file for the _Conic_point_2 class. */ #include + #include namespace CGAL { -/*! - * \class A class that stores additional information with the point's +/*! \class + * A class that stores additional information with the point's * coordinates, namely the conic IDs of the generating curves. */ -template -class _Conic_point_2 : public Alg_kernel_::Point_2 { +template +class _Conic_point_2 : public AlgKernel::Point_2 { public: - typedef Alg_kernel_ Alg_kernel; - typedef typename Alg_kernel::Point_2 Base; - typedef _Conic_point_2 Self; + typedef AlgKernel Alg_kernel; + typedef typename Alg_kernel::Point_2 Base; + typedef _Conic_point_2 Self; - typedef typename Alg_kernel::FT Algebraic; + typedef typename Alg_kernel::FT Algebraic; /*! \class * Representation of an ID of a conic arc. @@ -78,9 +78,9 @@ private: typedef std::list Ids_container; typedef typename std::list::const_iterator Ids_iterator; - Ids_container conic_ids; // The IDs of the generating conics. + Ids_container conic_ids; // the IDs of the generating conics. - public: +public: /// \name Constructors. //@{ @@ -88,21 +88,17 @@ private: _Conic_point_2() : Base() {} /*! Constrcutor from the base class. */ - _Conic_point_2(const Base& p) : - Base(p) - {} + _Conic_point_2(const Base& p) : Base(p) {} /*! Constructor with homegeneous coordinates. */ _Conic_point_2(const Algebraic& hx, const Algebraic& hy, const Algebraic& hz) : - Base (hx, hy, hz) + Base(hx, hy, hz) {} /*! Constructor with Cartesian coordinates. */ - _Conic_point_2(const Algebraic& x, const Algebraic& y) : - Base(x, y) - {} + _Conic_point_2(const Algebraic& x, const Algebraic& y) : Base(x, y) {} //@} /// \name Maintaining the generating conic IDs. @@ -115,13 +111,8 @@ private: /*! Check if the given conic generates the point. */ bool is_generating_conic(const Conic_id& id) const { if (! id.is_valid()) return false; - - Ids_iterator it; - - for (it = conic_ids.begin(); it != conic_ids.end(); ++it) { + for (auto it = conic_ids.begin(); it != conic_ids.end(); ++it) if (*it == id) return true; - } - return false; } //@} diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h index ed59662b14f..16eef6de002 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h @@ -32,7 +32,7 @@ namespace CGAL { */ template -class _Conic_x_monotone_arc_2 : private ConicArc { +class _Conic_x_monotone_arc_2 : public ConicArc { public: typedef ConicArc Conic_arc_2; typedef _Conic_x_monotone_arc_2 Self; @@ -79,13 +79,23 @@ public: typedef typename Intersection_map::value_type Intersection_map_entry; typedef typename Intersection_map::iterator Intersection_map_iterator; -protected: +private: typedef Conic_arc_2 Base; typedef typename Conic_arc_2::Integer Integer; typedef typename Conic_arc_2::Nt_traits Nt_traits; typedef typename Conic_arc_2::Rat_kernel Rat_kernel; + Algebraic m_alg_r; // The coefficients of the supporting conic curve: + Algebraic m_alg_s; // + Algebraic m_alg_t; // r*x^2 + s*y^2 + t*xy + u*x + v*y +w = 0 , + Algebraic m_alg_u; // + Algebraic m_alg_v; // converted to algebraic numbers. + Algebraic m_alg_w; // + + Conic_id m_id; // The ID number of the supporting conic curve. + +public: // Bit masks for the m_info field (the two least significant bits are already // used by the base class). enum { @@ -102,16 +112,6 @@ protected: FACING_MASK = (0x1 << FACING_UP) | (0x1 << FACING_DOWN) }; - Algebraic alg_r; // The coefficients of the supporting conic curve: - Algebraic alg_s; // - Algebraic alg_t; // r*x^2 + s*y^2 + t*xy + u*x + v*y +w = 0 , - Algebraic alg_u; // - Algebraic alg_v; // converted to algebraic numbers. - Algebraic alg_w; // - - Conic_id m_id; // The ID number of the supporting conic curve. - -public: /// \name Constrcution methods. //@{ @@ -127,12 +127,12 @@ public: */ _Conic_x_monotone_arc_2(const Self& arc) : Base(arc), - alg_r(arc.alg_r), - alg_s(arc.alg_s), - alg_t(arc.alg_t), - alg_u(arc.alg_u), - alg_v(arc.alg_v), - alg_w(arc.alg_w), + m_alg_r(arc.m_alg_r), + m_alg_s(arc.m_alg_s), + m_alg_t(arc.m_alg_t), + m_alg_u(arc.m_alg_u), + m_alg_v(arc.m_alg_v), + m_alg_w(arc.m_alg_w), m_id(arc.m_id) {} @@ -143,10 +143,7 @@ public: _Conic_x_monotone_arc_2(const Base& arc) : Base(arc), m_id() - { - CGAL_precondition(arc.is_valid() && arc.is_x_monotone()); - set(); - } + {} /*! Construct an x-monotone arc from a conic arc. * \param arc The given (base) arc. @@ -155,10 +152,7 @@ public: _Conic_x_monotone_arc_2(const Base& arc, const Conic_id& id) : Base(arc), m_id(id) - { - CGAL_precondition(arc.is_valid() && id.is_valid()); - set(); - } + {} /*! Construct an x-monotone sub-arc from a conic arc. * \param arc The given (base) arc. @@ -171,15 +165,7 @@ public: const Conic_id& id) : Base(arc), m_id(id) - { - CGAL_precondition(arc.is_valid() && id.is_valid()); - - // Set the two endpoints. - this->m_source = source; - this->m_target = target; - - set(); - } + {} /*! Construct a special segment connecting to given endpoints (for the usage * of the landmarks point-location strategy). @@ -188,21 +174,7 @@ public: */ _Conic_x_monotone_arc_2(const Point_2& source, const Point_2& target) : Base(source, target) - { - set_flag(DEGREE_1); - - Alg_kernel ker; - auto cmp_xy = ker.compare_xy_2_object(); - Comparison_result dir_res = cmp_xy(this->m_source, this->m_target); - if (dir_res == SMALLER) set_flag(IS_DIRECTED_RIGHT); - - // Check if the segment is vertical. - if (CGAL::sign(this->m_extra_data->b) == ZERO) - set_flag(IS_VERTICAL_SEGMENT); - - // Mark that this is a special segment. - set_flag(IS_SPECIAL_SEGMENT); - } + {} /*! Construct a special segment of a given line connecting to given * endpoints. @@ -215,54 +187,7 @@ public: const Algebraic& c, const Point_2& source, const Point_2& target) : Base() - { - // Make sure the two endpoints lie on the supporting line. - CGAL_precondition - (CGAL::sign(a * source.x() + b * source.y() + c) == CGAL::ZERO); - - CGAL_precondition - (CGAL::sign(a * target.x() + b * target.y() + c) == CGAL::ZERO); - - // Set the basic properties and clear the m_info bits. - this->m_source = source; - this->m_target = target; - this->m_orient = COLLINEAR; - reset_flags(); // inavlid arc - - // Check if the arc is directed right (the target is lexicographically - // greater than the source point), or to the left. - Alg_kernel ker; - Comparison_result res = - ker.compare_x_2_object()(this->m_source, this->m_target); - - set_flag(IS_VALID); - set_flag(DEGREE_1); - if (res == EQUAL) { - // Mark that the segment is vertical. - set_flag(IS_VERTICAL_SEGMENT); - - // Compare the endpoints lexicographically. - res = ker.compare_y_2_object()(this->m_source, this->m_target); - - CGAL_precondition (res != EQUAL); - if (res == EQUAL) { - reset_flags(); // inavlid arc - return; - } - } - - if (res == SMALLER) set_flag(IS_DIRECTED_RIGHT); - - // Store the coefficients of the line. - this->m_extra_data = new typename Base::Extra_data; - this->m_extra_data->a = a; - this->m_extra_data->b = b; - this->m_extra_data->c = c; - this->m_extra_data->side = ZERO; - - // Mark that this is a special segment. - set_flag(IS_SPECIAL_SEGMENT); - } + {} /*! Assignment operator. * \param arc The copied arc. @@ -276,12 +201,12 @@ public: Base::operator= (arc); // Set the rest of the properties. - alg_r = arc.alg_r; - alg_s = arc.alg_s; - alg_t = arc.alg_t; - alg_u = arc.alg_u; - alg_v = arc.alg_v; - alg_w = arc.alg_w; + m_alg_r = arc.m_alg_r; + m_alg_s = arc.m_alg_s; + m_alg_t = arc.m_alg_t; + m_alg_u = arc.m_alg_u; + m_alg_v = arc.m_alg_v; + m_alg_w = arc.m_alg_w; m_id = arc.m_id; @@ -292,6 +217,14 @@ public: /// \name Accessing the arc properties. //@{ + /*! Obtain the facing mask. + */ + size_t facing_mask() const { return this->m_info & FACING_MASK; } + + /*! Obtain the degree mask. + */ + size_t degree_mask() const { return this->m_info & DEGREE_MASK; } + /*! Obtain the coefficients of the underlying conic. */ const Integer& r() const { return ( this->m_r); } @@ -305,11 +238,13 @@ public: * \return The source point. */ const Conic_point_2& source() const { return (this->m_source); } + Conic_point_2& source() { return (this->m_source); } /*! Obtain the arc's target. * \return The target point. */ const Conic_point_2& target() const { return this->m_target; } + Conic_point_2& target() { return this->m_target; } /*! Obtain the orientation of the arc. * \return The orientation. @@ -335,12 +270,45 @@ public: bool is_directed_right() const { return test_flag(IS_DIRECTED_RIGHT); } + Algebraic alg_r() const { return m_alg_r; } + Algebraic alg_s() const { return m_alg_s; } + Algebraic alg_t() const { return m_alg_t; } + Algebraic alg_u() const { return m_alg_u; } + Algebraic alg_v() const { return m_alg_v; } + Algebraic alg_w() const { return m_alg_w; } + + /*! Obtain the conic id. + */ + Conic_id id() const { return m_id; } + /*! Obtain a bounding box for the conic arc. * \return The bounding box. */ Bbox_2 bbox() const { return Base::bbox(); } //@} + // Setters + //@{ + void set_alg_coefficients(const Algebraic& alg_r, const Algebraic& alg_s, + const Algebraic& alg_t, const Algebraic& alg_u, + const Algebraic& alg_v, const Algebraic& alg_w) + { + m_alg_r = alg_r; + m_alg_s = alg_s; + m_alg_t = alg_t; + m_alg_u = alg_u; + m_alg_v = alg_v; + m_alg_w = alg_w; + } + + /*! Add a generating conic ID. */ + void set_generating_conic(const Conic_id& id) { + this->m_source.set_generating_conic(id); + this->m_target.set_generating_conic(id); + } + + //@} + /// \name Predicates. //@{ @@ -381,84 +349,6 @@ public: /// \name Constructing points on the arc. //@{ - /*! Compute a point on the arc with the same x-coordiante as the given point. - * \param p The given point. - * \pre The arc is not vertical and p is in the x-range of the arc. - * \return A point on the arc with the same x-coordiante as p. - */ - Point_2 point_at_x(const Point_2& p) const { - // Make sure that p is in the x-range of the arc. - CGAL_precondition(! test_flag(IS_VERTICAL_SEGMENT)); - - CGAL_precondition_code(Alg_kernel ker;); - - CGAL_precondition(ker.compare_x_2_object()(p, left()) != SMALLER && - ker.compare_x_2_object()(p, right()) != LARGER); - - if (is_special_segment()) { - // In case of a special segment, the equation of the supported line - // (a*x + b*y + c) = 0 is stored with the extra data field, and we - // simply have: - Algebraic _y = -(this->m_extra_data->a*p.x() + this->m_extra_data->c) / - this->m_extra_data->b; - - // Return the computed point. - return Point_2(p.x(), _y); - } - - // Compute the y-coordinate according to the degree of the supporting - // conic curve. - Nt_traits nt_traits; - Algebraic y; - - if ((this->m_info & DEGREE_MASK) == flag_mask(DEGREE_1)) { - // In case of a linear curve, the y-coordinate is a simple linear - // expression of x(p) (note that v is not 0 as the arc is not vertical): - // y = -(u*x(p) + w) / v - y = -(alg_u*p.x() + alg_w) / alg_v; - } - else if (this->m_orient == COLLINEAR) { - CGAL_assertion (this->m_extra_data != nullptr); - - // In this case the equation of the supporting line is given by the - // extra data structure. - y = -(this->m_extra_data->a * p.x() + - this->m_extra_data->c) / this->m_extra_data->b; - } - else { - CGAL_assertion((this->m_info & DEGREE_MASK) == flag_mask(DEGREE_2)); - - // In this case the y-coordinate is one of solutions to the quadratic - // equation: - // s*y^2 + (t*x(p) + v)*y + (r*x(p)^2 + u*x(p) + w) = 0 - Algebraic A = alg_s; - Algebraic B = alg_t*p.x() + alg_v; - Algebraic C = (alg_r*p.x() + alg_u)*p.x() + alg_w; - - if (CGAL::sign(this->m_s) == ZERO) { - // In this case A is 0 and we have a linear equation. - CGAL_assertion (CGAL::sign (B) != ZERO); - - y = -C / B; - } - else { - // Solve the quadratic equation. - Algebraic disc = B*B - 4*A*C; - - CGAL_assertion (CGAL::sign (disc) != NEGATIVE); - - // We take either the root involving -sqrt(disc) or +sqrt(disc) - // based on the information flags. - y = (test_flag(PLUS_SQRT_DISC_ROOT)) ? - (nt_traits.sqrt (disc) - B) / (2*A) : - -(B + nt_traits.sqrt (disc)) / (2*A); - } - } - - // Return the computed point. - return Point_2(p.x(), y); - } - /*! Obtain a polyline approximating the conic arc. * \param n The maximal number of sample points. * \param oi An output iterator, whose value-type is pair @@ -523,241 +413,6 @@ public: return oi; } - /*! Compare to arcs immediately to the right of their intersection point. - * \param arc The compared arc. - * \param p The reference intersection point. - * \return The relative position of the arcs to the right of p. - * \pre Both arcs we compare are not vertical segments. - */ - Comparison_result compare_to_right(const Self& arc, const Conic_point_2& p) - const - { - CGAL_precondition(! test_flag(IS_VERTICAL_SEGMENT) && - ! arc.test_flag(IS_VERTICAL_SEGMENT)); - - // In case one arc is facing upwards and another facing downwards, it is - // clear that the one facing upward is above the one facing downwards. - if (has_same_supporting_conic(arc)) { - if (test_flag(FACING_UP) && arc.test_flag(FACING_DOWN)) - return LARGER; - else if (test_flag(FACING_DOWN) && arc.test_flag(FACING_UP)) - return SMALLER; - - // In this case the two arcs overlap. - CGAL_assertion((this->m_info & FACING_MASK) == (arc.m_info & FACING_MASK)); - return EQUAL; - } - - // Compare the slopes of the two arcs at p, using their first-order - // partial derivatives. - Algebraic slope1_numer, slope1_denom; - Algebraic slope2_numer, slope2_denom; - - derive_by_x_at(p, 1, slope1_numer, slope1_denom); - arc.derive_by_x_at(p, 1, slope2_numer, slope2_denom); - - // Check if any of the slopes is vertical. - const bool is_vertical_slope1 = (CGAL::sign(slope1_denom) == ZERO); - const bool is_vertical_slope2 = (CGAL::sign(slope2_denom) == ZERO); - - if (! is_vertical_slope1 && !is_vertical_slope2) { - // The two derivatives at p are well-defined: use them to determine - // which arc is above the other (the one with a larger slope is below). - Comparison_result slope_res = - CGAL::compare(slope1_numer*slope2_denom, slope2_numer*slope1_denom); - - if (slope_res != EQUAL) return (slope_res); - - // Use the second-order derivative. - derive_by_x_at(p, 2, slope1_numer, slope1_denom); - arc.derive_by_x_at(p, 2, slope2_numer, slope2_denom); - - slope_res = - CGAL::compare(slope1_numer*slope2_denom, slope2_numer*slope1_denom); - - if (slope_res != EQUAL) return (slope_res); - - // Use the third-order derivative. - derive_by_x_at(p, 3, slope1_numer, slope1_denom); - arc.derive_by_x_at(p, 3, slope2_numer, slope2_denom); - - slope_res = - CGAL::compare(slope1_numer*slope2_denom, slope2_numer*slope1_denom); - - // \todo Handle higher-order derivatives: - CGAL_assertion(slope_res != EQUAL); - - return slope_res; - } - else if (! is_vertical_slope2) { - // The first arc has a vertical slope at p: check whether it is - // facing upwards or downwards and decide accordingly. - CGAL_assertion((this->m_info & FACING_MASK) != 0); - - return (test_flag(FACING_UP)) ? LARGER : SMALLER; - } - else if (! is_vertical_slope1) { - // The second arc has a vertical slope at p_int: check whether it is - // facing upwards or downwards and decide accordingly. - CGAL_assertion((arc.m_info & FACING_MASK) != 0); - - return (arc.test_flag(FACING_UP)) ? SMALLER : LARGER; - } - - // The two arcs have vertical slopes at p_int: - // First check whether one is facing up and one down. In this case the - // comparison result is trivial. - if (test_flag(FACING_UP) && arc.test_flag(FACING_DOWN)) - return LARGER; - else if (test_flag(FACING_DOWN) && arc.test_flag(FACING_UP)) - return SMALLER; - - // Compute the second-order derivative by y and act according to it. - derive_by_y_at(p, 2, slope1_numer, slope1_denom); - arc.derive_by_y_at(p, 2, slope2_numer, slope2_denom); - - Comparison_result slope_res = - CGAL::compare(slope1_numer*slope2_denom, slope2_numer*slope1_denom); - - // If necessary, use the third-order derivative by y. - if (slope_res == EQUAL) { - // \todo Check this! - derive_by_y_at(p, 3, slope1_numer, slope1_denom); - arc.derive_by_y_at(p, 3, slope2_numer, slope2_denom); - - slope_res = - CGAL::compare(slope2_numer*slope1_denom, slope1_numer*slope2_denom); - } - - // \todo Handle higher-order derivatives: - CGAL_assertion(slope_res != EQUAL); - - if (test_flag(FACING_UP) && arc.test_flag(FACING_UP)) { - // Both are facing up. - return ((slope_res == LARGER) ? SMALLER : LARGER); - } - // Both are facing down. - return slope_res; - } - - /*! Compare to arcs immediately to the leftt of their intersection point. - * \param arc The compared arc. - * \param p The reference intersection point. - * \return The relative position of the arcs to the left of p. - * \pre Both arcs we compare are not vertical segments. - */ - Comparison_result compare_to_left(const Self& arc, const Conic_point_2& p) - const - { - CGAL_precondition(! test_flag(IS_VERTICAL_SEGMENT) && - ! arc.test_flag(IS_VERTICAL_SEGMENT)); - - // In case one arc is facing upwards and another facing downwards, it is - // clear that the one facing upward is above the one facing downwards. - if (has_same_supporting_conic (arc)) { - if (test_flag(FACING_UP) && arc.test_flag(FACING_DOWN)) - return LARGER; - else if (test_flag(FACING_DOWN) && arc.test_flag(FACING_UP)) - return SMALLER; - - // In this case the two arcs overlap. - CGAL_assertion((this->m_info & FACING_MASK) == (arc.m_info & FACING_MASK)); - - return EQUAL; - } - - // Compare the slopes of the two arcs at p, using their first-order - // partial derivatives. - Algebraic slope1_numer, slope1_denom; - Algebraic slope2_numer, slope2_denom; - - derive_by_x_at(p, 1, slope1_numer, slope1_denom); - arc.derive_by_x_at(p, 1, slope2_numer, slope2_denom); - - // Check if any of the slopes is vertical. - const bool is_vertical_slope1 = (CGAL::sign (slope1_denom) == ZERO); - const bool is_vertical_slope2 = (CGAL::sign (slope2_denom) == ZERO); - - if (! is_vertical_slope1 && !is_vertical_slope2) { - // The two derivatives at p are well-defined: use them to determine - // which arc is above the other (the one with a larger slope is below). - Comparison_result slope_res = CGAL::compare(slope2_numer*slope1_denom, - slope1_numer*slope2_denom); - - if (slope_res != EQUAL) return (slope_res); - - // Use the second-order derivative. - derive_by_x_at(p, 2, slope1_numer, slope1_denom); - arc.derive_by_x_at(p, 2, slope2_numer, slope2_denom); - - slope_res = CGAL::compare(slope1_numer*slope2_denom, - slope2_numer*slope1_denom); - - if (slope_res != EQUAL) return (slope_res); - - // Use the third-order derivative. - derive_by_x_at(p, 3, slope1_numer, slope1_denom); - arc.derive_by_x_at(p, 3, slope2_numer, slope2_denom); - - slope_res = CGAL::compare(slope2_numer*slope1_denom, - slope1_numer*slope2_denom); - - // \todo Handle higher-order derivatives: - CGAL_assertion(slope_res != EQUAL); - - return slope_res; - } - else if (! is_vertical_slope2) { - // The first arc has a vertical slope at p: check whether it is - // facing upwards or downwards and decide accordingly. - CGAL_assertion((this->m_info & FACING_MASK) != 0); - - return (test_flag(FACING_UP)) ? LARGER : SMALLER; - } - else if (! is_vertical_slope1) { - // The second arc has a vertical slope at p_int: check whether it is - // facing upwards or downwards and decide accordingly. - CGAL_assertion((arc.m_info & FACING_MASK) != 0); - - return (arc.test_flag(FACING_UP)) ? SMALLER : LARGER; - } - - // The two arcs have vertical slopes at p_int: - // First check whether one is facing up and one down. In this case the - // comparison result is trivial. - if (test_flag(FACING_UP) && arc.test_flag(FACING_DOWN)) - return LARGER; - else if (test_flag(FACING_DOWN) && arc.test_flag(FACING_UP)) - return SMALLER; - - // Compute the second-order derivative by y and act according to it. - derive_by_y_at(p, 2, slope1_numer, slope1_denom); - arc.derive_by_y_at(p, 2, slope2_numer, slope2_denom); - - Comparison_result slope_res = - CGAL::compare(slope2_numer*slope1_denom, slope1_numer*slope2_denom); - - // If necessary, use the third-order derivative by y. - if (slope_res == EQUAL) { - // \todo Check this! - derive_by_y_at(p, 3, slope1_numer, slope1_denom); - arc.derive_by_y_at(p, 3, slope2_numer, slope2_denom); - - slope_res = - CGAL::compare(slope2_numer*slope1_denom, slope1_numer*slope2_denom); - } - - // \todo Handle higher-order derivatives: - CGAL_assertion(slope_res != EQUAL); - - // Check whether both are facing up. - if (test_flag(FACING_UP) && arc.test_flag(FACING_UP)) - return ((slope_res == LARGER) ? SMALLER : LARGER); - - // Both are facing down. - return slope_res; - } - /*! Compute the intersections with the given arc. * \param arc The given intersecting arc. * \param inter_map Maps conic pairs to lists of their intersection points. @@ -849,49 +504,6 @@ public: /// \name Constructing x-monotone arcs. //@{ - /*! Split the arc into two at a given split point. - * \param p The split point. - * \param c1 Output: The first resulting arc, lying to the left of p. - * \param c2 Output: The first resulting arc, lying to the right of p. - * \pre p lies in the interior of the arc (not one of its endpoints). - */ - void split(const Conic_point_2& p, Self& c1, Self& c2) const { - // Make sure that p lies on the interior of the arc. - CGAL_precondition_code(Alg_kernel ker); - - CGAL_precondition(this->contains_point (p) && - ! ker.equal_2_object()(p, this->m_source) && - ! ker.equal_2_object()(p, this->m_target)); - - // Make copies of the current arc. - c1 = *this; - c2 = *this; - - // Assign the endpoints of the arc. - if (test_flag(IS_DIRECTED_RIGHT)) { - // The arc is directed from left to right, so p becomes c1's target - // and c2's source. - c1.m_target = p; - c2.m_source = p; - - if (! p.is_generating_conic(m_id)) { - c1.m_target.set_generating_conic(m_id); - c2.m_source.set_generating_conic(m_id); - } - } - else { - // The arc is directed from right to left, so p becomes c2's target - // and c1's source. - c1.m_source = p; - c2.m_target = p; - - if (! p.is_generating_conic(m_id)) { - c1.m_source.set_generating_conic(m_id); - c2.m_target.set_generating_conic(m_id); - } - } - } - /*! Flip the arc. * \return An arc with swapped source and target and a reverse orienation. */ @@ -913,49 +525,6 @@ public: return arc; } - /*! Trim the arc given its new endpoints. - * \param ps The new source point. - * \param pt The new target point. - * \return The new trimmed arc. - * \pre Both ps and pt lies on the arc and must conform with the current - * direction of the arc. - */ - Self trim(const Conic_point_2& ps, const Conic_point_2& pt) const { - // Make sure that both ps and pt lie on the arc. - CGAL_precondition(this->contains_point(ps) && this->contains_point(pt)); - - // Make sure that the endpoints conform with the direction of the arc. - Self arc = *this; - Alg_kernel ker; - - if (! ((test_flag(IS_DIRECTED_RIGHT) && - (ker.compare_xy_2_object()(ps, pt) == SMALLER)) || - (test_flag(IS_DIRECTED_RIGHT) && - (ker.compare_xy_2_object()(ps, pt) == LARGER)))) - { - // We are allowed to change the direction only in case of a segment. - CGAL_assertion(this->m_orient == COLLINEAR); - arc.flip_flag(IS_DIRECTED_RIGHT); - } - - // Make a copy of the current arc and assign its endpoints. - if (! ker.equal_2_object()(ps, this->m_source)) { - arc.m_source = ps; - - if (! ps.is_generating_conic(m_id)) - arc.m_source.set_generating_conic(m_id); - } - - if (! ker.equal_2_object()(pt, this->m_target)) { - arc.m_target = pt; - - if (! pt.is_generating_conic(m_id)) - arc.m_target.set_generating_conic(m_id); - } - - return arc; - } - /*! Check whether the two arcs are equal (have the same graph). * \param arc The compared arc. * \return (true) if the two arcs have the same graph; (false) otherwise. @@ -987,49 +556,6 @@ public: } } - /*! Check whether it is possible to merge the arc with the given arc. - * \param arc The query arc. - * \return (true) if it is possible to merge the two arcs; - * (false) otherwise. - */ - bool can_merge_with(const Self& arc) const { - // In order to merge the two arcs, they should have the same supporting - // conic. - if (! has_same_supporting_conic(arc)) return false; - - // Check if the left endpoint of one curve is the right endpoint of the - // other. - Alg_kernel ker; - return (ker.equal_2_object() (right(), arc.left()) || - ker.equal_2_object() (left(), arc.right())); - } - - /*! Merge the current arc with the given arc. - * \param arc The arc to merge with. - * \pre The two arcs are mergeable. - */ - void merge(const Self& arc) { - CGAL_precondition (this->can_merge_with (arc)); - - // Check if we should extend the arc to the left or to the right. - Alg_kernel ker; - - if (ker.equal_2_object() (right(), arc.left())) { - // Extend the arc to the right. - if (test_flag(IS_DIRECTED_RIGHT)) this->m_target = arc.right(); - else this->m_source = arc.right(); - } - else { - CGAL_precondition(ker.equal_2_object() (left(), arc.right())); - - // Extend the arc to the left. - if (test_flag(IS_DIRECTED_RIGHT)) - this->m_source = arc.left(); - else - this->m_target = arc.left(); - } - } - bool is_upper() const { return test_flag(FACING_UP); } bool is_lower() const { return test_flag(FACING_DOWN); } @@ -1048,16 +574,16 @@ private: /*! Set the properties of the x-monotone conic arc (for the usage of the * constructors). */ - void set() { + void set_x_monotone() { // Convert the coefficients of the supporting conic to algebraic numbers. Nt_traits nt_traits; - alg_r = nt_traits.convert(this->m_r); - alg_s = nt_traits.convert(this->m_s); - alg_t = nt_traits.convert(this->m_t); - alg_u = nt_traits.convert(this->m_u); - alg_v = nt_traits.convert(this->m_v); - alg_w = nt_traits.convert(this->m_w); + m_alg_r = nt_traits.convert(this->m_r); + m_alg_s = nt_traits.convert(this->m_s); + m_alg_t = nt_traits.convert(this->m_t); + m_alg_u = nt_traits.convert(this->m_u); + m_alg_v = nt_traits.convert(this->m_v); + m_alg_w = nt_traits.convert(this->m_w); // Set the generating conic ID for the source and target points. this->m_source.set_generating_conic(m_id); @@ -1164,8 +690,8 @@ private: if (! is_special_segment()) { // Check whether p satisfies the conic equation. // The point must satisfy: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0. - _sign = CGAL::sign((alg_r*px + alg_t*py + alg_u) * px + - (alg_s*py + alg_v) * py + alg_w); + _sign = CGAL::sign((m_alg_r*px + m_alg_t*py + m_alg_u) * px + + (m_alg_s*py + m_alg_v) * py + m_alg_w); } else { // Check whether p satisfies the equation of the line stored with the @@ -1236,6 +762,7 @@ private: CGAL::compare(this->m_w * factor2, arc.m_w * factor1) == EQUAL); } +public: /*! Obtain the i'th order derivative by x of the conic at the point p=(x,y). * \param p The point where we derive. * \param i The order of the derivatives (either 1, 2 or 3). @@ -1276,8 +803,8 @@ private: // 2s*y + t*x + v beta // const Algebraic two = 2; - const Algebraic sl_numer = two*alg_r*p.x() + alg_t*p.y() + alg_u; - const Algebraic sl_denom = two*alg_s*p.y() + alg_t*p.x() + alg_v; + const Algebraic sl_numer = two*m_alg_r*p.x() + m_alg_t*p.y() + m_alg_u; + const Algebraic sl_denom = two*m_alg_s*p.y() + m_alg_t*p.x() + m_alg_v; if (i == 1) { // Make sure that the denominator is always positive. @@ -1299,8 +826,8 @@ private: // y'' = -2 ------------------------------------- = ------- // beta^3 delta // - const Algebraic sl2_numer = alg_s * sl_numer*sl_numer - - alg_t * sl_numer*sl_denom + alg_r * sl_denom*sl_denom; + const Algebraic sl2_numer = m_alg_s * sl_numer*sl_numer - + m_alg_t * sl_numer*sl_denom + m_alg_r * sl_denom*sl_denom; const Algebraic sl2_denom = sl_denom*sl_denom*sl_denom; if (i == 2) { @@ -1324,7 +851,7 @@ private: // beta^2 * delta // const Algebraic sl3_numer = - (two * alg_s * sl_numer - alg_t * sl_denom) * sl2_numer; + (two * m_alg_s * sl_numer - m_alg_t * sl_denom) * sl2_numer; const Algebraic sl3_denom = sl_denom*sl_denom * sl2_denom; if (i == 3) { @@ -1385,8 +912,8 @@ private: // 2r*x + t*y + u beta // const Algebraic two = 2; - const Algebraic sl_numer = two*alg_s*p.y() + alg_t*p.x() + alg_v; - const Algebraic sl_denom = two*alg_r*p.x() + alg_t*p.y() + alg_u; + const Algebraic sl_numer = two*m_alg_s*p.y() + m_alg_t*p.x() + m_alg_v; + const Algebraic sl_denom = two*m_alg_r*p.x() + m_alg_t*p.y() + m_alg_u; if (i == 1) { // Make sure that the denominator is always positive. @@ -1408,8 +935,8 @@ private: // x'' = -2 ------------------------------------- // beta^3 // - const Algebraic sl2_numer = alg_r * sl_numer*sl_numer - - alg_t * sl_numer*sl_denom + alg_s * sl_denom*sl_denom; + const Algebraic sl2_numer = m_alg_r * sl_numer*sl_numer - + m_alg_t * sl_numer*sl_denom + m_alg_s * sl_denom*sl_denom; const Algebraic sl2_denom = sl_denom*sl_denom*sl_denom; if (i == 2) { @@ -1433,12 +960,12 @@ private: // beta^2 * delta // const Algebraic sl3_numer = - (two * alg_r * sl_numer - alg_t * sl_denom) * sl2_numer; + (two * m_alg_r * sl_numer - m_alg_t * sl_denom) * sl2_numer; const Algebraic sl3_denom = sl_denom*sl_denom * sl2_denom; if (i == 3) { // Make sure that the denominator is always positive. - if (CGAL::sign (sl_denom) != NEGATIVE) { + if (CGAL::sign(sl_denom) != NEGATIVE) { slope_numer = -6 * sl3_numer; slope_denom = sl3_denom; } @@ -1454,6 +981,7 @@ private: CGAL_error(); } +private: /*! Compute the overlap with a given arc, which is supposed to have the same * supporting conic curve as this arc. * \param arc The given arc. @@ -1555,8 +1083,8 @@ private: else { // Compute the x-coordinates of the intersection points. n_xs = compute_resultant_roots(nt_traits, - alg_r, alg_s, alg_t, - alg_u, alg_v, alg_w, + m_alg_r, m_alg_s, m_alg_t, + m_alg_u, m_alg_v, m_alg_w, deg1, arc.m_extra_data->a, arc.m_extra_data->b, @@ -1566,8 +1094,8 @@ private: // Compute the y-coordinates of the intersection points. n_ys = compute_resultant_roots(nt_traits, - alg_s, alg_r, alg_t, - alg_v, alg_u, alg_w, + m_alg_s, m_alg_r, m_alg_t, + m_alg_v, m_alg_u, m_alg_w, deg1, arc.m_extra_data->b, arc.m_extra_data->a, diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/IO_base_test.h b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/IO_base_test.h index 9065587101e..3b3a9e4c536 100644 --- a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/IO_base_test.h +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/IO_base_test.h @@ -277,8 +277,7 @@ bool read_general_arc(InputStream_& is, Curve& cv) /*! */ template -bool read_general_conic(InputStream_& is, Curve& cv) -{ +bool read_general_conic(InputStream_& is, Curve& cv) { // Read a general conic, given by its coefficients . Rational r, s, t, u, v, w; is >> r >> s >> t >> u >> v >> w; @@ -288,15 +287,16 @@ bool read_general_conic(InputStream_& is, Curve& cv) } /*! */ -template -bool read_general_curve(InputStream_& is, Curve& cv) +template +bool read_general_curve(InputStream_& is, typename Traits::Curve_2& cv, + const Traits& traits) { Rational r, s, t, u, v, w; // The conic coefficients. // Read a general conic, given by its coefficients . is >> r >> s >> t >> u >> v >> w; CGAL::Orientation orient; Point_2 source, target; - if (!read_orientation_and_end_points(is, orient, source, target)) + if (! read_orientation_and_end_points(is, orient, source, target)) return false; // Create the conic (or circular) arc. @@ -329,17 +329,17 @@ bool IO_base_test::read_xcurve(InputStream_& is, for (unsigned int i=0; i -bool read_partial_ellipse(InputStream_& is, Curve& cv) -{ +template +bool read_partial_ellipse(InputStream_& is, typename Traits::Curve_2& cv, + const Traits& traits) { bool is_circle; // Is this a circle. Rat_circle circle; Rational r, s, t, u, v, w; @@ -1050,15 +1050,16 @@ bool read_partial_ellipse(InputStream_& is, Curve& cv) return false; // Create the conic (or circular) arc. - cv = (is_circle) ? Curve(circle, orient, source, target) : - Curve(r, s, t, u, v, w, orient, source, target); + auto ctr_cv = traits.construct_curve_2_object(); + cv = (is_circle) ? ctr_cv(circle, orient, source, target) : + ctr_cv(r, s, t, u, v, w, orient, source, target); return true; } /*! */ -template -bool read_full_ellipse(InputStream_& is, Curve& cv) -{ +template +bool read_full_ellipse(InputStream_& is, typename Traits::Curve_2& cv, + const Traits& traits) { bool is_circle; // Is this a circle. Rat_circle circle; Rational r, s, t, u, v, w; @@ -1066,14 +1067,14 @@ bool read_full_ellipse(InputStream_& is, Curve& cv) return false; // Create a full ellipse (or circle). - cv = (is_circle) ? Curve(circle) : Curve(r, s, t, u, v, w); + auto ctr_cv = traits.construct_curve_2_object(); + cv = (is_circle) ? ctr_cv(circle) : ctr_cv(r, s, t, u, v, w); return true; } /*! Read a hyperbola */ -template -bool read_hyperbola(InputStream_& is, Curve& cv) -{ +template +bool read_hyperbola(InputStream_& is, Curve& cv, const Traits& traits) { // Read the hyperbola (using the format "a b x0 y0"): // 2 2 // ( x - x0 ) ( y - y0 ) @@ -1096,14 +1097,15 @@ bool read_hyperbola(InputStream_& is, Curve& cv) return false; // Create the conic (or circular) arc. - cv = Curve(r, s, t, u, v, w, orient, source, target); + auto ctr_cv = traits.construct_curve_2_object(); + cv = ctr_cv(r, s, t, u, v, w, orient, source, target); return true; } /*! Read a hyperbola */ -template -bool read_parabola(InputStream_& is, Curve& cv) -{ +template +bool read_parabola(InputStream_& is, typename Traits::Curve_2& cv, + const Traits& traits) { // Read the parabola (using the format "c x0 y0"): // // 2 @@ -1125,15 +1127,15 @@ bool read_parabola(InputStream_& is, Curve& cv) return false; // Create the conic (or circular) arc. - cv = Curve(r, s, t, u, v, w, orient, source, target); + auto ctr_cv = traits.construct_curve_2_object(); + cv = ctr_cv(r, s, t, u, v, w, orient, source, target); return true; } /*! */ -template -bool read_segment(InputStream_& is, Curve& cv) -{ - +template +bool read_segment(InputStream_& is, typename Traits::Curve_2& cv, + const Traits& traits) { // Read a segment, given by its endpoints (x1,y1) and (x2,y2); Rational x1, y1, x2, y2; is >> x1 >> y1 >> x2 >> y2; @@ -1143,19 +1145,20 @@ bool read_segment(InputStream_& is, Curve& cv) Rat_segment segment(source, target); // Create the segment. - cv = Curve(segment); + auto ctr_cv = traits.construct_curve_2_object(); + cv = ctr_cv(segment); return true; } /*! */ -template -bool read_general_arc(InputStream_& is, Curve& cv) -{ +template +bool read_general_arc(InputStream_& is, typename Traits::Curve_2& cv, + const Traits& traits) { // Read a general conic, given by its coefficients . Rational r, s, t, u, v, w; // The conic coefficients. is >> r >> s >> t >> u >> v >> w; // Read the orientation. - int i_orient = 0; + int i_orient(0); is >> i_orient; CGAL::Orientation orient = (i_orient > 0) ? CGAL::COUNTERCLOCKWISE : (i_orient < 0) ? CGAL::CLOCKWISE : CGAL::COLLINEAR; @@ -1164,7 +1167,7 @@ bool read_general_arc(InputStream_& is, Curve& cv) // whose intersection with // defines the source. Point_2 app_source; - if (!read_app_point(is, app_source)) return false; + if (! read_app_point(is, app_source)) return false; Rational r1, s1, t1, u1, v1, w1; is >> r1 >> s1 >> t1 >> u1 >> v1 >> w1; @@ -1172,32 +1175,34 @@ bool read_general_arc(InputStream_& is, Curve& cv) // whose intersection with // defines the target. Point_2 app_target; - if (!read_app_point(is, app_target)) return false; + if (! read_app_point(is, app_target)) return false; Rational r2, s2, t2, u2, v2, w2; is >> r2 >> s2 >> t2 >> u2 >> v2 >> w2; // Create the conic arc. - cv = Curve(r, s, t, u, v, w, orient, + auto ctr_cv = traits.construct_curve_2_object(); + cv = ctr_cv(r, s, t, u, v, w, orient, app_source, r1, s1, t1, u1, v1, w1, app_target, r2, s2, t2, u2, v2, w2); return true; } /*! */ -template -bool read_general_curve(InputStream_& is, Curve& cv) -{ +template +bool read_general_curve(InputStream_& is, typename Traits::Curve_2& cv, + const Traits& traits) { Rational r, s, t, u, v, w; // The conic coefficients. // Read a general conic, given by its coefficients . is >> r >> s >> t >> u >> v >> w; CGAL::Orientation orient; Point_2 source, target; - if (!read_orientation_and_end_points(is, orient, source, target)) + if (! read_orientation_and_end_points(is, orient, source, target)) return false; // Create the conic (or circular) arc. - cv = Curve(r, s, t, u, v, w, orient, source, target); + auto ctr_cv = traits.construct_curve_2_object(); + cv = ctr_cv(r, s, t, u, v, w, orient, source, target); return true; } @@ -1205,11 +1210,11 @@ bool read_general_curve(InputStream_& is, Curve& cv) template <> template bool IO_base_test::read_xcurve(InputStream_& is, - X_monotone_curve_2& xcv) -{ + X_monotone_curve_2& xcv) { Curve_2 tmp_cv; - if (!read_curve(is, tmp_cv)) return false; - xcv = X_monotone_curve_2(tmp_cv); + if (! read_curve(is, tmp_cv)) return false; + auto ctr_xcv = m_geom_traits.construct_x_monotone_curve_2_object(); + xcv = ctr_xcv(tmp_cv); return true; } @@ -1221,21 +1226,29 @@ bool IO_base_test::read_curve(InputStream_& is, Curve_2& cv) // Get the arc type: char type; is >> type; - if ((type == 'f') || (type == 'F')) return read_full_ellipse(is, cv); - else if ((type == 's') || (type == 'S')) return read_segment(is, cv); - else if ((type == 'i') || (type == 'I')) return read_general_arc(is, cv); + if ((type == 'f') || (type == 'F')) + return read_full_ellipse(is, cv, m_geom_traits); + else if ((type == 's') || (type == 'S')) + return read_segment(is, cv, m_geom_traits); + else if ((type == 'i') || (type == 'I')) + return read_general_arc(is, cv, m_geom_traits); else if ((type == 'c') || (type == 'C')) { // Read a general conic, given by its coefficients . Rational r, s, t, u, v, w; is >> r >> s >> t >> u >> v >> w; // Create a full conic (should work only for ellipses). - cv = Curve_2(r, s, t, u, v, w); + auto ctr_cv = m_geom_traits.construct_curve_2_object(); + cv = ctr_cv(r, s, t, u, v, w); return true; } - else if ((type == 'e') || (type == 'E')) return read_partial_ellipse(is, cv); - else if ((type == 'h') || (type == 'H')) return read_hyperbola(is, cv); - else if ((type == 'p') || (type == 'P')) return read_parabola(is, cv); - else if ((type == 'a') || (type == 'A')) return read_general_curve(is, cv); + else if ((type == 'e') || (type == 'E')) + return read_partial_ellipse(is, cv, m_geom_traits); + else if ((type == 'h') || (type == 'H')) + return read_hyperbola(is, cv, m_geom_traits); + else if ((type == 'p') || (type == 'P')) + return read_parabola(is, cv, m_geom_traits); + else if ((type == 'a') || (type == 'A')) + return read_general_curve(is, cv, m_geom_traits); // If we reached here, we have an unknown conic type: std::cerr << "Illegal conic type specification: " << type << "." diff --git a/Boolean_set_operations_2/examples/Boolean_set_operations_2/conic_traits_adapter.cpp b/Boolean_set_operations_2/examples/Boolean_set_operations_2/conic_traits_adapter.cpp index 3046b9f4f72..a35c90e29c6 100644 --- a/Boolean_set_operations_2/examples/Boolean_set_operations_2/conic_traits_adapter.cpp +++ b/Boolean_set_operations_2/examples/Boolean_set_operations_2/conic_traits_adapter.cpp @@ -40,51 +40,50 @@ typedef Traits_2::Point_2 Point_2; // Insert a conic arc as a polygon edge: Subdivide the arc into x-monotone // sub-arcs and append these sub-arcs as polygon edges. -void append_conic_arc (Polygon_2& polygon, const Curve_2& arc) -{ - Conic_traits_2 traits; - std::list objects; - std::list::iterator it; - X_monotone_curve_2 xarc; +void append_conic_arc(Polygon_2& polygon, const Curve_2& arc) { + Conic_traits_2 traits; + std::list objects; + X_monotone_curve_2 xarc; traits.make_x_monotone_2_object() (arc, std::back_inserter(objects)); - for (it = objects.begin(); it != objects.end(); ++it) - { + for (auto it = objects.begin(); it != objects.end(); ++it) { if (CGAL::assign (xarc, *it)) polygon.push_back (xarc); } } -int main () -{ +int main() { + Conic_traits_2 traits; + auto ctr_cv = traits.construct_curve_2_object(); + // Construct a parabolic arc supported by a parabola: x^2 + 2y - 4 = 0, // and whose endpoints lie on the line y = 0: - Curve_2 parabola1 = Curve_2 (1, 0, 0, 0, 2, -4, CGAL::COUNTERCLOCKWISE, - Point_2(2, 0), Point_2(-2, 0)); + Curve_2 parabola1 = ctr_cv(1, 0, 0, 0, 2, -4, CGAL::COUNTERCLOCKWISE, + Point_2(2, 0), Point_2(-2, 0)); // Construct a parabolic arc supported by a parabola: x^2 - 2y - 4 = 0, // and whose endpoints lie on the line y = 0: - Curve_2 parabola2 = Curve_2 (1, 0, 0, 0, -2, -4, CGAL::COUNTERCLOCKWISE, - Point_2(-2, 0), Point_2(2, 0)); + Curve_2 parabola2 = ctr_cv(1, 0, 0, 0, -2, -4, CGAL::COUNTERCLOCKWISE, + Point_2(-2, 0), Point_2(2, 0)); // Construct a polygon from these two parabolic arcs. Polygon_2 P; - append_conic_arc (P, parabola1); - append_conic_arc (P, parabola2); + append_conic_arc(P, parabola1); + append_conic_arc(P, parabola2); // Construct a polygon that corresponds to the ellipse: x^2 + 9y^2 - 9 = 0: Polygon_2 Q; - append_conic_arc (Q, Curve_2 (-1, -9, 0, 0, 0, 9)); + append_conic_arc(Q, ctr_cv(-1, -9, 0, 0, 0, 9)); // Compute the intersection of the two polygons. std::list res; - CGAL::intersection (P, Q, std::back_inserter(res)); + CGAL::intersection(P, Q, std::back_inserter(res)); - std::copy (res.begin(), res.end(), // export to standard output - std::ostream_iterator(std::cout, "\n")); + std::copy(res.begin(), res.end(), // export to standard output + std::ostream_iterator(std::cout, "\n")); std::cout << std::endl; - return (0); + return 0; } #endif From 6e50ac3fce45375655e04e281dff5031dc0fdf28 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Mon, 30 May 2022 19:13:11 +0300 Subject: [PATCH 023/105] Cintinued cleaning up --- .../Arrangement_on_surface_2/IO_base_test.h | 103 ++++++++++-------- 1 file changed, 57 insertions(+), 46 deletions(-) diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/IO_base_test.h b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/IO_base_test.h index 3b3a9e4c536..e90d8619884 100644 --- a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/IO_base_test.h +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/IO_base_test.h @@ -239,14 +239,15 @@ bool read_orientation_and_end_points(InputStream_& is, } /*! */ -template -bool read_general_arc(InputStream_& is, Curve& cv) +template +bool read_general_arc(InputStream_& is, typename Traits::Curve_2& cv, + const Traits& traits) { // Read a general conic, given by its coefficients . Rational r, s, t, u, v, w; // The conic coefficients. is >> r >> s >> t >> u >> v >> w; // Read the orientation. - int i_orient = 0; + int i_orient(0); is >> i_orient; CGAL::Orientation orient = (i_orient > 0) ? CGAL::COUNTERCLOCKWISE : (i_orient < 0) ? CGAL::CLOCKWISE : CGAL::COLLINEAR; @@ -255,7 +256,7 @@ bool read_general_arc(InputStream_& is, Curve& cv) // whose intersection with // defines the source. Point_2 app_source; - if (!read_app_point(is, app_source)) return false; + if (! read_app_point(is, app_source)) return false; Rational r1, s1, t1, u1, v1, w1; is >> r1 >> s1 >> t1 >> u1 >> v1 >> w1; @@ -263,26 +264,29 @@ bool read_general_arc(InputStream_& is, Curve& cv) // whose intersection with // defines the target. Point_2 app_target; - if (!read_app_point(is, app_target)) return false; + if (! read_app_point(is, app_target)) return false; Rational r2, s2, t2, u2, v2, w2; is >> r2 >> s2 >> t2 >> u2 >> v2 >> w2; // Create the conic arc. - cv = Curve(r, s, t, u, v, w, orient, + auto ctr_cv = traits.construct_curve_2_object(); + cv = ctr_cv(r, s, t, u, v, w, orient, app_source, r1, s1, t1, u1, v1, w1, app_target, r2, s2, t2, u2, v2, w2); return true; } /*! */ -template -bool read_general_conic(InputStream_& is, Curve& cv) { +template +bool read_general_conic(InputStream_& is, typename Traits::Curve_2& cv, + const Traits& traits) { // Read a general conic, given by its coefficients . Rational r, s, t, u, v, w; is >> r >> s >> t >> u >> v >> w; // Create a full conic (should work only for ellipses). - cv = Curve(r, s, t, u, v, w); + auto ctr_cv = traits.construct_curve_2_object(); + cv = ctr_cv(r, s, t, u, v, w); return true; } @@ -300,7 +304,8 @@ bool read_general_curve(InputStream_& is, typename Traits::Curve_2& cv, return false; // Create the conic (or circular) arc. - cv = Curve(r, s, t, u, v, w, orient, source, target); + auto ctr_cv = traits.construct_curve_2_object(); + cv = ctr_cv(r, s, t, u, v, w, orient, source, target); return true; } @@ -327,20 +332,22 @@ bool IO_base_test::read_xcurve(InputStream_& is, unsigned int number_of_curves; is >> number_of_curves; + ctr_xcv = m_geom_traits.construct_x_monotone_curve_2_object(); + for (unsigned int i=0; i::read_curve(InputStream_& is, Curve_2& cv) for (unsigned int i = 0; i < number_of_curves; ++i) { if ((type == 'a') || (type == 'A')) { - if (!read_general_curve(is, tmp_cv)) return false; + if (! read_general_curve(is, tmp_cv, m_geom_traits)) return false; conic_segments.push_back(tmp_cv); } else if ((type == 'c') || (type == 'C')) { - if (!read_general_conic(is, tmp_cv)) return false; + if (! read_general_conic(is, tmp_cv, m_geom_traits)) return false; conic_segments.push_back(tmp_cv); } else if ((type == 'i') || (type == 'I')) { - if (!read_general_arc(is, tmp_cv)) return false; + if (! read_general_arc(is, tmp_cv, m_geom_traits)) return false; conic_segments.push_back(tmp_cv); } @@ -1226,33 +1233,37 @@ bool IO_base_test::read_curve(InputStream_& is, Curve_2& cv) // Get the arc type: char type; is >> type; - if ((type == 'f') || (type == 'F')) - return read_full_ellipse(is, cv, m_geom_traits); - else if ((type == 's') || (type == 'S')) - return read_segment(is, cv, m_geom_traits); - else if ((type == 'i') || (type == 'I')) - return read_general_arc(is, cv, m_geom_traits); - else if ((type == 'c') || (type == 'C')) { - // Read a general conic, given by its coefficients . - Rational r, s, t, u, v, w; - is >> r >> s >> t >> u >> v >> w; - // Create a full conic (should work only for ellipses). - auto ctr_cv = m_geom_traits.construct_curve_2_object(); - cv = ctr_cv(r, s, t, u, v, w); - return true; + switch (type) { + case 'f': + case 'F': return read_full_ellipse(is, cv, m_geom_traits); + case 's': + case 'S': return read_segment(is, cv, m_geom_traits); + case 'i': + case 'I': return read_general_arc(is, cv, m_geom_traits); + case 'c': + case 'C': + { + // Read a general conic, given by its coefficients . + Rational r, s, t, u, v, w; + is >> r >> s >> t >> u >> v >> w; + // Create a full conic (should work only for ellipses). + auto ctr_cv = m_geom_traits.construct_curve_2_object(); + cv = ctr_cv(r, s, t, u, v, w); + return true; + } + case 'e': + case 'E': return read_partial_ellipse(is, cv, m_geom_traits); + case 'h': + case 'H': return read_hyperbola(is, cv, m_geom_traits); + case 'p': + case 'P': return read_parabola(is, cv, m_geom_traits); + case 'a': + case 'A': return read_general_curve(is, cv, m_geom_traits); + default: + // If we reached here, we have an unknown conic type: + std::cerr << "Illegal conic type specification: " << type << "." + << std::endl; } - else if ((type == 'e') || (type == 'E')) - return read_partial_ellipse(is, cv, m_geom_traits); - else if ((type == 'h') || (type == 'H')) - return read_hyperbola(is, cv, m_geom_traits); - else if ((type == 'p') || (type == 'P')) - return read_parabola(is, cv, m_geom_traits); - else if ((type == 'a') || (type == 'A')) - return read_general_curve(is, cv, m_geom_traits); - - // If we reached here, we have an unknown conic type: - std::cerr << "Illegal conic type specification: " << type << "." - << std::endl; return false; } @@ -1459,7 +1470,7 @@ bool IO_base_test::read_curve(InputStream_& is, Curve_2& cv) // If we reached here, we have an unknown rational arc type: std::cerr << "Illegal rational arc type specification: " << type << "." << std::endl; - return (false); + return false; } // Bezier From ab52d337b7c1a0d33d51df0bcec2e33cb0b3f63e Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Tue, 31 May 2022 11:15:54 +0300 Subject: [PATCH 024/105] Continued --- .../include/CGAL/Arr_conic_traits_2.h | 21 +- .../Arrangement_on_surface_2/IO_base_test.h | 51 +- .../test_conic_polycurve.cpp | 494 ++++++++---------- .../test/Surface_sweep_2/test_sweep_conic.cpp | 144 +++-- 4 files changed, 328 insertions(+), 382 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index faa0591dc37..54a3db3fe01 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -2239,8 +2239,8 @@ public: //check if the orientation conforms to the src and tgt. if( (xcv.is_directed_right() && compare_x_2(src, tgt) == LARGER) || (! xcv.is_directed_right() && compare_x_2(src, tgt) == SMALLER) ) - return (trim(xcv, tgt, src)); - else return (trim(xcv, src, tgt)); + return trim(xcv, tgt, src); + else return trim(xcv, src, tgt); } private: @@ -2258,34 +2258,35 @@ public: CGAL_precondition(xcv.contains_point(ps) && xcv.contains_point(pt)); // Make sure that the endpoints conform with the direction of the arc. + X_monotone_curve_2 res_xcv = xcv; auto cmp_xy = m_traits.m_alg_kernel->compare_xy_2_object(); if (! ((xcv.test_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT) && - (cmp_xy()(ps, pt) == SMALLER)) || + (cmp_xy(ps, pt) == SMALLER)) || (xcv.test_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT) && (cmp_xy(ps, pt) == LARGER)))) { // We are allowed to change the direction only in case of a segment. CGAL_assertion(xcv.orientation() == COLLINEAR); - xcv.flip_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT); + res_xcv.flip_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT); } // Make a copy of the current arc and assign its endpoints. - auto eq = m_traits.m_alg_kernel->equal_2_object()(); + auto eq = m_traits.m_alg_kernel->equal_2_object(); if (! eq(ps, xcv.source())) { - xcv.set_source(ps); + res_xcv.set_source(ps); if (! ps.is_generating_conic(xcv.id())) - xcv.m_source.set_generating_conic(xcv.id()); + res_xcv.source().set_generating_conic(xcv.id()); } if (! eq(pt, xcv.target())) { - xcv.set_target(pt); + res_xcv.set_target(pt); if (! pt.is_generating_conic(xcv.id())) - xcv.m_target.set_generating_conic(xcv.id()); + res_xcv.target().set_generating_conic(xcv.id()); } - return xcv; + return res_xcv; } }; diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/IO_base_test.h b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/IO_base_test.h index e90d8619884..d08285f483c 100644 --- a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/IO_base_test.h +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/IO_base_test.h @@ -293,8 +293,7 @@ bool read_general_conic(InputStream_& is, typename Traits::Curve_2& cv, /*! */ template bool read_general_curve(InputStream_& is, typename Traits::Curve_2& cv, - const Traits& traits) -{ + const Traits& traits) { Rational r, s, t, u, v, w; // The conic coefficients. // Read a general conic, given by its coefficients . is >> r >> s >> t >> u >> v >> w; @@ -313,8 +312,7 @@ bool read_general_curve(InputStream_& is, typename Traits::Curve_2& cv, template <> template bool IO_base_test::read_xcurve(InputStream_& is, - X_monotone_curve_2& xcv) -{ + X_monotone_curve_2& xcv) { // since we are dealing with polycurve, we will make more than 1 conic curves // (polycurve compatible) and return the x-monotone-constructed polycurve. @@ -329,26 +327,24 @@ bool IO_base_test::read_xcurve(InputStream_& is, is >> type; //get number of x-monotone conic-arcs. - unsigned int number_of_curves; + size_t number_of_curves; is >> number_of_curves; - ctr_xcv = m_geom_traits.construct_x_monotone_curve_2_object(); + const auto& sub_traits = *(m_geom_traits.subcurve_traits_2()); + auto ctr_xcv = sub_traits.construct_x_monotone_curve_2_object(); for (unsigned int i=0; i::read_xcurve(InputStream_& is, /*! Read a conic poly-curve */ template <> template -bool IO_base_test::read_curve(InputStream_& is, Curve_2& cv) -{ +bool IO_base_test::read_curve(InputStream_& is, Curve_2& cv) { // since we are dealing with polycurve, we will make more than 1 conic curves // (polycurve compatible) and return the constructed polycurve. @@ -383,20 +378,21 @@ bool IO_base_test::read_curve(InputStream_& is, Curve_2& cv) is >> type; //get number of xmonotone-conic arcs. - unsigned int number_of_curves; + size_t number_of_curves; is >> number_of_curves; + const auto& sub_traits = *(m_geom_traits.subcurve_traits_2()); for (unsigned int i = 0; i < number_of_curves; ++i) { if ((type == 'a') || (type == 'A')) { - if (! read_general_curve(is, tmp_cv, m_geom_traits)) return false; + if (! read_general_curve(is, tmp_cv, sub_traits)) return false; conic_segments.push_back(tmp_cv); } else if ((type == 'c') || (type == 'C')) { - if (! read_general_conic(is, tmp_cv, m_geom_traits)) return false; + if (! read_general_conic(is, tmp_cv, sub_traits)) return false; conic_segments.push_back(tmp_cv); } else if ((type == 'i') || (type == 'I')) { - if (! read_general_arc(is, tmp_cv, m_geom_traits)) return false; + if (! read_general_arc(is, tmp_cv, sub_traits)) return false; conic_segments.push_back(tmp_cv); } @@ -429,12 +425,11 @@ template bool IO_base_test::read_segment(InputStream_& is, Subcurve_2& seg) { - Subcurve_2 tmp_seg; char type; is >> type; - if (!read_general_curve(is, tmp_seg)) return false; - seg = tmp_seg; - return true; + const auto& sub_traits = *(m_geom_traits.subcurve_traits_2()); + if (! read_general_curve(is, seg, sub_traits)) return false; + return true; } template <> @@ -445,8 +440,10 @@ bool IO_base_test::read_xsegment(InputStream_& is, char type; is >> type; Subcurve_2 tmp_seg; - if (!read_general_curve(is, tmp_seg)) return false; - xseg = X_monotone_subcurve_2(tmp_seg); + const auto& sub_traits = *(m_geom_traits.subcurve_traits_2()); + if (! read_general_curve(is, tmp_seg, sub_traits)) return false; + auto ctr_xcv = sub_traits.construct_x_monotone_curve_2_object(); + xseg = ctr_xcv(tmp_seg); return true; } diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_conic_polycurve.cpp b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_conic_polycurve.cpp index 84c33b4d914..c2c3015e193 100644 --- a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_conic_polycurve.cpp +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_conic_polycurve.cpp @@ -51,43 +51,41 @@ typedef Polycurve_conic_traits_2::Point_2 Pc_point_2; // CGAL::CORE_algebraic_number_traits> // >::Point_2 test_point_2; -void check_equal() -{ +void check_equal() { bool are_equal; - Polycurve_conic_traits_2 traits; - Polycurve_conic_traits_2::Equal_2 equal = traits.equal_2_object(); - Polycurve_conic_traits_2::Construct_x_monotone_curve_2 - construct_x_monotone_curve_2 = traits.construct_x_monotone_curve_2_object(); + Conic_traits_2 sub_traits; + Polycurve_conic_traits_2 traits(&sub_traits); + auto equal = traits.equal_2_object(); + auto ctr_xcv = traits.construct_x_monotone_curve_2_object(); + auto ctr_sub_cv = sub_traits.construct_curve_2_object(); //create some curves Conic_point_2 ps1(Rational(1,4), 4); Conic_point_2 pt1(2, Rational(1,2)); - Conic_curve_2 c1(0, 0, 1, 0, 0, -1, CGAL::COUNTERCLOCKWISE, ps1, pt1); + Conic_curve_2 c1 = + ctr_sub_cv(0, 0, 1, 0, 0, -1, CGAL::COUNTERCLOCKWISE, ps1, pt1); Conic_point_2 ps2(Rational(1,4), 4); Conic_point_2 pt2(2, Rational(1,2)); - Conic_curve_2 c2(0, 0, 1, 0, 0, -1, CGAL::COUNTERCLOCKWISE, ps2, pt2); + Conic_curve_2 c2 = + ctr_sub_cv(0, 0, 1, 0, 0, -1, CGAL::COUNTERCLOCKWISE, ps2, pt2); Rat_point_2 ps3(Rational(1,4), 4); Rat_point_2 pmid3(Rational(3,2), 2); Rat_point_2 pt3(2, Rational(1,3)); - Conic_curve_2 c3(ps3, pmid3, pt3); + Conic_curve_2 c3 = ctr_sub_cv(ps3, pmid3, pt3); Rat_point_2 ps4(1, 5); Rat_point_2 pmid4(Rational(3,2), 3); Rat_point_2 pt4(3, Rational(1,3)); - Conic_curve_2 c4(ps4, pmid4, pt4); + Conic_curve_2 c4 = ctr_sub_cv(ps4, pmid4, pt4); // //make x_monotone - Polycurve_conic_traits_2::X_monotone_curve_2 xmc1 = - construct_x_monotone_curve_2(c1); - Polycurve_conic_traits_2::X_monotone_curve_2 xmc2 = - construct_x_monotone_curve_2(c2); - Polycurve_conic_traits_2::X_monotone_curve_2 xmc3 = - construct_x_monotone_curve_2(c3); - Polycurve_conic_traits_2::X_monotone_curve_2 xmc4 = - construct_x_monotone_curve_2(c4); + Polycurve_conic_traits_2::X_monotone_curve_2 xmc1 = ctr_xcv(c1); + Polycurve_conic_traits_2::X_monotone_curve_2 xmc2 = ctr_xcv(c2); + Polycurve_conic_traits_2::X_monotone_curve_2 xmc3 = ctr_xcv(c3); + Polycurve_conic_traits_2::X_monotone_curve_2 xmc4 = ctr_xcv(c4); are_equal = equal(xmc1, xmc2); std::cout << "Two equal conic arcs are computed as: " @@ -105,8 +103,7 @@ void check_equal() template void check_intersect(typename Traits::X_monotone_curve_2& xcv1, typename Traits::X_monotone_curve_2& xcv2, - const Traits& traits) - { + const Traits& traits) { typedef typename Traits::Multiplicity Multiplicity; typedef typename Traits::Point_2 Point_2; typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; @@ -115,8 +112,8 @@ void check_equal() Intersection_result; std::vector intersection_points; - traits.intersect_2_object()(xcv1, xcv2, - std::back_inserter(intersection_points)); + auto intersect = traits.intersect_2_object(); + intersect(xcv1, xcv2, std::back_inserter(intersection_points)); std::cout<< "Number of intersection Points: " << intersection_points.size() << std::endl; @@ -134,13 +131,12 @@ void check_equal() // } } -void check_compare_end_points_xy_2() -{ - Polycurve_conic_traits_2 traits; - Polycurve_conic_traits_2::Construct_x_monotone_curve_2 - construct_x_monotone_curve_2 = traits.construct_x_monotone_curve_2_object(); - Polycurve_conic_traits_2::Compare_endpoints_xy_2 compare_endpoints_xy_2 = - traits.compare_endpoints_xy_2_object(); +void check_compare_end_points_xy_2() { + Conic_traits_2 sub_traits; + Polycurve_conic_traits_2 traits(&sub_traits); + auto ctr_xcv = traits.construct_x_monotone_curve_2_object(); + auto cmp_endpoints = traits.compare_endpoints_xy_2_object(); + auto ctr_sub_cv = sub_traits.construct_curve_2_object(); //create some curves Conic_point_2 ps1(Rational(1,4), 4); @@ -154,69 +150,69 @@ void check_compare_end_points_xy_2() // as the intersections of the parabola with the lines y = -3 and y = -2. // Note that the arc is clockwise oriented. Conic_curve_2 - c2 = Conic_curve_2(1, 0, 0, 0, 1, 0, // The parabola. - CGAL::CLOCKWISE, - Conic_point_2(-1.73, -3), // Approximation of the source. - 0, 0, 0, 0, 1, 3, // The line: y = -3. - Conic_point_2(1.41, -2), // Approximation of the target. - 0, 0, 0, 0, 1, 2); // The line: y = -2. + c2 = ctr_sub_cv(1, 0, 0, 0, 1, 0, // The parabola. + CGAL::CLOCKWISE, + Conic_point_2(-1.73, -3), // Approximation of the source. + 0, 0, 0, 0, 1, 3, // The line: y = -3. + Conic_point_2(1.41, -2), // Approximation of the target. + 0, 0, 0, 0, 1, 2); // The line: y = -2. assert(c2.is_valid()); //make polyline x-monotone curves - Polycurve_conic_traits_2::X_monotone_curve_2 polyline_xmc1 = - construct_x_monotone_curve_2(c1); - Polycurve_conic_traits_2::X_monotone_curve_2 polyline_xmc2 = - construct_x_monotone_curve_2(c2); + Polycurve_conic_traits_2::X_monotone_curve_2 polyline_xmc1 = ctr_xcv(c1); + Polycurve_conic_traits_2::X_monotone_curve_2 polyline_xmc2 = ctr_xcv(c2); - CGAL::Comparison_result res = compare_endpoints_xy_2(polyline_xmc1); + CGAL::Comparison_result res = cmp_endpoints(polyline_xmc1); std::cout << "compare_end_points_xy_2 for counterclockwise curve: " << (res == CGAL::SMALLER ? "SMALLER": (res == CGAL::LARGER ? "LARGER" : "EQUAL")) << std::endl; - res = compare_endpoints_xy_2(polyline_xmc2); + res = cmp_endpoints(polyline_xmc2); std::cout<< "compare_end_points_xy_2 for clockwise curve: " << (res == CGAL::SMALLER ? "SMALLER": (res == CGAL::LARGER ? "LARGER" : "EQUAL")) << std::endl; } template -void check_split(Curve_type &xcv1, Curve_type &xcv2) -{ - Polycurve_conic_traits_2 traits; +void check_split(Curve_type& xcv1, Curve_type& xcv2) { + Conic_traits_2 sub_traits; + Polycurve_conic_traits_2 traits(&sub_traits); + auto ctr_sub_cv = sub_traits.construct_curve_2_object(); + auto ctr_sub_xcv = sub_traits.construct_x_monotone_curve_2_object(); //split x poly-curves - Conic_curve_2 c6(1,1,0,6,-26,162,CGAL::COUNTERCLOCKWISE, - Conic_point_2(Algebraic(-7), Algebraic(13)), - Conic_point_2(Algebraic(-3), Algebraic(9))); - Conic_curve_2 c7(1,0,0,0,-1,0,CGAL::COUNTERCLOCKWISE, - Conic_point_2(Algebraic(-3), Algebraic(9)), - Conic_point_2(Algebraic(0), Algebraic(0))); - Conic_curve_2 c8(0,1,0,-1,0,0, CGAL::COUNTERCLOCKWISE, - Conic_point_2(Algebraic(0), Algebraic(0)), - Conic_point_2(Algebraic(4), Algebraic(-2))); + Conic_curve_2 c6 = ctr_sub_cv(1,1,0,6,-26,162,CGAL::COUNTERCLOCKWISE, + Conic_point_2(Algebraic(-7), Algebraic(13)), + Conic_point_2(Algebraic(-3), Algebraic(9))); + Conic_curve_2 c7 = ctr_sub_cv(1,0,0,0,-1,0,CGAL::COUNTERCLOCKWISE, + Conic_point_2(Algebraic(-3), Algebraic(9)), + Conic_point_2(Algebraic(0), Algebraic(0))); + Conic_curve_2 c8 = ctr_sub_cv(0,1,0,-1,0,0, CGAL::COUNTERCLOCKWISE, + Conic_point_2(Algebraic(0), Algebraic(0)), + Conic_point_2(Algebraic(4), Algebraic(-2))); - Conic_x_monotone_curve_2 xc6(c6); - Conic_x_monotone_curve_2 xc7(c7); - Conic_x_monotone_curve_2 xc8(c8); + Conic_x_monotone_curve_2 xc6 = ctr_sub_xcv(c6); + Conic_x_monotone_curve_2 xc7 = ctr_sub_xcv(c7); + Conic_x_monotone_curve_2 xc8 = ctr_sub_xcv(c8); std::vector xmono_conic_curves_2; + auto ctr_xcv = traits.construct_x_monotone_curve_2_object(); + xmono_conic_curves_2.push_back(xc6); xmono_conic_curves_2.push_back(xc7); Pc_x_monotone_curve_2 split_expected_1 = - traits.construct_x_monotone_curve_2_object()(xmono_conic_curves_2.begin(), - xmono_conic_curves_2.end()); + ctr_xcv(xmono_conic_curves_2.begin(), xmono_conic_curves_2.end()); xmono_conic_curves_2.clear(); xmono_conic_curves_2.push_back(xc8); Pc_x_monotone_curve_2 split_expected_2 = - traits.construct_x_monotone_curve_2_object()(xmono_conic_curves_2.begin(), - xmono_conic_curves_2.end()); + ctr_xcv(xmono_conic_curves_2.begin(), xmono_conic_curves_2.end()); Polycurve_conic_traits_2::X_monotone_curve_2 split_curve_1, split_curve_2; - Polycurve_conic_traits_2::Point_2 - point_of_split = Polycurve_conic_traits_2::Point_2(0,0); + Polycurve_conic_traits_2::Point_2 point_of_split = + Polycurve_conic_traits_2::Point_2(0,0); //Split functor traits.split_2_object()(xcv2, point_of_split, split_curve_1, split_curve_2); @@ -230,23 +226,21 @@ void check_split(Curve_type &xcv1, Curve_type &xcv2) std::cout << "Something is wrong with split" << std::endl; } -void check_is_vertical() -{ - Polycurve_conic_traits_2 traits; - Polycurve_conic_traits_2::Construct_x_monotone_curve_2 - construct_x_monotone_curve_2 = traits.construct_x_monotone_curve_2_object(); - Polycurve_conic_traits_2::Is_vertical_2 is_vertical = - traits.is_vertical_2_object(); +void check_is_vertical() { + Conic_traits_2 sub_traits; + Polycurve_conic_traits_2 traits(&sub_traits); + auto ctr_sub_cv = sub_traits.construct_curve_2_object(); + auto ctr_xcv = traits.construct_x_monotone_curve_2_object(); + auto is_vertical = traits.is_vertical_2_object(); //create a curve Rat_point_2 ps1(1, 10); Rat_point_2 pmid1(5, 4); Rat_point_2 pt1(10, 1); - Conic_curve_2 c1(ps1, pmid1, pt1); + Conic_curve_2 c1 = ctr_sub_cv(ps1, pmid1, pt1); //make x-monotone curve - Polycurve_conic_traits_2::X_monotone_curve_2 polyline_xmc1 = - construct_x_monotone_curve_2(c1); + Polycurve_conic_traits_2::X_monotone_curve_2 polyline_xmc1 = ctr_xcv(c1); bool result = is_vertical(polyline_xmc1); std::cout << "Is_verticle:: Expected first result is not vertivle: Computed: " @@ -255,8 +249,7 @@ void check_is_vertical() /*! */ template -bool read_orientation(stream& is, CGAL::Orientation& orient) -{ +bool read_orientation(stream& is, CGAL::Orientation& orient) { int i_orient; is >> i_orient; orient = (i_orient > 0) ? CGAL::COUNTERCLOCKWISE : @@ -266,8 +259,7 @@ bool read_orientation(stream& is, CGAL::Orientation& orient) /*! */ template -bool read_app_point(stream& is, Conic_point_2& p) -{ +bool read_app_point(stream& is, Conic_point_2& p) { //waqar: original double x, y; is >> x >> y; @@ -291,18 +283,18 @@ bool read_orientation_and_end_points(stream& is, CGAL::Orientation& orient, Conic_point_2& target) { // Read the orientation. - if (!read_orientation(is, orient)) return false; + if (! read_orientation(is, orient)) return false; // Read the end points of the arc and create it. - if (!read_app_point(is, source)) return false; - if (!read_app_point(is, target)) return false; + if (! read_app_point(is, source)) return false; + if (! read_app_point(is, target)) return false; return true; } /*! */ -template -bool read_general_arc(stream& is, Curve& cv) -{ +template +bool read_general_arc(stream& is, typename Traits::Curve_2& cv, + const Traits& traits) { // Read a general conic, given by its coefficients . Rational r, s, t, u, v, w; // The conic coefficients. is >> r >> s >> t >> u >> v >> w; @@ -316,7 +308,7 @@ bool read_general_arc(stream& is, Curve& cv) // whose intersection with // defines the source. Conic_point_2 app_source; - if (!read_app_point(is, app_source)) return false; + if (! read_app_point(is, app_source)) return false; Rational r1, s1, t1, u1, v1, w1; is >> r1 >> s1 >> t1 >> u1 >> v1 >> w1; @@ -324,7 +316,7 @@ bool read_general_arc(stream& is, Curve& cv) // whose intersection with // defines the target. Conic_point_2 app_target; - if (!read_app_point(is, app_target)) return false; + if (! read_app_point(is, app_target)) return false; Rational r2, s2, t2, u2, v2, w2; is >> r2 >> s2 >> t2 >> u2 >> v2 >> w2; @@ -334,34 +326,36 @@ bool read_general_arc(stream& is, Curve& cv) << r2 << s2 << t2 << u2 << v2 << w2 << std::endl; // Create the conic arc. - cv = Curve(r, s, t, u, v, w, orient, - app_source, r1, s1, t1, u1, v1, w1, - app_target, r2, s2, t2, u2, v2, w2); + auto ctr_cv = traits.construct_curve_2_object(); + cv = ctr_cv(r, s, t, u, v, w, orient, + app_source, r1, s1, t1, u1, v1, w1, + app_target, r2, s2, t2, u2, v2, w2); return true; } /*! */ -template -bool read_general_conic(stream& is, Curve& cv) -{ +template +bool read_general_conic(stream& is, typename Traits::Curve_2& cv, + const Traits& traits) { // Read a general conic, given by its coefficients . Rational r, s, t, u, v, w; is >> r >> s >> t >> u >> v >> w; // Create a full conic (should work only for ellipses). - cv = Curve(r, s, t, u, v, w); + auto ctr_cv = traits.construct_curve_2_object(); + cv = ctr_cv(r, s, t, u, v, w); return true; } // /*! */ -template -bool read_general_curve(stream& is, Curve& cv) -{ +template +bool read_general_curve(stream& is, typename Traits::Curve_2& cv, + const Traits& traits) { Rational r, s, t, u, v, w; // The conic coefficients. // Read a general conic, given by its coefficients . is >> r >> s >> t >> u >> v >> w; CGAL::Orientation orient; Conic_point_2 source, target; - if (!read_orientation_and_end_points(is, orient, source, target)) + if (! read_orientation_and_end_points(is, orient, source, target)) return false; // Create the conic (or circular) arc. @@ -369,26 +363,25 @@ bool read_general_curve(stream& is, Curve& cv) // << u << " " << v << " " << w << std::endl; // std::cout << "Read Points : " << source.x() << " " << source.y() << " " // << target.x() << " " << target.y() << std::endl; - cv = Curve(r, s, t, u, v, w, orient, source, target); + auto ctr_cv = traits.construct_curve_2_object(); + cv = ctr_cv(r, s, t, u, v, w, orient, source, target); return true; } -std::istream& skip_comments(std::istream& is, std::string& line) -{ +std::istream& skip_comments(std::istream& is, std::string& line) { while (std::getline(is, line)) if (!line.empty() && (line[0] != '#')) break; return is; } -bool check_compare_y_at_x_2() -{ - Polycurve_conic_traits_2 traits; - Polycurve_conic_traits_2::Compare_y_at_x_2 cmp_y_at_x_2 = - traits.compare_y_at_x_2_object(); +bool check_compare_y_at_x_2() { + Conic_traits_2 sub_traits; + Polycurve_conic_traits_2 traits(&sub_traits); + auto ctr_sub_cv = sub_traits.construct_curve_2_object(); + auto ctr_sub_xcv = sub_traits.construct_x_monotone_curve_2_object(); + auto cmp_y_at_x_2 = traits.compare_y_at_x_2_object(); //polycurve constructors - Polycurve_conic_traits_2::Construct_x_monotone_curve_2 - construct_x_mono_polycurve = traits.construct_x_monotone_curve_2_object(); - Polycurve_conic_traits_2::Construct_curve_2 construct_polycurve = - traits.construct_curve_2_object(); + auto construct_x_mono_polycurve = traits.construct_x_monotone_curve_2_object(); + auto ctr_cv = traits.construct_curve_2_object(); //create a curve Rat_point_2 ps1(1, 10); @@ -400,14 +393,14 @@ bool check_compare_y_at_x_2() Rat_point_2 ps2(10, 1); Rat_point_2 pmid2(15, 5); Rat_point_2 pt2(20, 10); - Conic_curve_2 c2(ps2, pmid2, pt2); + Conic_curve_2 c2 = ctr_sub_cv(ps2, pmid2, pt2); - Conic_curve_2 c3(1,0,0,0,-1,0,CGAL::COUNTERCLOCKWISE, - Conic_point_2(Algebraic(0), Algebraic(0)), - Conic_point_2(Algebraic(3), Algebraic(9))); - Conic_curve_2 c4(1,0,0,0,-1,0,CGAL::COUNTERCLOCKWISE, - Conic_point_2(Algebraic(3), Algebraic(9)), - Conic_point_2(Algebraic(5), Algebraic(25))); + Conic_curve_2 c3 = ctr_sub_cv(1,0,0,0,-1,0,CGAL::COUNTERCLOCKWISE, + Conic_point_2(Algebraic(0), Algebraic(0)), + Conic_point_2(Algebraic(3), Algebraic(9))); + Conic_curve_2 c4 = ctr_sub_cv(1,0,0,0,-1,0,CGAL::COUNTERCLOCKWISE, + Conic_point_2(Algebraic(3), Algebraic(9)), + Conic_point_2(Algebraic(5), Algebraic(25))); std::vector conic_curves, conic_curves_2, Conic_curves_3; conic_curves.push_back(c1); @@ -416,10 +409,10 @@ bool check_compare_y_at_x_2() //conic_curves_2.push_back(c3); //conic_curves_2.push_back(c4); - Conic_x_monotone_curve_2 xc1(c1); - Conic_x_monotone_curve_2 xc2(c2); - Conic_x_monotone_curve_2 xc3(c3); - Conic_x_monotone_curve_2 xc4(c4); + Conic_x_monotone_curve_2 xc1 = ctr_sub_xcv(c1); + Conic_x_monotone_curve_2 xc2 = ctr_sub_xcv(c2); + Conic_x_monotone_curve_2 xc3 = ctr_sub_xcv(c3); + Conic_x_monotone_curve_2 xc4 = ctr_sub_xcv(c4); std::vector xmono_conic_curves, xmono_conic_curves_2; /* VERY IMPORTANT @@ -442,13 +435,13 @@ bool check_compare_y_at_x_2() //construct poly-curve Polycurve_conic_traits_2::Curve_2 conic_polycurve = - construct_polycurve(conic_curves.begin(), conic_curves.end()); + ctr_cv(conic_curves.begin(), conic_curves.end()); //Polycurve_conic_traits_2::Curve_2 conic_polycurve_2 = - // construct_polycurve(conic_curves_2.begin(), conic_curves_2.end()); + // ctr_cv(conic_curves_2.begin(), conic_curves_2.end()); //make x-monotone curve //Polycurve_conic_traits_2::X_monotone_curve_2 polyline_xmc1 = - // construct_x_monotone_curve_2(c1); + // ctr_xcv(c1); //create points Polycurve_conic_traits_2::Point_2 @@ -476,37 +469,33 @@ bool check_compare_y_at_x_2() return true; } -void check_are_mergable() -{ - Polycurve_conic_traits_2 traits; - Polycurve_conic_traits_2::Construct_x_monotone_curve_2 - construct_x_monotone_curve_2 = traits.construct_x_monotone_curve_2_object(); - Polycurve_conic_traits_2::Are_mergeable_2 are_mergeable_2 = - traits.are_mergeable_2_object(); +void check_are_mergable() { + Conic_traits_2 sub_traits; + Polycurve_conic_traits_2 traits(&sub_traits); + auto ctr_sub_cv = sub_traits.construct_curve_2_object(); + auto ctr_xcv = traits.construct_x_monotone_curve_2_object(); + auto are_mergeable_2 = traits.are_mergeable_2_object(); //create a curve Rat_point_2 ps1(1, 10); Rat_point_2 pmid1(5, 4); Rat_point_2 pt1(10, 1); - Conic_curve_2 c1(ps1, pmid1, pt1); + Conic_curve_2 c1 = ctr_sub_cv(ps1, pmid1, pt1); Rat_point_2 ps2(10, 1); Rat_point_2 pmid2(15, 14); Rat_point_2 pt2(20, 20); - Conic_curve_2 c2(ps2, pmid2, pt2); + Conic_curve_2 c2 = ctr_sub_cv(ps2, pmid2, pt2); Rat_point_2 ps3(Rational(1,4), 4); Rat_point_2 pmid3(Rational(3,2), 2); Rat_point_2 pt3(2, Rational(1,3)); - Conic_curve_2 c3(ps3, pmid3, pt3); + Conic_curve_2 c3 = ctr_sub_cv(ps3, pmid3, pt3); //construct x-monotone curve(compatible with polyline class) - Polycurve_conic_traits_2::X_monotone_curve_2 polyline_xmc1 = - construct_x_monotone_curve_2(c1); - Polycurve_conic_traits_2::X_monotone_curve_2 polyline_xmc2 = - construct_x_monotone_curve_2(c2); - Polycurve_conic_traits_2::X_monotone_curve_2 polyline_xmc3 = - construct_x_monotone_curve_2(c3); + Polycurve_conic_traits_2::X_monotone_curve_2 polyline_xmc1 = ctr_xcv(c1); + Polycurve_conic_traits_2::X_monotone_curve_2 polyline_xmc2 = ctr_xcv(c2); + Polycurve_conic_traits_2::X_monotone_curve_2 polyline_xmc3 = ctr_xcv(c3); bool result = are_mergeable_2(polyline_xmc1, polyline_xmc2); std::cout << "Are_mergable:: Mergable x-monotone polycurves are Computed as: " @@ -517,29 +506,27 @@ void check_are_mergable() << ((result)? "Mergable" : "Not-Mergable") << std::endl; } -void check_merge_2() -{ - Polycurve_conic_traits_2 traits; - Polycurve_conic_traits_2::Construct_x_monotone_curve_2 - construct_x_monotone_curve_2 = traits.construct_x_monotone_curve_2_object(); - Polycurve_conic_traits_2::Merge_2 merge_2 = traits.merge_2_object(); +void check_merge_2() { + Conic_traits_2 sub_traits; + Polycurve_conic_traits_2 traits(&sub_traits); + auto ctr_sub_cv = sub_traits.construct_curve_2_object(); + auto ctr_xcv = traits.construct_x_monotone_curve_2_object(); + auto merge_2 = traits.merge_2_object(); //create a curve Rat_point_2 ps1(1, 10); Rat_point_2 pmid1(5, 4); Rat_point_2 pt1(10, 1); - Conic_curve_2 c1(ps1, pmid1, pt1); + Conic_curve_2 c1 = ctr_sub_cv(ps1, pmid1, pt1); Rat_point_2 ps2(10, 1); Rat_point_2 pmid2(15, 14); Rat_point_2 pt2(20, 20); - Conic_curve_2 c2(ps2, pmid2, pt2); + Conic_curve_2 c2 = ctr_sub_cv(ps2, pmid2, pt2); //construct x-monotone curve (compatible with polyline class) - Polycurve_conic_traits_2::X_monotone_curve_2 polyline_xmc1 = - construct_x_monotone_curve_2(c1); - Polycurve_conic_traits_2::X_monotone_curve_2 polyline_xmc2 = - construct_x_monotone_curve_2(c2); + Polycurve_conic_traits_2::X_monotone_curve_2 polyline_xmc1 = ctr_xcv(c1); + Polycurve_conic_traits_2::X_monotone_curve_2 polyline_xmc2 = ctr_xcv(c2); Polycurve_conic_traits_2::X_monotone_curve_2 merged_xmc; @@ -548,101 +535,93 @@ void check_merge_2() << std:: endl; } -void check_construct_opposite() -{ - Polycurve_conic_traits_2 traits; - Polycurve_conic_traits_2::Construct_x_monotone_curve_2 - construct_x_monotone_curve_2 = traits.construct_x_monotone_curve_2_object(); - Polycurve_conic_traits_2::Construct_opposite_2 construct_opposite_2 = - traits.construct_opposite_2_object(); +void check_construct_opposite() { + Conic_traits_2 sub_traits; + Polycurve_conic_traits_2 traits(&sub_traits); + auto ctr_sub_cv = sub_traits.construct_curve_2_object(); + auto ctr_xcv = traits.construct_x_monotone_curve_2_object(); + auto ctr_opposite = traits.construct_opposite_2_object(); //create a curve Rat_point_2 ps1(1, 10); Rat_point_2 pmid1(5, 4); Rat_point_2 pt1(10, 1); - Conic_curve_2 c1(ps1, pmid1, pt1); + Conic_curve_2 c1 = ctr_sub_cv(ps1, pmid1, pt1); //construct x-monotone curve (compatible with polyline class) Polycurve_conic_traits_2::X_monotone_curve_2 polyline_xmc1 = - construct_x_monotone_curve_2(c1); + ctr_xcv(c1); Polycurve_conic_traits_2::X_monotone_curve_2 polyline_opposite_curve = - construct_opposite_2(polyline_xmc1); + ctr_opposite(polyline_xmc1); std::cout<< "Construct_opposite_2:: Opposite curve created"; } -void check_compare_y_at_x_right() -{ - Polycurve_conic_traits_2 traits; - Polycurve_conic_traits_2::Construct_x_monotone_curve_2 - construct_x_monotone_curve_2 = traits.construct_x_monotone_curve_2_object(); - Polycurve_conic_traits_2::Compare_y_at_x_right_2 cmp_y_at_x_right_2 = - traits.compare_y_at_x_right_2_object(); +void check_compare_y_at_x_right() { + Conic_traits_2 sub_traits; + Polycurve_conic_traits_2 traits(&sub_traits); + auto ctr_sub_cv = sub_traits.construct_curve_2_object(); + auto ctr_xcv = traits.construct_x_monotone_curve_2_object(); + auto cmp_y_at_x_right = traits.compare_y_at_x_right_2_object(); //create constructing curves Rat_point_2 ps2(1, 10); Rat_point_2 pmid2(5, 4); Rat_point_2 pt2(10, 1); - Conic_curve_2 c1(ps2, pmid2, pt2); + Conic_curve_2 c1 = ctr_sub_cv(ps2, pmid2, pt2); Rat_point_2 ps3(10, 1); Rat_point_2 pmid3(5, 4); Rat_point_2 pt3(1, 10); - Conic_curve_2 c2(ps3, pmid3, pt3); + Conic_curve_2 c2 = ctr_sub_cv(ps3, pmid3, pt3); //construct x-monotone curve (compatible with polyline class) - Polycurve_conic_traits_2::X_monotone_curve_2 polyline_xmc1 = - construct_x_monotone_curve_2(c1); - Polycurve_conic_traits_2::X_monotone_curve_2 polyline_xmc2 = - construct_x_monotone_curve_2(c2); + Polycurve_conic_traits_2::X_monotone_curve_2 polyline_xmc1 = ctr_xcv(c1); + Polycurve_conic_traits_2::X_monotone_curve_2 polyline_xmc2 = ctr_xcv(c2); Polycurve_conic_traits_2::Point_2 intersection_point = Polycurve_conic_traits_2::Point_2(5,4); CGAL::Comparison_result result; - result = cmp_y_at_x_right_2(polyline_xmc1, polyline_xmc2, intersection_point); + result = cmp_y_at_x_right(polyline_xmc1, polyline_xmc2, intersection_point); std::cout << "Compare_y_at_x_right:: Expected Answer: equal, Computed answer: " << (result == CGAL::SMALLER ? "smaller": (result == CGAL::LARGER ? "Larger" : "equal")) << std::endl; } -void check_compare_y_at_x_left() -{ - Polycurve_conic_traits_2 traits; - Polycurve_conic_traits_2::Construct_x_monotone_curve_2 - construct_x_monotone_curve_2 = traits.construct_x_monotone_curve_2_object(); - Polycurve_conic_traits_2::Compare_y_at_x_left_2 cmp_y_at_x_left_2 = - traits.compare_y_at_x_left_2_object(); +void check_compare_y_at_x_left() { + Conic_traits_2 sub_traits; + Polycurve_conic_traits_2 traits(&sub_traits); + auto ctr_sub_cv = sub_traits.construct_curve_2_object(); + auto ctr_xcv = traits.construct_x_monotone_curve_2_object(); + auto cmp_y_at_x_left = traits.compare_y_at_x_left_2_object(); //create constructing curves Rat_point_2 ps2(1, 10); Rat_point_2 pmid2(5, 4); Rat_point_2 pt2(10, 1); - Conic_curve_2 c1(ps2, pmid2, pt2); + Conic_curve_2 c1 = ctr_sub_cv(ps2, pmid2, pt2); Rat_point_2 ps3(10, 1); Rat_point_2 pmid3(5, 4); Rat_point_2 pt3(1, 10); - Conic_curve_2 c2(ps3, pmid3, pt3); + Conic_curve_2 c2 = ctr_sub_cv(ps3, pmid3, pt3); //construct x-monotone curve(compatible with polyline class) - Polycurve_conic_traits_2::X_monotone_curve_2 polyline_xmc1 = - construct_x_monotone_curve_2(c1); - Polycurve_conic_traits_2::X_monotone_curve_2 polyline_xmc2 = - construct_x_monotone_curve_2(c2); + Polycurve_conic_traits_2::X_monotone_curve_2 polyline_xmc1 = ctr_xcv(c1); + Polycurve_conic_traits_2::X_monotone_curve_2 polyline_xmc2 = ctr_xcv(c2); Polycurve_conic_traits_2::Point_2 intersection_point = Polycurve_conic_traits_2::Point_2(5,4); CGAL::Comparison_result result; - result = cmp_y_at_x_left_2(polyline_xmc1, polyline_xmc2, intersection_point); + result = cmp_y_at_x_left(polyline_xmc1, polyline_xmc2, intersection_point); std::cout << "Compare_y_at_x_left:: Expected Answer: equal, Computed answer: " << (result == CGAL::SMALLER ? "smaller": (result == CGAL::LARGER ? "Larger" : "equal")) << std::endl; } template -void check_make_x_monotne_curve(const typename GeometryTraits::Curve_2& c1) -{ +void check_make_x_monotne_curve(const typename GeometryTraits::Curve_2& c1) { typename GeometryTraits::Point_2 Point_2; typename GeometryTraits::X_monotone_curve_2 X_monotone_curve_2; typedef boost::variant Make_x_monotone_result; @@ -663,8 +642,7 @@ void check_make_x_monotne_curve(const typename GeometryTraits::Curve_2& c1) } template -void check_push_front(Curve base_curve, Segment curve_tobe_pushed) -{ +void check_push_front(Curve base_curve, Segment curve_tobe_pushed) { Polycurve_conic_traits_2 traits; std::cout << "Base curve: " << base_curve << std::endl; @@ -675,8 +653,7 @@ void check_push_front(Curve base_curve, Segment curve_tobe_pushed) } template -void check_push_back(Curve& base_curve, Segment curve_tobe_pushed) -{ +void check_push_back(Curve& base_curve, Segment curve_tobe_pushed) { Polycurve_conic_traits_2 traits; std::cout << "Base curve: " << base_curve << std::endl; @@ -688,8 +665,7 @@ void check_push_back(Curve& base_curve, Segment curve_tobe_pushed) } template -void check_compare_x_2(const Segment& seg1, const Segment& seg2) -{ +void check_compare_x_2(const Segment& seg1, const Segment& seg2) { Polycurve_conic_traits_2 traits; CGAL::Comparison_result result; @@ -707,16 +683,14 @@ void check_compare_x_2(const Segment& seg1, const Segment& seg2) } template -void check_compare_points(Curve& cv) -{ +void check_compare_points(Curve& cv) { Polycurve_conic_traits_2 traits; CGAL::Arr_parameter_space result = traits.parameter_space_in_x_2_object()(cv, CGAL::ARR_MAX_END); } template -void check_trim(curve& xcv, int sx, int sy, int tx, int ty) -{ +void check_trim(curve& xcv, int sx, int sy, int tx, int ty) { Polycurve_conic_traits_2 traits; // Conic_point_2 source(Algebraic(-16), Algebraic(-4)); @@ -732,39 +706,41 @@ void check_trim(curve& xcv, int sx, int sy, int tx, int ty) } -int main(int argc, char* argv[]) -{ - Polycurve_conic_traits_2 traits; +int main(int argc, char* argv[]) { + Conic_traits_2 sub_traits; + Polycurve_conic_traits_2 traits(&sub_traits); + auto ctr_sub_cv = sub_traits.construct_curve_2_object(); + auto ctr_sub_xcv = sub_traits.construct_x_monotone_curve_2_object(); //polycurve constructors - auto construct_x_mono_polycurve = traits.construct_x_monotone_curve_2_object(); - auto construct_polycurve = traits.construct_curve_2_object(); + auto ctr_xcv = traits.construct_x_monotone_curve_2_object(); + auto ctr_cv = traits.construct_curve_2_object(); //create a curve - Conic_curve_2 c3(1,0,0,0,-1,0,CGAL::COUNTERCLOCKWISE, - Conic_point_2(Algebraic(0), Algebraic(0)), - Conic_point_2(Algebraic(3), Algebraic(9))); - Conic_curve_2 c4(1,0,0,0,-1,0,CGAL::COUNTERCLOCKWISE, - Conic_point_2(Algebraic(3), Algebraic(9)), - Conic_point_2(Algebraic(5), Algebraic(25))); - Conic_curve_2 c5(0,1,0,1,0,0, CGAL::COUNTERCLOCKWISE, - Conic_point_2(Algebraic(-25), Algebraic(-5)), - Conic_point_2(Algebraic(0), Algebraic(0))); + Conic_curve_2 c3 = ctr_sub_cv(1,0,0,0,-1,0,CGAL::COUNTERCLOCKWISE, + Conic_point_2(Algebraic(0), Algebraic(0)), + Conic_point_2(Algebraic(3), Algebraic(9))); + Conic_curve_2 c4 = ctr_sub_cv(1,0,0,0,-1,0,CGAL::COUNTERCLOCKWISE, + Conic_point_2(Algebraic(3), Algebraic(9)), + Conic_point_2(Algebraic(5), Algebraic(25))); + Conic_curve_2 c5 = ctr_sub_cv(0,1,0,1,0,0, CGAL::COUNTERCLOCKWISE, + Conic_point_2(Algebraic(-25), Algebraic(-5)), + Conic_point_2(Algebraic(0), Algebraic(0))); - Conic_curve_2 c6(1,1,0,6,-26,162,CGAL::COUNTERCLOCKWISE, - Conic_point_2(Algebraic(-7), Algebraic(13)), - Conic_point_2(Algebraic(-3), Algebraic(9))); - Conic_curve_2 c7(1,0,0,0,-1,0,CGAL::COUNTERCLOCKWISE, - Conic_point_2(Algebraic(-3), Algebraic(9)), - Conic_point_2(Algebraic(0), Algebraic(0))); - Conic_curve_2 c8(0,1,0,-1,0,0, CGAL::COUNTERCLOCKWISE, - Conic_point_2(Algebraic(0), Algebraic(0)), - Conic_point_2(Algebraic(4), Algebraic(-2))); + Conic_curve_2 c6 = ctr_sub_cv(1,1,0,6,-26,162,CGAL::COUNTERCLOCKWISE, + Conic_point_2(Algebraic(-7), Algebraic(13)), + Conic_point_2(Algebraic(-3), Algebraic(9))); + Conic_curve_2 c7 = ctr_sub_cv(1,0,0,0,-1,0,CGAL::COUNTERCLOCKWISE, + Conic_point_2(Algebraic(-3), Algebraic(9)), + Conic_point_2(Algebraic(0), Algebraic(0))); + Conic_curve_2 c8 = ctr_sub_cv(0,1,0,-1,0,0, CGAL::COUNTERCLOCKWISE, + Conic_point_2(Algebraic(0), Algebraic(0)), + Conic_point_2(Algebraic(4), Algebraic(-2))); - Conic_curve_2 c9(1,0,0,0,-1,0,CGAL::COUNTERCLOCKWISE, - Conic_point_2(Algebraic(-5), Algebraic(25)), - Conic_point_2(Algebraic(5), Algebraic(25))); - Conic_curve_2 c10(58, 72, -48, 0, 0, -360); + Conic_curve_2 c9 = ctr_sub_cv(1,0,0,0,-1,0,CGAL::COUNTERCLOCKWISE, + Conic_point_2(Algebraic(-5), Algebraic(25)), + Conic_point_2(Algebraic(5), Algebraic(25))); + Conic_curve_2 c10 = ctr_sub_cv(58, 72, -48, 0, 0, -360); //This vector is used to store curves that will be used to create polycurve std::vector conic_curves; @@ -772,21 +748,21 @@ int main(int argc, char* argv[]) //construct poly-curve Polycurve_conic_traits_2::Curve_2 conic_polycurve = - construct_polycurve(conic_curves.begin(), conic_curves.end()); + ctr_cv(conic_curves.begin(), conic_curves.end()); - Conic_curve_2 c11(0,1,0,-1,0,0,CGAL::COUNTERCLOCKWISE, - Conic_point_2(Algebraic(25), Algebraic(-5)), - Conic_point_2(Algebraic(0), Algebraic(0))); - Conic_curve_2 c12(1,0,0,0,-1,0,CGAL::COUNTERCLOCKWISE, - Conic_point_2(Algebraic(0), Algebraic(0)), - Conic_point_2(Algebraic(5), Algebraic(25))); + Conic_curve_2 c11 = ctr_sub_cv(0,1,0,-1,0,0,CGAL::COUNTERCLOCKWISE, + Conic_point_2(Algebraic(25), Algebraic(-5)), + Conic_point_2(Algebraic(0), Algebraic(0))); + Conic_curve_2 c12 = ctr_sub_cv(1,0,0,0,-1,0,CGAL::COUNTERCLOCKWISE, + Conic_point_2(Algebraic(0), Algebraic(0)), + Conic_point_2(Algebraic(5), Algebraic(25))); conic_curves.clear(); conic_curves.push_back(c11); conic_curves.push_back(c12); //construct poly-curve Polycurve_conic_traits_2::Curve_2 conic_polycurve_2 = - construct_polycurve(conic_curves.begin(), conic_curves.end()); + ctr_cv(conic_curves.begin(), conic_curves.end()); /* VERY IMPORTANT * For efficiency reasons, we recommend users not to construct @@ -794,13 +770,12 @@ int main(int argc, char* argv[]) * functor supplied by the conic-arc traits class to convert conic curves * to x-monotone curves. */ - Conic_x_monotone_curve_2 xc3(c3); - Conic_x_monotone_curve_2 xc4(c4); - Conic_x_monotone_curve_2 xc5(c5); - Conic_x_monotone_curve_2 xc6(c6); - Conic_x_monotone_curve_2 xc7(c7); - Conic_x_monotone_curve_2 xc8(c8); - + Conic_x_monotone_curve_2 xc3 = ctr_sub_xcv(c3); + Conic_x_monotone_curve_2 xc4 = ctr_sub_xcv(c4); + Conic_x_monotone_curve_2 xc5 = ctr_sub_xcv(c5); + Conic_x_monotone_curve_2 xc6 = ctr_sub_xcv(c6); + Conic_x_monotone_curve_2 xc7 = ctr_sub_xcv(c7); + Conic_x_monotone_curve_2 xc8 = ctr_sub_xcv(c8); //This vector is used to store curves that will be used to create //X-monotone-polycurve @@ -809,11 +784,9 @@ int main(int argc, char* argv[]) xmono_conic_curves_2.push_back(xc3); xmono_conic_curves_2.push_back(xc4); - //construct x-monotone poly-curve Pc_x_monotone_curve_2 conic_x_mono_polycurve_1 = - construct_x_mono_polycurve(xmono_conic_curves_2.begin(), - xmono_conic_curves_2.end()); + ctr_xcv(xmono_conic_curves_2.begin(), xmono_conic_curves_2.end()); xmono_conic_curves_2.clear(); xmono_conic_curves_2.push_back(xc6); @@ -821,15 +794,13 @@ int main(int argc, char* argv[]) xmono_conic_curves_2.push_back(xc8); //construct x-monotone poly-curve Pc_x_monotone_curve_2 conic_x_mono_polycurve_2 = - construct_x_mono_polycurve(xmono_conic_curves_2.begin(), - xmono_conic_curves_2.end()); + ctr_xcv(xmono_conic_curves_2.begin(), xmono_conic_curves_2.end()); xmono_conic_curves_2.clear(); xmono_conic_curves_2.push_back(xc5); Pc_x_monotone_curve_2 x_polycurve_push = - construct_x_mono_polycurve(xmono_conic_curves_2.begin(), - xmono_conic_curves_2.end()); + ctr_xcv(xmono_conic_curves_2.begin(), xmono_conic_curves_2.end()); Polycurve_conic_traits_2::X_monotone_subcurve_2 xcurve_push = Polycurve_conic_traits_2::X_monotone_subcurve_2(c5); //traits.construct_x_monotone_curve_2_object()(c5); @@ -838,28 +809,27 @@ int main(int argc, char* argv[]) xmono_conic_curves_2.push_back(xc3); xmono_conic_curves_2.push_back(xc4); Pc_x_monotone_curve_2 base_curve = - construct_x_mono_polycurve(xmono_conic_curves_2.begin(), - xmono_conic_curves_2.end()); + ctr_xcv(xmono_conic_curves_2.begin(), xmono_conic_curves_2.end()); //curves for push_back - Conic_curve_2 c13(1,1,0,-50,12,660,CGAL::COUNTERCLOCKWISE, - Conic_point_2(Algebraic(25), Algebraic(-7)), - Conic_point_2(Algebraic(25), Algebraic(-5))); - Conic_curve_2 c14(0,1,0,-1,0,0,CGAL::COUNTERCLOCKWISE, - Conic_point_2(Algebraic(25), Algebraic(-5)), - Conic_point_2(Algebraic(0), Algebraic(0))); - Conic_curve_2 c15(-1,0,0,0,1,0,CGAL::COUNTERCLOCKWISE, - Conic_point_2(Algebraic(0), Algebraic(0)), - Conic_point_2(Algebraic(5), Algebraic(25))); + Conic_curve_2 c13 = ctr_sub_cv(1,1,0,-50,12,660,CGAL::COUNTERCLOCKWISE, + Conic_point_2(Algebraic(25), Algebraic(-7)), + Conic_point_2(Algebraic(25), Algebraic(-5))); + Conic_curve_2 c14 = ctr_sub_cv(0,1,0,-1,0,0,CGAL::COUNTERCLOCKWISE, + Conic_point_2(Algebraic(25), Algebraic(-5)), + Conic_point_2(Algebraic(0), Algebraic(0))); + Conic_curve_2 c15 = ctr_sub_cv(-1,0,0,0,1,0,CGAL::COUNTERCLOCKWISE, + Conic_point_2(Algebraic(0), Algebraic(0)), + Conic_point_2(Algebraic(5), Algebraic(25))); conic_curves.clear(); conic_curves.push_back(c13); conic_curves.push_back(c14); Polycurve_conic_traits_2::Curve_2 base_curve_push_back = - construct_polycurve(conic_curves.begin(), conic_curves.end()); + ctr_cv(conic_curves.begin(), conic_curves.end()); conic_curves.push_back(c15); Polycurve_conic_traits_2::Curve_2 Expected_push_back_result = - construct_polycurve(conic_curves.begin(), conic_curves.end()); + ctr_cv(conic_curves.begin(), conic_curves.end()); // //checking the orientattion consistency // Conic_curve_2 c21(0,1,0,1,0,0,CGAL::CLOCKWISE, @@ -874,7 +844,7 @@ int main(int argc, char* argv[]) // xmono_conic_curves_2.push_back(xc20); // xmono_conic_curves_2.push_back(xc21); // Pc_x_monotone_curve_2 eric_polycurve = - // construct_x_mono_polycurve(xmono_conic_curves_2.begin(), + // ctr_xcv(xmono_conic_curves_2.begin(), // xmono_conic_curves_2.end()); // std::cout << "the polycurve is: " << eric_polycurve << std::endl; diff --git a/Surface_sweep_2/test/Surface_sweep_2/test_sweep_conic.cpp b/Surface_sweep_2/test/Surface_sweep_2/test_sweep_conic.cpp index 45ae9544851..260dd8738cc 100644 --- a/Surface_sweep_2/test/Surface_sweep_2/test_sweep_conic.cpp +++ b/Surface_sweep_2/test/Surface_sweep_2/test_sweep_conic.cpp @@ -40,13 +40,14 @@ typedef std::list CurveList; typedef std::list PointList; typedef PointList::iterator PointListIter; - /*! Conic reader */ template class Conic_reader { +private: + Traits_2 m_traits; + public: - int ReadData(const char* filename, CurveList& curves, CGAL::Bbox_2& bbox) - { + int read_data(const char* filename, CurveList& curves, CGAL::Bbox_2& bbox) { Curve_2 cv; char dummy[256]; @@ -58,8 +59,8 @@ public: int count; inp >> count; inp.getline(dummy, sizeof(dummy)); - for (int i = 0; i < count; i++) { - ReadCurve(inp, cv); + for (int i = 0; i < count; ++i) { + read_curve(inp, cv); curves.push_back(cv); CGAL::Bbox_2 curve_bbox = cv.bbox(); if (i == 0) bbox = curve_bbox; @@ -69,50 +70,47 @@ public: return 0; } - void ReadCurve(std::ifstream & is, Curve_2 & cv) - { + void read_curve(std::ifstream& is, Curve_2& cv) { + auto ctr_cv = m_traits.construct_curve_2_object(); + // Read a line from the input file. char one_line[128]; - skip_comments (is, one_line); + skip_comments(is, one_line); std::string stringvalues(one_line); - std::istringstream str_line (stringvalues, std::istringstream::in); + std::istringstream str_line(stringvalues, std::istringstream::in); // Get the arc type. // Supported types are: 'f' - Full ellipse (or circle). // 'e' - Elliptic arc (or circular arc). // 's' - Line segment. - char type; - bool is_circle = false; // Is this a circle. + bool is_circle(false); // Is this a circle. Rat_circle_2 circle; - Rational r, s, t, u, v, w; // The conic coefficients. + Rational r, s, t, u, v, w; // The conic coefficients. + char type; str_line >> type; // An ellipse (full ellipse or a partial ellipse): - if (type == 'f' || type == 'F' || type == 'e' || type == 'E') - { + if (type == 'f' || type == 'F' || type == 'e' || type == 'E') { // Read the ellipse (using the format "a b x0 y0"): // // x - x0 2 y - y0 2 // ( -------- ) + ( -------- ) = 1 // a b // - int a, b, x0, y0; - + int a, b, x0, y0; str_line >> a >> b >> x0 >> y0; - Rational a_sq = Rational(a*a); - Rational b_sq = Rational(b*b); + Rational a_sq = Rational(a*a); + Rational b_sq = Rational(b*b); - if (a == b) - { + if (a == b) { is_circle = true; - circle = Rat_circle_2 (Rat_point_2 (Rational(x0), Rational(y0)), - Rational(a*b)); + circle = + Rat_circle_2(Rat_point_2(Rational(x0), Rational(y0)), Rational(a*b)); } - else - { + else { r = b_sq; s = a_sq; t = 0; @@ -121,54 +119,43 @@ public: w = Rational(x0*x0*b_sq + y0*y0*a_sq - a_sq*b_sq); } - if (type == 'f' || type == 'F') - { + if (type == 'f' || type == 'F') { // Create a full ellipse (or circle). - if (is_circle) - cv = Curve_2 (circle); - else - cv = Curve_2 (r, s, t, u, v, w); + cv = (is_circle) ? ctr_cv(circle) : ctr_cv(r, s, t, u, v, w); + return; } - else - { - // Read the endpointd of the arc. - int x1, y1, x2, y2; - str_line >> x1 >> y1 >> x2 >> y2; + // Read the endpointd of the arc. + int x1, y1, x2, y2; + str_line >> x1 >> y1 >> x2 >> y2; - Point_2 source = Point_2 (Algebraic(x1), Algebraic(y1)); - Point_2 target = Point_2 (Algebraic(x2), Algebraic(y2)); + Point_2 source = Point_2 (Algebraic(x1), Algebraic(y1)); + Point_2 target = Point_2 (Algebraic(x2), Algebraic(y2)); - // Create the arc. Note that it is always clockwise oriented. - if (is_circle) - cv = Curve_2 (circle, - CGAL::CLOCKWISE, - source, target); - else - cv = Curve_2 (r, s, t, u, v, w, - CGAL::CLOCKWISE, - source, target); - } + // Create the arc. Note that it is always clockwise oriented. + cv = (is_circle) ? + ctr_cv(circle, CGAL::CLOCKWISE, source, target) : + ctr_cv(r, s, t, u, v, w, CGAL::CLOCKWISE, source, target); + return; } - else if (type == 's' || type == 'S') - { - // Read a segment, given by its endpoints (x1,y1) and (x2,y2); - int x1, y1, x2, y2; + if (type == 's' || type == 'S') { + // Read a segment, given by its endpoints (x1,y1) and (x2,y2); + int x1, y1, x2, y2; str_line >> x1 >> y1 >> x2 >> y2; // Create the segment. - Rat_point_2 source = Rat_point_2 (Rational(x1), Rational(y1)); - Rat_point_2 target = Rat_point_2 (Rational(x2), Rational(y2)); + Rat_point_2 source = Rat_point_2(Rational(x1), Rational(y1)); + Rat_point_2 target = Rat_point_2(Rational(x2), Rational(y2)); - cv = Curve_2(Rat_segment_2 (source, target)); + cv = ctr_cv(Rat_segment_2(source, target)); + return; } - return; + std::cerr << "Invalid type (" << type << ")" << std::endl; } - void skip_comments( std::ifstream& is, char* one_line ) - { + void skip_comments( std::ifstream& is, char* one_line) { while( !is.eof() ){ is.getline( one_line, 128 ); if( one_line[0] != '#' ){ @@ -181,13 +168,11 @@ public: //--------------------------------------------------------------------------- // The main: // -int main (int argc, char** argv) -{ +int main(int argc, char* argv[]) { bool verbose = false; // Define a test objects to read the conic arcs from it. - if (argc<2) - { + if (argc<2) { std::cerr << "Usage: Conic_traits_test " << std::endl; exit(1); } @@ -196,27 +181,25 @@ int main (int argc, char** argv) CurveList curves; Conic_reader reader; - reader.ReadData(argv[1], curves, bbox); + reader.read_data(argv[1], curves, bbox); // run the sweep std::list mylist; CGAL::compute_subcurves(curves.begin(), curves.end(), - std::back_inserter(mylist), false); + std::back_inserter(mylist), false); PointList point_list_with_ends; CGAL::compute_intersection_points(curves.begin(), curves.end(), - std::back_inserter(point_list_with_ends), true); + std::back_inserter(point_list_with_ends), + true); std::size_t point_count_with_ends_calculated = point_list_with_ends.size(); // generate the string for the output std::stringstream out1; - for ( std::list::iterator iter = mylist.begin() ; - iter != mylist.end() ; ++iter ) - { + for (auto iter = mylist.begin(); iter != mylist.end(); ++iter) out1 << *iter << "\n"; - } // read the output from the file std::stringstream out2; @@ -226,12 +209,10 @@ int main (int argc, char** argv) std::ifstream in_file(argv[1]); in_file >> count; in_file.getline(buf, 1024); // to get rid of the new line - for ( int i = 0 ; i < count ; i++ ) { - in_file.getline(buf, 1024); - } + for (int i = 0 ; i < count ; ++i) in_file.getline(buf, 1024); in_file >> count; in_file.getline(buf, 1024); // to get rid of the new line - for (int i = 0; i < count; i++) { + for (int i = 0; i < count; ++i) { in_file.getline(buf, 1024); out2 << buf << "\n"; } @@ -239,31 +220,28 @@ int main (int argc, char** argv) in_file >> point_count_with_ends_from_file; in_file.close(); - if ( verbose ) - { + if (verbose) { std::cout << "Result: \n" << mylist.size() << "\n"; - for ( std::list::iterator i = mylist.begin() ; - i != mylist.end() ; ++i ) - { + for (auto i = mylist.begin(); i != mylist.end() ; ++i) std::cout << *i << "\n"; - } } std::string calculated = out1.str(); std::string infile = out2.str(); - if ( infile == calculated ) { - if ( point_count_with_ends_from_file != - point_count_with_ends_calculated ) { + if (infile == calculated) { + if (point_count_with_ends_from_file != point_count_with_ends_calculated) { std::cout << "number of intersection points (with ends):" << point_count_with_ends_calculated << ". Should be " << point_count_with_ends_from_file << "\n"; std::cout << argv[1] << " Error\n"; return -1; - } else { + } + else { std::cout << argv[1] << " OK!\n"; } - } else { + } + else { std::cout << argv[1] << " Error\n"; std::cout << "\ncalculated:\n"; std::cout << calculated << std::endl; From 9c89ddb71e89aba65e7cc0431b0e526d3b0a41d0 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Tue, 31 May 2022 19:36:40 +0300 Subject: [PATCH 025/105] Continued --- .../include/CGAL/Arr_conic_traits_2.h | 746 +++++++++++++---- .../CGAL/Arr_geometry_traits/Conic_arc_2.h | 539 +------------ .../Conic_x_monotone_arc_2.h | 749 +++--------------- 3 files changed, 715 insertions(+), 1319 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index 54a3db3fe01..e794c25c97f 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -64,6 +64,7 @@ public: typedef typename Rat_kernel::Circle_2 Rat_circle_2; typedef typename Alg_kernel::FT Algebraic; + typedef typename Alg_kernel::Point_2 Alg_point_2; typedef typename Nt_traits::Integer Integer; @@ -88,19 +89,35 @@ public: private: // Type definition for the intersection points mapping. - typedef typename X_monotone_curve_2::Conic_id Conic_id; - typedef typename X_monotone_curve_2::Intersection_point Intersection_point; - typedef typename X_monotone_curve_2::Intersection_map Intersection_map; + typedef typename Point_2::Conic_id Conic_id; + typedef std::pair Conic_pair; - typedef std::shared_ptr Shared_rat_kernel; - typedef std::shared_ptr Shared_alg_kernel; - typedef std::shared_ptr Shared_nt_Traits; + /*! \struct Less functor for Conic_pair. + */ + struct Less_conic_pair { + bool operator()(const Conic_pair& cp1, const Conic_pair& cp2) const { + // Compare the pairs of IDs lexicographically. + return ((cp1.first < cp2.first) || + ((cp1.first == cp2.first) && (cp1.second < cp2.second))); + } + }; + + typedef std::pair Intersection_point; + typedef std::list Intersection_list; + typedef std::map + Intersection_map; + typedef typename Intersection_map::iterator Intersection_map_iterator; + + + typedef std::shared_ptr Shared_rat_kernel; + typedef std::shared_ptr Shared_alg_kernel; + typedef std::shared_ptr Shared_nt_Traits; const Shared_rat_kernel m_rat_kernel; const Shared_alg_kernel m_alg_kernel; const Shared_nt_Traits m_nt_traits; - mutable Intersection_map inter_map; // Mapping conic pairs to their + mutable Intersection_map m_inter_map; // Mapping conic pairs to their // intersection points. public: @@ -253,36 +270,35 @@ public: * LARGER if y(p) > cv(x(p)), i.e. the point is above the curve; * EQUAL if p lies on the curve. */ - Comparison_result operator()(const Point_2& p, - const X_monotone_curve_2& cv) const - { + Comparison_result operator()(const Point_2& p, const X_monotone_curve_2& xcv) + const { auto cmp_y = m_traits.m_alg_kernel->compare_y_2_object(); - if (cv.is_vertical()) { + if (xcv.is_vertical()) { // A special treatment for vertical segments: // In case p has the same x c-ordinate of the vertical segment, compare // it to the segment endpoints to determine its position. - Comparison_result res1 = cmp_y(p, cv.left()); - Comparison_result res2 = cmp_y(p, cv.right()); + Comparison_result res1 = cmp_y(p, xcv.left()); + Comparison_result res2 = cmp_y(p, xcv.right()); return (res1 == res2) ? res1 : EQUAL; } // Check whether the point is exactly on the curve. - if (cv.contains_point(p)) return EQUAL; + if (m_traits.contains_point(xcv, p)) return EQUAL; // Obtain a point q on the x-monotone arc with the same x coordinate as p. Point_2 q; auto cmp_x = m_traits.m_alg_kernel->compare_x_2_object(); - Comparison_result x_res_left = cmp_x(p, cv.left()); - if (x_res_left == EQUAL) q = cv.left(); + Comparison_result x_res_left = cmp_x(p, xcv.left()); + if (x_res_left == EQUAL) q = xcv.left(); else { CGAL_precondition(x_res_left != SMALLER); - auto x_res_right = cmp_x(p, cv.right()); - if (x_res_right == EQUAL) q = cv.right(); + auto x_res_right = cmp_x(p, xcv.right()); + if (x_res_right == EQUAL) q = xcv.right(); else { CGAL_precondition(x_res_right != LARGER); - q = point_at_x(cv, p); + q = point_at_x(xcv, p); } } @@ -299,9 +315,10 @@ public: */ Point_2 point_at_x(const X_monotone_curve_2& xcv, const Point_2& p) const { // Make sure that p is in the x-range of the arc. - CGAL_precondition(! xcv.test_flag(X_monotone_curve_2::IS_VERTICAL_SEGMENT)); + CGAL_precondition(! xcv.is_vertical()); - CGAL_precondition_code(auto cmp_x = m_traits.m_alg_kernel->compare_x_2_object()); + CGAL_precondition_code(auto cmp_x = + m_traits.m_alg_kernel->compare_x_2_object()); CGAL_precondition((cmp_x(p, xcv.left()) != SMALLER) && (cmp_x(p, xcv.right()) != LARGER)); @@ -320,7 +337,7 @@ public: // conic curve. Algebraic y; - if (xcv.degree_mask() == xcv.flag_mask(X_monotone_curve_2::DEGREE_1)) { + if (xcv.degree_mask() == X_monotone_curve_2::degree_1_mask()) { // In case of a linear curve, the y-coordinate is a simple linear // expression of x(p) (note that v is not 0 as the arc is not vertical): // y = -(u*x(p) + w) / v @@ -335,7 +352,7 @@ public: y = -(extra_data->a * p.x() + extra_data->c) / extra_data->b; } else { - CGAL_assertion(xcv.degree_mask() == xcv.flag_mask(X_monotone_curve_2::DEGREE_2)); + CGAL_assertion(xcv.degree_mask() == X_monotone_curve_2::degree_2_mask()); // In this case the y-coordinate is one of solutions to the quadratic // equation: @@ -406,18 +423,15 @@ public: { // Make sure that p lies on both curves, and that both are defined to its // left (so their left endpoint is lexicographically smaller than p). - CGAL_precondition(xcv1.contains_point(p) && - xcv2.contains_point(p)); + CGAL_precondition(m_traits.contains_point(xcv1, p) && + m_traits.contains_point(xcv2, p)); CGAL_precondition_code(const auto ker = m_traits.m_alg_kernel); CGAL_precondition(ker->compare_xy_2_object()(p, xcv1.left()) == LARGER && ker->compare_xy_2_object()(p, xcv2.left()) == LARGER); // If one of the curves is vertical, it is below the other one. - if (xcv1.is_vertical()) { - // Check whether both are vertical: - return (xcv2.is_vertical()) ? EQUAL : SMALLER; - } + if (xcv1.is_vertical()) return (xcv2.is_vertical()) ? EQUAL : SMALLER; else if (xcv2.is_vertical()) return LARGER; // Compare the two curves immediately to the left of p: @@ -433,11 +447,8 @@ public: */ Comparison_result compare_to_left(const X_monotone_curve_2& xcv1, const X_monotone_curve_2& xcv2, - const Point_2& p) - const - { - CGAL_precondition(! xcv1.test_flag(X_monotone_curve_2::IS_VERTICAL_SEGMENT) && - ! xcv2.test_flag(X_monotone_curve_2::IS_VERTICAL_SEGMENT)); + const Point_2& p) const { + CGAL_precondition(! xcv1.is_vertical() && ! xcv2.is_vertical()); // In case one arc is facing upwards and another facing downwards, it is // clear that the one facing upward is above the one facing downwards. @@ -587,16 +598,15 @@ public: { // Make sure that p lies on both curves, and that both are defined to its // left (so their left endpoint is lexicographically smaller than p). - CGAL_precondition(xcv1.contains_point(p) && xcv2.contains_point(p)); + CGAL_precondition(m_traits.contains_point(xcv1, p) && + m_traits.contains_point(xcv2, p)); CGAL_precondition_code(const auto ker = m_traits.m_alg_kernel); CGAL_precondition_code(auto cmp_xy = ker->compare_xy_2_object()); CGAL_precondition(cmp_xy(p, xcv1.right()) == SMALLER && cmp_xy(p, xcv2.right()) == SMALLER); // If one of the curves is vertical, it is above the other one. - if (xcv1.is_vertical()) - // Check whether both are vertical: - return (xcv2.is_vertical()) ? EQUAL : LARGER; + if (xcv1.is_vertical()) return (xcv2.is_vertical()) ? EQUAL : LARGER; else if (xcv2.is_vertical()) return SMALLER; // Compare the two curves immediately to the right of p: @@ -613,8 +623,7 @@ public: Comparison_result compare_to_right(const X_monotone_curve_2& xcv1, const X_monotone_curve_2& xcv2, const Point_2& p) const { - CGAL_precondition(! xcv1.test_flag(X_monotone_curve_2::IS_VERTICAL_SEGMENT) && - ! xcv2.test_flag(X_monotone_curve_2::IS_VERTICAL_SEGMENT)); + CGAL_precondition(! xcv1.is_vertical() && ! xcv2.is_vertical()); // In case one arc is facing upwards and another facing downwards, it is // clear that the one facing upward is above the one facing downwards. @@ -752,7 +761,7 @@ public: const X_monotone_curve_2& xcv2) const { if (&xcv1 == &xcv2) return true; - return xcv1.equals(xcv2); + return equals(xcv1, xcv2); } /*! Check whether the two points are the same. @@ -764,6 +773,38 @@ public: if (&p1 == &p2) return (true); return(m_traits.m_alg_kernel->compare_xy_2_object()(p1, p2) == EQUAL); } + + private: + /*! Check whether the two arcs are equal (have the same graph). + * \param arc The compared arc. + * \return (true) if the two arcs have the same graph; (false) otherwise. + */ + bool equals(const X_monotone_curve_2& xcv1, + const X_monotone_curve_2& xcv2) const { + // The two arc must have the same supporting conic curves. + if (! m_traits.has_same_supporting_conic(xcv1, xcv2)) return false; + + auto eq = m_traits.m_alg_kernel->equal_2_object(); + + // Check that the arc endpoints are the same. + if (xcv1.orientation() == COLLINEAR) { + CGAL_assertion(xcv2.orientation() == COLLINEAR); + return((eq(xcv1.source(), xcv2.source()) && + eq(xcv1.target(), xcv2.target())) || + (eq(xcv1.source(), xcv2.target()) && + eq(xcv1.target(), xcv2.source()))); + } + + if (xcv1.orientation() == xcv2.m_orient) { + // Same orientation - the source and target points must be the same. + return (eq(xcv1.source(), xcv2.source()) && + eq(xcv1.target(), xcv2.target())); + } + + // Reverse orientation - the source and target points must be swapped. + return (eq(xcv1.source(), xcv2.target()) && + eq(xcv1.target(), xcv2.source())); + } }; /*! Obtain an Equal_2 functor object. */ @@ -812,8 +853,8 @@ public: Conic_id conic_id(index); // Find the points of vertical tangency to cv and act accordingly. - typename Curve_2::Point_2 vtan_ps[2]; - auto n_vtan_ps = cv.vertical_tangency_points(vtan_ps); + Alg_point_2 vtan_ps[2]; + auto n_vtan_ps = m_traits.vertical_tangency_points(cv, vtan_ps); if (n_vtan_ps == 0) { // In case the given curve is already x-monotone: *oi++ = Make_x_monotone_result(ctr_xcv(cv, conic_id)); @@ -828,19 +869,19 @@ public: // In case the curve is a full conic, split it into two x-monotone // arcs, one going from ps[0] to ps[1], and the other from ps[1] to // ps[0]. - *oi++ = Make_x_monotone_result(ctr_xcv(cv, vtan_ps[0], - vtan_ps[1], conic_id)); - *oi++ = Make_x_monotone_result(ctr_xcv(cv, vtan_ps[1], - vtan_ps[0], conic_id)); + *oi++ = Make_x_monotone_result(ctr_xcv(cv, vtan_ps[0], vtan_ps[1], + conic_id)); + *oi++ = Make_x_monotone_result(ctr_xcv(cv, vtan_ps[1], vtan_ps[0], + conic_id)); } else { if (n_vtan_ps == 1) { // Split the arc into two x-monotone sub-curves: one going from the // arc source to ps[0], and the other from ps[0] to the target. - *oi++ = Make_x_monotone_result(ctr_xcv(cv, cv.source(), - vtan_ps[0], conic_id)); - *oi++ = Make_x_monotone_result(ctr_xcv(cv, vtan_ps[0], - cv.target(), conic_id)); + *oi++ = Make_x_monotone_result(ctr_xcv(cv, cv.source(), vtan_ps[0], + conic_id)); + *oi++ = Make_x_monotone_result(ctr_xcv(cv, vtan_ps[0], cv.target(), + conic_id)); } else { CGAL_assertion(n_vtan_ps == 2); @@ -928,7 +969,7 @@ public: X_monotone_curve_2& xcv1, X_monotone_curve_2& xcv2) const { // Make sure that p lies on the interior of the arc. CGAL_precondition_code(auto eq = m_traits.m_alg_kernel->equal_2_object()); - CGAL_precondition(xcv.contains_point(p) && + CGAL_precondition(m_traits.contains_point(xcv, p) && ! eq(p, xcv.source()) && ! eq(p, xcv.target())); // Make copies of the current arc. @@ -966,13 +1007,25 @@ public: Split_2 split_2_object() const { return Split_2(*this); } class Intersect_2 { - private: + protected: + using Traits = Arr_conic_traits_2; + Intersection_map& m_inter_map; // The map of intersection points. - public: - /*! Constructor. */ - Intersect_2(Intersection_map& map) : m_inter_map(map) {} + /*! The traits (in case it has state) */ + const Traits& m_traits; + /*! Constructor. + * \param traits the traits. + */ + Intersect_2(Intersection_map& map, const Traits& traits) : + m_inter_map(map), + m_traits(traits) + {} + + friend class Arr_conic_traits_2; + + public: /*! Find the intersections of the two given curves and insert them to the * given output iterator. As two segments may itersect only once, only a * single will be contained in the iterator. @@ -982,14 +1035,351 @@ public: * \return The past-the-end iterator. */ template - OutputIterator operator()(const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2, + OutputIterator operator()(const X_monotone_curve_2& xcv1, + const X_monotone_curve_2& xcv2, OutputIterator oi) const - { return cv1.intersect(cv2, m_inter_map, oi); } + { return intersect(xcv1, xcv2, m_inter_map, oi); } + + private: + /*! Compute the overlap with a given arc, which is supposed to have the same + * supporting conic curve as this arc. + * \param arc The given arc. + * \param overlap Output: The overlapping arc (if any). + * \return Whether we found an overlap. + */ + bool compute_overlap(const X_monotone_curve_2& xcv1, + const X_monotone_curve_2& xcv2, + X_monotone_curve_2& overlap) const { + // Check if the two arcs are identical. + if (m_traits.equal_2_object()(xcv1,xcv2)) { + overlap = xcv2; + return true; + } + + if (m_traits.is_strictly_between_endpoints(xcv1, xcv2.left())) { + if (m_traits.is_strictly_between_endpoints(xcv1, xcv2.right())) { + // Case 1 - *this: +-----------> + // arc: +=====> + overlap = xcv2; + return true; + } + else { + // Case 2 - *this: +-----------> + // arc: +=====> + overlap = xcv1; + + if (overlap.is_directed_right()) overlap.m_source = xcv2.left(); + else overlap.m_target = xcv2.left(); + + return true; + } + } + else if (m_traits.is_strictly_between_endpoints(xcv1, xcv2.right())) { + // Case 3 - *this: +-----------> + // arc: +=====> + overlap = xcv1; + if (overlap.is_directed_right()) overlap.m_target = xcv2.right(); + else overlap.m_source = xcv2.right(); + return true; + } + else if (m_traits.is_between_endpoints(xcv2, xcv1.source()) && + m_traits.is_between_endpoints(xcv2, xcv1.target()) && + (m_traits.is_strictly_between_endpoints(xcv2, xcv1.source()) || + m_traits.is_strictly_between_endpoints(xcv2, xcv1.target()))) + { + // Case 4 - *this: +-----------> + // arc: +================> + overlap = xcv1; + return true; + } + + // If we reached here, there are no overlaps: + return false; + } + + /*! Intersect the supporing conic curves of this arc and the given arc. + * \param arc The arc to intersect with. + * \param inter_list The list of intersection points. + */ + void intersect_supporting_conics(const X_monotone_curve_2& xcv1, + const X_monotone_curve_2& xcv2, + Intersection_list& inter_list) const { + if (xcv1.is_special_segment() && ! xcv2.is_special_segment()) { + // If one of the arcs is a special segment, make sure it is (arc). + intersect_supporting_conics(xcv2, xcv1, inter_list); + return; + } + + const int deg1 = (xcv1.degree_mask() == X_monotone_curve_2::degree_1_mask()) ? 1 : 2; + const int deg2 = (xcv2.degree_mask() == X_monotone_curve_2::degree_1_mask()) ? 1 : 2; + Nt_traits nt_traits; + Algebraic xs[4]; + int n_xs = 0; + Algebraic ys[4]; + int n_ys = 0; + + if (xcv2.is_special_segment()) { + // The second arc is a special segment (a*x + b*y + c = 0). + if (xcv1.is_special_segment()) { + // Both arc are sepcial segment, so they have at most one intersection + // point. + const auto* extra_data1 = xcv1.extra_data(); + const auto* extra_data2 = xcv2.extra_data(); + Algebraic denom = + extra_data1->a * extra_data2->b - extra_data1->b * extra_data2->a; + + if (CGAL::sign (denom) != CGAL::ZERO) { + xs[0] = (extra_data1->b * extra_data2->c - + extra_data1->c * extra_data2->b) / denom; + n_xs = 1; + + ys[0] = (extra_data1->c * extra_data2->a - + extra_data1->a * extra_data2->c) / denom; + n_ys = 1; + } + } + else { + const auto* extra_data2 = xcv2.extra_data(); + + // Compute the x-coordinates of the intersection points. + n_xs = compute_resultant_roots(nt_traits, + xcv1.alg_r(), xcv1.alg_s(), + xcv1.alg_t(), xcv1.alg_u(), + xcv1.alg_v(), xcv1.alg_w(), + deg1, + extra_data2->a, + extra_data2->b, + extra_data2->c, + xs); + CGAL_assertion(n_xs <= 2); + + // Compute the y-coordinates of the intersection points. + n_ys = compute_resultant_roots(nt_traits, + xcv1.alg_s(), xcv1.alg_r(), + xcv1.alg_t(), xcv1.alg_v(), + xcv1.alg_u(), xcv1.alg_w(), + deg1, + extra_data2->b, + extra_data2->a, + extra_data2->c, + ys); + CGAL_assertion(n_ys <= 2); + } + } + else { + // Compute the x-coordinates of the intersection points. + n_xs = compute_resultant_roots(nt_traits, + xcv1.r(), xcv1.s(), xcv1.t(), + xcv1.u(), xcv1.v(), xcv1.w(), + deg1, + xcv2.r(), xcv2.s(), xcv2.t(), + xcv2.u(), xcv2.v(), xcv2.w(), + deg2, + xs); + CGAL_assertion(n_xs <= 4); + + // Compute the y-coordinates of the intersection points. + n_ys = compute_resultant_roots(nt_traits, + xcv1.s(), xcv1.r(), xcv1.t(), + xcv1.v(), xcv1.u(), xcv1.w(), + deg1, + xcv2.s(), xcv2.r(), xcv2.t(), + xcv2.v(), xcv2.u(), xcv2.w(), + deg2, + ys); + CGAL_assertion(n_ys <= 4); + } + + // Pair the coordinates of the intersection points. As the vectors of + // x and y-coordinates are sorted in ascending order, we output the + // intersection points in lexicographically ascending order. + unsigned int mult; + int i, j; + + if (xcv2.is_special_segment()) { + if ((n_xs == 0) || (n_ys == 0)) return; + + if ((n_xs == 1) && (n_ys == 1)) { + // Single intersection. + Point_2 ip(xs[0], ys[0]); + ip.set_generating_conic(xcv1.id()); + ip.set_generating_conic(xcv2.id()); + + // In case the other curve is of degree 2, this is a tangency point. + mult = ((deg1 == 1) || xcv1.is_special_segment()) ? 1 : 2; + inter_list.push_back(Intersection_point(ip, mult)); + } + else if ((n_xs == 1) && (n_ys == 2)) { + Point_2 ip1(xs[0], ys[0]); + ip1.set_generating_conic(xcv1.id()); + ip1.set_generating_conic(xcv2.id()); + + inter_list.push_back(Intersection_point(ip1, 1)); + + Point_2 ip2(xs[0], ys[1]); + ip2.set_generating_conic(xcv1.id()); + ip2.set_generating_conic(xcv2.id()); + + inter_list.push_back(Intersection_point(ip2, 1)); + } + else if ((n_xs == 2) && (n_ys == 1)) { + Point_2 ip1(xs[0], ys[0]); + ip1.set_generating_conic(xcv1.id()); + ip1.set_generating_conic(xcv2.id()); + + inter_list.push_back(Intersection_point(ip1, 1)); + + Point_2 ip2(xs[1], ys[0]); + ip2.set_generating_conic(xcv1.id()); + ip2.set_generating_conic(xcv2.id()); + + inter_list.push_back(Intersection_point(ip2, 1)); + } + else { + CGAL_assertion((n_xs == 2) && (n_ys == 2)); + + // The x-coordinates and the y-coordinates are given in ascending + // order. If the slope of the segment is positive, we pair the + // coordinates as is - otherwise, we swap the pairs. + int ind_first_y(0), ind_second_y(1); + + const auto* extra_data2 = xcv2.extra_data(); + if (CGAL::sign(extra_data2->b) == CGAL::sign(extra_data2->a)) { + ind_first_y = 1; + ind_second_y = 0; + } + + Point_2 ip1(xs[0], ys[ind_first_y]); + ip1.set_generating_conic(xcv1.id()); + ip1.set_generating_conic(xcv2.id()); + + inter_list.push_back(Intersection_point(ip1, 1)); + + Point_2 ip2(xs[1], ys[ind_second_y]); + ip2.set_generating_conic(xcv1.id()); + ip2.set_generating_conic(xcv2.id()); + + inter_list.push_back(Intersection_point(ip2, 1)); + } + + return; + } + + for (i = 0; i < n_xs; ++i) { + for (j = 0; j < n_ys; ++j) { + if (xcv1.is_on_supporting_conic(xs[i], ys[j]) && + xcv2.is_on_supporting_conic(xs[i], ys[j])) + { + // Create the intersection point and set its generating conics. + Point_2 ip(xs[i], ys[j]); + + ip.set_generating_conic(xcv1.id()); + ip.set_generating_conic(xcv2.id()); + + // Compute the multiplicity of the intersection point. + if (deg1 == 1 && deg2 == 1) mult = 1; + else mult = xcv1.multiplicity_of_intersection_point(xcv2, ip); + + // Insert the intersection point to the output list. + inter_list.push_back(Intersection_point(ip, mult)); + } + } + } + } + + /*! Compute the intersections with the given arc. + * \param arc The given intersecting arc. + * \param inter_map Maps conic pairs to lists of their intersection points. + * \param oi The output iterator. + * \return The past-the-end iterator. + */ + template + OutputIterator intersect(const X_monotone_curve_2& xcv1, + const X_monotone_curve_2& xcv2, + Intersection_map& inter_map, + OutputIterator oi) const { + typedef boost::variant + Intersection_result; + + if (m_traits.has_same_supporting_conic(xcv1, xcv2)) { + // Check for overlaps between the two arcs. + X_monotone_curve_2 overlap; + + if (compute_overlap(xcv1, xcv2, overlap)) { + // There can be just a single overlap between two x-monotone arcs: + *oi++ = Intersection_result(overlap); + return oi; + } + + // In case there is not overlap and the supporting conics are the same, + // there cannot be any intersection points, unless the two arcs share + // an end point. + // Note that in this case we do not define the multiplicity of the + // intersection points we report. + auto alg_kernel = m_traits.m_alg_kernel; + auto eq = alg_kernel->equal_2_object(); + if (eq(xcv1.left(), xcv2.left())) { + Intersection_point ip(xcv1.left(), 0); + *oi++ = Intersection_result(ip); + } + + if (eq(xcv1.right(), xcv2.right())) { + Intersection_point ip(xcv1.right(), 0); + *oi++ = Intersection_result(ip); + } + + return oi; + } + + // Search for the pair of supporting conics in the map (the first conic + // ID in the pair should be smaller than the second one, to guarantee + // uniqueness). + Conic_pair conic_pair; + Intersection_map_iterator map_iter; + Intersection_list inter_list; + bool invalid_ids = false; + + if (xcv1.id().is_valid() && xcv2.id().is_valid()) { + if (xcv1.id() < xcv2.id()) conic_pair = Conic_pair(xcv1.id(), xcv2.id()); + else conic_pair = Conic_pair(xcv2.id(), xcv1.id()); + map_iter = inter_map.find(conic_pair); + } + else { + // In case one of the IDs is invalid, we do not look in the map neither + // we cache the results. + map_iter = inter_map.end(); + invalid_ids = true; + } + + if (map_iter == inter_map.end()) { + // In case the intersection points between the supporting conics have + // not been computed before, compute them now and store them in the map. + intersect_supporting_conics(xcv1, xcv2, inter_list); + + if (! invalid_ids) inter_map[conic_pair] = inter_list; + } + else { + // Obtain the precomputed intersection points from the map. + inter_list = (*map_iter).second; + } + + // Go over the list of intersection points and report those that lie on + // both x-monotone arcs. + for (auto iter = inter_list.begin(); iter != inter_list.end(); ++iter) { + if (m_traits.is_between_endpoints(xcv1, (*iter).first) && + m_traits.is_between_endpoints(xcv2, (*iter).first)) + { + *oi++ = Intersection_result(*iter); + } + } + + return oi; + } }; /*! Obtain an Intersect_2 functor object. */ - Intersect_2 intersect_2_object() const { return (Intersect_2(inter_map)); } + Intersect_2 intersect_2_object() const + { return Intersect_2(m_inter_map, *this); } class Are_mergeable_2 { protected: @@ -1432,8 +1822,8 @@ public: * \pre cv is x-monotone. */ X_monotone_curve_2 operator()(const Curve_2& cv) const { + CGAL_precondition(cv.is_valid() && is_x_monotone(cv)); X_monotone_curve_2 xcv(cv); - CGAL_precondition(xcv.is_valid() && xcv.is_x_monotone()); m_traits.set_x_monotone(xcv); return xcv; } @@ -1442,8 +1832,7 @@ public: * \param xcv The given (Curve_2) curve. * \param id The ID of the base curve. */ - X_monotone_curve_2 operator()(const Curve_2& cv, const Conic_id& id) const - { + X_monotone_curve_2 operator()(const Curve_2& cv, const Conic_id& id) const { X_monotone_curve_2 xcv(cv, id); CGAL_precondition(xcv.is_valid() && id.is_valid()); m_traits.set_x_monotone(xcv); @@ -1554,6 +1943,26 @@ public: xcv.set_flag(X_monotone_curve_2::IS_SPECIAL_SEGMENT); return xcv; } + + private: + /*! Determine whether the arc is x-monotone. + */ + bool is_x_monotone(const Curve_2& cv) const { + // Collect vertical tangency points. + Alg_point_2 vtan_ps[2]; + auto res = m_traits.vertical_tangency_points(cv, vtan_ps); + return (res == 0); + } + + /*! Determine whether the arc is y-monotone. + */ + bool is_y_monotone(const Curve_2& cv) const { + // Collect horizontal tangency points. + Alg_point_2 htan_ps[2]; + auto res = m_traits.horizontal_tangency_points(cv, htan_ps); + return (res == 0); + } + }; /*! Obtain a Construct_x_monotone_curve_2 functor object. */ @@ -1723,8 +2132,7 @@ public: Curve_2 arc; // Make sure that no three points are collinear. - Rat_kernel ker; - auto orient_f = m_rat_kernel.orientation_2_object(); + auto orient_f = m_traits.m_rat_kernel->orientation_2_object(); const bool point_collinear = (orient_f(p1, p2, p3) == COLLINEAR || orient_f(p1, p2, p4) == COLLINEAR || @@ -1795,9 +2203,9 @@ public: Point_2 mp4 = Point_2(nt_traits->convert(p4.x()), nt_traits->convert(p4.y())); - if (! is_strictly_between_endpoints(arc, mp2) || - ! is_strictly_between_endpoints(arc, mp3) || - ! is_strictly_between_endpoints(arc, mp4)) + if (! m_traits.is_strictly_between_endpoints(arc, mp2) || + ! m_traits.is_strictly_between_endpoints(arc, mp3) || + ! m_traits.is_strictly_between_endpoints(arc, mp4)) { arc.reset_flags(); // inavlid arc return arc; @@ -2101,8 +2509,8 @@ public: Curve_2 operator()(const Rat_circle_2& circ, const Orientation& orient, const Point_2& source, const Point_2& target) const { // Make sure that the source and the taget are not the same. - CGAL_precondition(Alg_kernel().compare_xy_2_object()(source, target) != - EQUAL); + CGAL_precondition_code(auto cmp_xy = m_traits.m_alg_kernel->compare_xy_2_object()); + CGAL_precondition(cmp_xy(source, target) != EQUAL); CGAL_precondition(orient != COLLINEAR); Curve_2 arc; @@ -2150,9 +2558,8 @@ public: // Set the arc properties (no need to compute the orientation). m_traits.set(arc, rat_coeffs); - return arc; - } + } }; /*! Obtain a Construct_curve_2 functor object. */ @@ -2222,8 +2629,7 @@ public: * \pre both points must be interior and must lie on \c cv */ X_monotone_curve_2 operator()(const X_monotone_curve_2& xcv, - const Point_2& src, - const Point_2& tgt)const + const Point_2& src, const Point_2& tgt) const { // make functor objects CGAL_precondition_code(Compare_y_at_x_2 compare_y_at_x_2 = @@ -2255,7 +2661,8 @@ public: const Point_2& ps, const Point_2& pt) const { // Make sure that both ps and pt lie on the arc. - CGAL_precondition(xcv.contains_point(ps) && xcv.contains_point(pt)); + CGAL_precondition(m_traits.contains_point(xcv, ps) && + m_traits.contains_point(xcv, pt)); // Make sure that the endpoints conform with the direction of the arc. X_monotone_curve_2 res_xcv = xcv; @@ -2498,13 +2905,13 @@ public: * \return true if the point is between the two endpoints, * (false) if it is not. */ - bool is_between_endpoints(const Curve_2& arc, const Point_2& p) const { - CGAL_precondition(! arc.is_full_conic()); + bool is_between_endpoints(const Curve_2& cv, const Point_2& p) const { + CGAL_precondition(! cv.is_full_conic()); // Check if p is one of the endpoints. auto eq = m_alg_kernel->equal_2_object(); - if (eq(p, arc.source()) || eq(p, arc.target())) return true; - else return (is_strictly_between_endpoints(arc, p)); + if (eq(p, cv.source()) || eq(p, cv.target())) return true; + else return is_strictly_between_endpoints(cv, p); } /*! Check whether the given point is strictly between the source and the @@ -2514,33 +2921,33 @@ public: * \return true if the point is strictly between the two endpoints, * (false) if it is not. */ - bool is_strictly_between_endpoints(const Curve_2& arc, const Point_2& p) const + bool is_strictly_between_endpoints(const Curve_2& cv, const Point_2& p) const { // In case this is a full conic, any point on its boundary is between // its end points. - if (arc.is_full_conic()) return true; + if (cv.is_full_conic()) return true; // Check if we have extra data available. - const auto* extra_data = arc.extra_data(); + const auto* extra_data = cv.extra_data(); if (extra_data != nullptr) { if (extra_data->side != ZERO) { // In case of a hyperbolic arc, make sure the point is located on the // same branch as the arc. - if (arc.sign_of_extra_data(p.x(), p.y()) != extra_data->side) + if (cv.sign_of_extra_data(p.x(), p.y()) != extra_data->side) return false; } else { // In case we have a segment of a line pair, make sure that p really // satisfies the equation of the line. - if (arc.sign_of_extra_data(p.x(), p.y()) != ZERO) return false; + if (cv.sign_of_extra_data(p.x(), p.y()) != ZERO) return false; } } // Act according to the conic degree. auto orient_f = m_alg_kernel->orientation_2_object(); - const auto& source = arc.source(); - const auto& target = arc.target(); - if (arc.orientation() == COLLINEAR) { + const auto& source = cv.source(); + const auto& target = cv.target(); + if (cv.orientation() == COLLINEAR) { Comparison_result res1; Comparison_result res2; @@ -2569,20 +2976,19 @@ public: // source and the target. return (orient_f(source, p, target) == COLLINEAR); } - else { - // In case of a conic of degree 2, make a decision based on the conic's - // orientation and whether (source,p,target) is a right or a left turn. - if (arc.orientation() == COUNTERCLOCKWISE) - return (orient_f(source, p, target) == LEFT_TURN); - else - return (orient_f(source, p, target) == RIGHT_TURN); - } + + // In case of a conic of degree 2, make a decision based on the conic's + // orientation and whether (source,p,target) is a right or a left turn. + if (cv.orientation() == COUNTERCLOCKWISE) + return (orient_f(source, p, target) == LEFT_TURN); + else + return (orient_f(source, p, target) == RIGHT_TURN); } /*! Build the data for hyperbolic arc, contaning the characterization of the * hyperbolic branch the arc is placed on. */ - void build_hyperbolic_arc_data(Curve_2& arc) const { + void build_hyperbolic_arc_data(Curve_2& cv) const { // Let phi be the rotation angle of the conic from its canonic form. // We can write: // @@ -2594,10 +3000,10 @@ public: // cos(2*phi) = ----------------------- // sqrt((r - s)^2 + t^2) // - const int or_fact = (arc.orientation() == CLOCKWISE) ? -1 : 1; - const Algebraic r = m_nt_traits->convert(or_fact * arc.r()); - const Algebraic s = m_nt_traits->convert(or_fact * arc.s()); - const Algebraic t = m_nt_traits->convert(or_fact * arc.t()); + const int or_fact = (cv.orientation() == CLOCKWISE) ? -1 : 1; + const Algebraic r = m_nt_traits->convert(or_fact * cv.r()); + const Algebraic s = m_nt_traits->convert(or_fact * cv.s()); + const Algebraic t = m_nt_traits->convert(or_fact * cv.t()); const Algebraic cos_2phi = (r - s) / m_nt_traits->sqrt((r-s)*(r-s) + t*t); const Algebraic zero = 0; const Algebraic one = 1; @@ -2642,8 +3048,8 @@ public: // 4*r*s - t^2 4*r*s - t^2 // // The denominator (4*r*s - t^2) must be negative for hyperbolas. - const Algebraic u = m_nt_traits->convert(or_fact * arc.u()); - const Algebraic v = m_nt_traits->convert(or_fact * arc.v()); + const Algebraic u = m_nt_traits->convert(or_fact * cv.u()); + const Algebraic v = m_nt_traits->convert(or_fact * cv.v()); const Algebraic det = 4*r*s - t*t; Algebraic x0, y0; @@ -2666,14 +3072,14 @@ public: // Make sure that the two endpoints are located on the same branch // of the hyperbola. - const auto& source = arc.source(); - const auto& target = arc.target(); - arc.set_extra_data(extra_data); - extra_data->side = arc.sign_of_extra_data(source.x(), source.y()); + const auto& source = cv.source(); + const auto& target = cv.target(); + cv.set_extra_data(extra_data); + extra_data->side = cv.sign_of_extra_data(source.x(), source.y()); CGAL_assertion(extra_data->side != ZERO); CGAL_assertion(extra_data->side == - arc.sign_of_extra_data(target.x(), target.y())); + cv.sign_of_extra_data(target.x(), target.y())); } /*! Find the x coordinates of the underlying conic at a given y coordinate. @@ -2682,16 +3088,16 @@ public: * \pre The vector xs must be allocated at the size of 2. * \return The number of x coordinates computed (either 0, 1 or 2). */ - int conic_get_x_coordinates(const Curve_2& arc, + int conic_get_x_coordinates(const Curve_2& cv, const Algebraic& y, Algebraic* xs) const { // Solve the quadratic equation for a given y and find the x values: // r*x^2 + (t*y + u)*x + (s*y^2 + v*y + w) = 0 - Algebraic A = m_nt_traits->convert(arc.r()); + Algebraic A = m_nt_traits->convert(cv.r()); Algebraic B = - m_nt_traits->convert(arc.t())*y + m_nt_traits->convert(arc.u()); + m_nt_traits->convert(cv.t())*y + m_nt_traits->convert(cv.u()); Algebraic C = - (m_nt_traits->convert(arc.s())*y + m_nt_traits->convert(arc.v()))*y + - m_nt_traits->convert(arc.w()); + (m_nt_traits->convert(cv.s())*y + m_nt_traits->convert(cv.v()))*y + + m_nt_traits->convert(cv.w()); return solve_quadratic_equation(A, B, C, xs[0], xs[1]); } @@ -2702,16 +3108,16 @@ public: * \pre The vector ys must be allocated at the size of 2. * \return The number of y coordinates computed (either 0, 1 or 2). */ - int conic_get_y_coordinates(const Curve_2& arc, + int conic_get_y_coordinates(const Curve_2& cv, const Algebraic& x, Algebraic* ys) const { // Solve the quadratic equation for a given x and find the y values: // s*y^2 + (t*x + v)*y + (r*x^2 + u*x + w) = 0 - Algebraic A = m_nt_traits->convert(arc.s()); + Algebraic A = m_nt_traits->convert(cv.s()); Algebraic B = - m_nt_traits->convert(arc.t())*x + m_nt_traits->convert(arc.v()); + m_nt_traits->convert(cv.t())*x + m_nt_traits->convert(cv.v()); Algebraic C = - (m_nt_traits->convert(arc.r())*x + m_nt_traits->convert(arc.u()))*x + - m_nt_traits->convert(arc.w()); + (m_nt_traits->convert(cv.r())*x + m_nt_traits->convert(cv.u()))*x + + m_nt_traits->convert(cv.w()); return solve_quadratic_equation(A, B, C, ys[0], ys[1]); } @@ -2760,17 +3166,17 @@ public: * \pre The vector ps should be allocated at the size of 2. * \return The number of points found. */ - int points_at_x(const Curve_2& arc, const Point_2& p, Point_2* ps) const { + int points_at_x(const Curve_2& cv, const Point_2& p, Point_2* ps) const { // Get the y coordinates of the points on the conic. Algebraic ys[2]; - int n = conic_get_y_coordinates(arc, p.x(), ys); + int n = conic_get_y_coordinates(cv, p.x(), ys); // Find all the points that are contained in the arc. int m = 0; for (int i = 0; i < n; ++i) { ps[m] = Point_2(p.x(), ys[i]); - if (arc.is_full_conic() || is_between_endpoints(arc, ps[m])) ++m; + if (cv.is_full_conic() || is_between_endpoints(cv, ps[m])) ++m; } // Return the number of points on the arc. @@ -2784,17 +3190,17 @@ public: * \pre The vector ps should be allocated at the size of 2. * \return The number of points found. */ - int points_at_y(const Curve_2& arc, const Point_2& p, Point_2* ps) const { + int points_at_y(const Curve_2& cv, const Point_2& p, Point_2* ps) const { // Get the y coordinates of the points on the conic. Algebraic xs[2]; - int n = conic_get_x_coordinates(arc, p.y(), xs); + int n = conic_get_x_coordinates(cv, p.y(), xs); // Find all the points that are contained in the arc. int m = 0; for (int i = 0; i < n; ++i) { ps[m] = Point_2(xs[i], p.y()); - if (arc.is_full_conic() || is_between_endpoints(arc, ps[m])) ++m; + if (cv.is_full_conic() || is_between_endpoints(cv, ps[m])) ++m; } // Return the number of points on the arc. @@ -2917,24 +3323,19 @@ public: if ((xcv1.orientation() == COLLINEAR) && (xcv2.orientation() == COLLINEAR)) { // Construct the two supporting lines and compare them. - auto construct_line = m_alg_kernel->construct_line_2_object(); - typename Alg_kernel::Line_2 l1 = - construct_line(xcv1.source(), xcv1.target()); - typename Alg_kernel::Line_2 l2 = - construct_line(xcv2.source(), xcv2.target()); + auto ctr_line = m_alg_kernel->construct_line_2_object(); + typename Alg_kernel::Line_2 l1 = ctr_line(xcv1.source(), xcv1.target()); + typename Alg_kernel::Line_2 l2 = ctr_line(xcv2.source(), xcv2.target()); auto equal = m_alg_kernel->equal_2_object(); - if (equal(l1, l2)) return true; - // Try to compare l1 with the opposite of l2. - l2 = construct_line(xcv2.target(), xcv2.source()); - + l2 = ctr_line(xcv2.target(), xcv2.source()); return equal(l1, l2); } else if ((xcv1.orientation() == COLLINEAR) || (xcv2.orientation() == COLLINEAR)) { - // Only one arc is collinear, so the supporting curves cannot be the - // same: + // Only one arc is collinear; therefore so the supporting curves cannot + // be the same: return false; } @@ -2964,6 +3365,83 @@ public: CGAL::compare(xcv1.v() * factor2, xcv2.v() * factor1) == EQUAL && CGAL::compare(xcv1.w() * factor2, xcv2.w() * factor1) == EQUAL); } + + /*! Check whether the given point lies on the arc. + * \param p The qury point. + * \param (true) if p lies on the arc; (false) otherwise. + */ + bool contains_point(const X_monotone_curve_2& xcv, const Point_2& p) const { + // First check if p lies on the supporting conic. We first check whether + // it is one of p's generating conic curves. + bool p_on_conic(false); + if (p.is_generating_conic(xcv.id())) p_on_conic = true; + else { + // Check whether p satisfies the supporting conic equation. + p_on_conic = xcv.is_on_supporting_conic(p.x(), p.y()); + if (p_on_conic) { + // As p lies on the supporting conic of our arc, add its ID to + // the list of generating conics for p. + Point_2& p_non_const = const_cast(p); + p_non_const.set_generating_conic(xcv.id()); + } + } + + if (! p_on_conic) return false; + + // Check if p is between the endpoints of the arc. + return is_between_endpoints(xcv, p); + } + + /*! Calculate the vertical tangency points of the arc. + * \param vpts The vertical tangency points. + * \pre The vpts vector should be allocated at the size of 2. + * \return The number of vertical tangency points. + */ + int vertical_tangency_points(const Curve_2& cv, Alg_point_2* vpts) const { + // No vertical tangency points for line segments: + if (cv.orientation() == COLLINEAR) return 0; + + // Calculate the vertical tangency points of the supporting conic. + Alg_point_2 ps[2]; + auto n = cv.conic_vertical_tangency_points(ps); + // Return only the points that are contained in the arc interior. + int m(0); + for (int i = 0; i < n; ++i) { + std::cout << ps[i] << std::endl; + if (cv.is_full_conic() || is_strictly_between_endpoints(cv, ps[i])) + vpts[m++] = ps[i]; + } + + // Return the number of vertical tangency points found. + CGAL_assertion(m <= 2); + return m; + } + + /*! Calculate the horizontal tangency points of the arc. + * \param hpts The horizontal tangency points. + * \pre The hpts vector should be allocated at the size of 2. + * \return The number of horizontal tangency points. + */ + int horizontal_tangency_points(const Curve_2& cv, Point_2* hpts) const { + // No horizontal tangency points for line segments: + if (cv.orientation() == COLLINEAR) return 0; + + // Calculate the horizontal tangency points of the conic. + Alg_point_2 ps[2]; + int n = cv.conic_horizontal_tangency_points(ps); + + // Return only the points that are contained in the arc interior. + int m = 0; + + for (int i = 0; i < n; ++i) { + if (cv.is_full_conic() || is_strictly_between_endpoints(cv, ps[i])) + hpts[m++] = ps[i]; + } + + // Return the number of horizontal tangency points found. + CGAL_assertion(m <= 2); + return m; + } }; #include diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h index ac9a63b356e..5f17cad0d82 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h @@ -163,15 +163,15 @@ public: /// \name Get the arc properties. //@{ - /*! Check wheather the arc is valid. + /*! Determine wheather the arc is valid. */ bool is_valid() const { return test_flag(IS_VALID); } - /*! Check whether the arc represents a full conic curve. + /*! Determine whether the arc represents a full conic curve. */ bool is_full_conic() const { return test_flag(IS_FULL_CONIC); } - /*! Get the coefficients of the underlying conic. + /*! Obtain the coefficients of the underlying conic. */ const Integer& r() const { return (m_r); } const Integer& s() const { return (m_s); } @@ -180,22 +180,6 @@ public: const Integer& v() const { return (m_v); } const Integer& w() const { return (m_w); } - /*! Check whether the arc is x-monotone. - */ - bool is_x_monotone() const { - // Check if the arc contains no vertical tangency points. - Point_2 vtan_ps[2]; - return (vertical_tangency_points(vtan_ps) == 0); - } - - /*! Check whether the arc is y-monotone. - */ - bool is_y_monotone() const { - // Check if the arc contains no horizontal tangency points. - Point_2 htan_ps[2]; - return (horizontal_tangency_points(htan_ps) == 0); - } - /*! Obtain the arc's source. * \return The source point. * \pre The arc does not represent a full conic curve. @@ -305,11 +289,13 @@ public: //@} -public: +protected: + template friend class Arr_conic_traits_2; + /// \name Flag manipulation functions. //@{ template - constexpr size_t flag_mask(const T flag) const { return 0x1 << flag; } + static constexpr size_t flag_mask(const T flag) { return 0x1 << flag; } void reset_flags() { m_info = 0; } @@ -369,390 +355,6 @@ public: /*! Set the extra data field. */ void set_extra_data(Extra_data* extra_data) { m_extra_data = extra_data; } - - //@} - - /// \name Compute points on the arc. - //@{ - - /*! Calculate the vertical tangency points of the arc. - * \param vpts The vertical tangency points. - * \pre The vpts vector should be allocated at the size of 2. - * \return The number of vertical tangency points. - */ - int vertical_tangency_points(Point_2* vpts) const { - // No vertical tangency points for line segments: - if (m_orient == COLLINEAR) return 0; - - // Calculate the vertical tangency points of the supporting conic. - Point_2 ps[2]; - auto n = conic_vertical_tangency_points(ps); - - // Return only the points that are contained in the arc interior. - int m = 0; - - for (int i = 0; i < n; ++i) { - if (is_full_conic() || is_strictly_between_endpoints(ps[i])) { - vpts[m] = ps[i]; - ++m; - } - } - - // Return the number of vertical tangency points found. - CGAL_assertion(m <= 2); - return m; - } - - /*! Calculate the horizontal tangency points of the arc. - * \param hpts The horizontal tangency points. - * \pre The hpts vector should be allocated at the size of 2. - * \return The number of horizontal tangency points. - */ - int horizontal_tangency_points(Point_2* hpts) const { - // No horizontal tangency points for line segments: - if (m_orient == COLLINEAR) return 0; - - // Calculate the horizontal tangency points of the conic. - Point_2 ps[2]; - int n = conic_horizontal_tangency_points(ps); - - // Return only the points that are contained in the arc interior. - int m = 0; - - for (int i = 0; i < n; ++i) { - if (is_full_conic() || is_strictly_between_endpoints(ps[i])) { - hpts[m] = ps[i]; - ++m; - } - } - - // Return the number of horizontal tangency points found. - CGAL_assertion(m <= 2); - return m; - } - - /*! Find all points on the arc with a given x-coordinate. - * \param p A placeholder for the x-coordinate. - * \param ps The point on the arc at x(p). - * \pre The vector ps should be allocated at the size of 2. - * \return The number of points found. - */ - int points_at_x(const Point_2& p, Point_2* ps) const { - // Get the y coordinates of the points on the conic. - Algebraic ys[2]; - int n = conic_get_y_coordinates(p.x(), ys); - - // Find all the points that are contained in the arc. - int m = 0; - - for (int i = 0; i < n; ++i) { - ps[m] = Point_2(p.x(), ys[i]); - - if (is_full_conic() || is_between_endpoints(ps[m])) ++m; - } - - // Return the number of points on the arc. - CGAL_assertion(m <= 2); - return m; - } - - /*! Find all points on the arc with a given y-coordinate. - * \param p A placeholder for the y-coordinate. - * \param ps The point on the arc at x(p). - * \pre The vector ps should be allocated at the size of 2. - * \return The number of points found. - */ - int points_at_y(const Point_2& p, Point_2* ps) const { - // Get the y coordinates of the points on the conic. - Algebraic xs[2]; - int n = conic_get_x_coordinates(p.y(), xs); - - // Find all the points that are contained in the arc. - int m = 0; - - for (int i = 0; i < n; ++i) { - ps[m] = Point_2(xs[i], p.y()); - if (is_full_conic() || is_between_endpoints(ps[m])) ++m; - } - - // Return the number of points on the arc. - CGAL_assertion(m <= 2); - return m; - } - //@} - -private: - /// \name Auxiliary construction functions. - //@{ - - /*! Set the properties of a conic arc (for the usage of the constructors). - * \param rat_coeffs A vector of size 6, storing the rational coefficients - * of x^2, y^2, xy, x, y and the free coefficient resp. - */ - void set(const Rational* rat_coeffs) { - set_flag(IS_VALID); - - // Convert the coefficients vector to an equivalent vector of integer - // coefficients. - Nt_traits nt_traits; - Integer int_coeffs[6]; - - nt_traits.convert_coefficients(rat_coeffs, rat_coeffs + 6, int_coeffs); - - // Check the orientation of conic curve, and negate the conic coefficients - // if its given orientation. - typename Rat_kernel::Conic_2 temp_conic(rat_coeffs[0], rat_coeffs[1], - rat_coeffs[2], rat_coeffs[3], - rat_coeffs[4], rat_coeffs[5]); - - if (m_orient == temp_conic.orientation()) { - m_r = int_coeffs[0]; - m_s = int_coeffs[1]; - m_t = int_coeffs[2]; - m_u = int_coeffs[3]; - m_v = int_coeffs[4]; - m_w = int_coeffs[5]; - } - else { - m_r = -int_coeffs[0]; - m_s = -int_coeffs[1]; - m_t = -int_coeffs[2]; - m_u = -int_coeffs[3]; - m_v = -int_coeffs[4]; - m_w = -int_coeffs[5]; - } - - // Make sure both endpoint lie on the supporting conic. - if (! is_on_supporting_conic(m_source) || - ! is_on_supporting_conic(m_target)) - { - reset_flags(); // inavlid arc - return; - } - - m_extra_data = nullptr; - - // Check whether we have a degree 2 curve. - if ((CGAL::sign(m_r) != ZERO) || (CGAL::sign(m_s) != ZERO) || - (CGAL::sign(m_t) != ZERO)) - { - if (m_orient == COLLINEAR) { - // We have a segment of a line pair with rational coefficients. - // Compose the equation of the underlying line - // (with algebraic coefficients). - const Algebraic x1 = m_source.x(), y1 = m_source.y(); - const Algebraic x2 = m_target.x(), y2 = m_target.y(); - - // The supporting line is A*x + B*y + C = 0, where: - // - // A = y2 - y1, B = x1 - x2, C = x2*y1 - x1*y2 - // - // We use the extra dat field to store the equation of this line. - m_extra_data = new Extra_data; - m_extra_data->a = y2 - y1; - m_extra_data->b = x1 - x2; - m_extra_data->c = x2*y1 - x1*y2; - m_extra_data->side = ZERO; - - // Make sure the midpoint is on the line pair (thus making sure that - // the two points are not taken from different lines). - Alg_kernel ker; - Point_2 p_mid = ker.construct_midpoint_2_object()(m_source, m_target); - - if (CGAL::sign((nt_traits.convert(m_r)*p_mid.x() + - nt_traits.convert(m_t)*p_mid.y() + - nt_traits.convert(m_u)) * p_mid.x() + - (nt_traits.convert(m_s)*p_mid.y() + - nt_traits.convert(m_v)) * p_mid.y() + - nt_traits.convert(m_w)) != ZERO) - { - reset_flags(); // inavlid arc - return; - } - } - else { - // The sign of (4rs - t^2) detetmines the conic type: - // - if it is possitive, the conic is an ellipse, - // - if it is negative, the conic is a hyperbola, - // - if it is zero, the conic is a parabola. - CGAL::Sign sign_conic = CGAL::sign(4*m_r*m_s - m_t*m_t); - - // Build the extra hyperbolic data if necessary - if (sign_conic == NEGATIVE) build_hyperbolic_arc_data(); - - if (sign_conic != POSITIVE) { - // In case of a non-degenerate parabola or a hyperbola, make sure - // the arc is not infinite. - Alg_kernel ker; - Point_2 p_mid = ker.construct_midpoint_2_object()(m_source, m_target); - Point_2 ps[2]; - - bool finite_at_x = (points_at_x(p_mid, ps) > 0); - bool finite_at_y = (points_at_y(p_mid, ps) > 0); - - if (! finite_at_x && ! finite_at_y) { - reset_flags(); // inavlid arc - return; - } - } - } - } - - - set_flag(IS_VALID); // mark that this arc valid - reset_flag(IS_FULL_CONIC); // mark that this arc is not a full conic - } - - /*! Set the properties of a conic arc that is really a full curve - * (that is, an ellipse). - * \param rat_coeffs A vector of size 6, storing the rational coefficients - * of x^2, y^2, xy, x, y and the free coefficient resp. - * \param comp_orient Should we compute the orientation of the given curve. - */ - void set_full(const Rational* rat_coeffs, const bool& comp_orient) { - // Convert the coefficients vector to an equivalent vector of integer - // coefficients. - Nt_traits nt_traits; - Integer int_coeffs[6]; - - nt_traits.convert_coefficients(rat_coeffs, rat_coeffs + 6, int_coeffs); - - // Check the orientation of conic curve, and negate the conic coefficients - // if its given orientation. - typename Rat_kernel::Conic_2 temp_conic(rat_coeffs[0], rat_coeffs[1], - rat_coeffs[2], rat_coeffs[3], - rat_coeffs[4], rat_coeffs[5]); - const Orientation temp_orient = temp_conic.orientation(); - - if (comp_orient) m_orient = temp_orient; - - if (m_orient == temp_orient) { - m_r = int_coeffs[0]; - m_s = int_coeffs[1]; - m_t = int_coeffs[2]; - m_u = int_coeffs[3]; - m_v = int_coeffs[4]; - m_w = int_coeffs[5]; - } - else { - m_r = -int_coeffs[0]; - m_s = -int_coeffs[1]; - m_t = -int_coeffs[2]; - m_u = -int_coeffs[3]; - m_v = -int_coeffs[4]; - m_w = -int_coeffs[5]; - } - - // Make sure the conic is a non-degenerate ellipse: - // The coefficients should satisfy (4rs - t^2) > 0. - const bool is_ellipse = (CGAL::sign(4*m_r*m_s - m_t*m_t) == POSITIVE); - CGAL_assertion(is_ellipse); - - // We do not have to store any extra data with the arc. - m_extra_data = nullptr; - - // Mark that this arc is a full conic curve. - if (is_ellipse) { - set_flag(IS_VALID); - set_flag(IS_FULL_CONIC); - } - else reset_flags(); // inavlid arc - } - - /*! Build the data for hyperbolic arc, contaning the characterization of the - * hyperbolic branch the arc is placed on. - */ - void build_hyperbolic_arc_data() { - // Let phi be the rotation angle of the conic from its canonic form. - // We can write: - // - // t - // sin(2*phi) = ----------------------- - // sqrt((r - s)^2 + t^2) - // - // r - s - // cos(2*phi) = ----------------------- - // sqrt((r - s)^2 + t^2) - // - Nt_traits nt_traits; - const int or_fact = (m_orient == CLOCKWISE) ? -1 : 1; - const Algebraic r = nt_traits.convert(or_fact * m_r); - const Algebraic s = nt_traits.convert(or_fact * m_s); - const Algebraic t = nt_traits.convert(or_fact * m_t); - const Algebraic cos_2phi = (r - s) / nt_traits.sqrt((r-s)*(r-s) + t*t); - const Algebraic zero = 0; - const Algebraic one = 1; - const Algebraic two = 2; - Algebraic sin_phi; - Algebraic cos_phi; - - // Calculate sin(phi) and cos(phi) according to the half-angle formulae: - // - // sin(phi)^2 = 0.5 * (1 - cos(2*phi)) - // cos(phi)^2 = 0.5 * (1 + cos(2*phi)) - Sign sign_t = CGAL::sign(t); - - if (sign_t == ZERO) { - // sin(2*phi) == 0, so phi = 0 or phi = PI/2 - if (CGAL::sign(cos_2phi) == POSITIVE) { - // phi = 0. - sin_phi = zero; - cos_phi = one; - } - else { - // phi = PI/2. - sin_phi = one; - cos_phi = zero; - } - } - else if (sign_t == POSITIVE) { - // sin(2*phi) > 0 so 0 < phi < PI/2. - sin_phi = nt_traits.sqrt((one + cos_2phi) / two); - cos_phi = nt_traits.sqrt((one - cos_2phi) / two); - } - else { - // sin(2*phi) < 0 so PI/2 < phi < PI. - sin_phi = nt_traits.sqrt((one + cos_2phi) / two); - cos_phi = -nt_traits.sqrt((one - cos_2phi) / two); - } - - // Calculate the center (x0, y0) of the conic, given by the formulae: - // - // t*v - 2*s*u t*u - 2*r*v - // x0 = ------------- , y0 = ------------- - // 4*r*s - t^2 4*r*s - t^2 - // - // The denominator (4*r*s - t^2) must be negative for hyperbolas. - const Algebraic u = nt_traits.convert(or_fact * m_u); - const Algebraic v = nt_traits.convert(or_fact * m_v); - const Algebraic det = 4*r*s - t*t; - Algebraic x0, y0; - - CGAL_assertion(CGAL::sign(det) == NEGATIVE); - - x0 = (t*v - two*s*u) / det; - y0 = (t*u - two*r*v) / det; - - // The axis separating the two branches of the hyperbola is now given by: - // - // cos(phi)*x + sin(phi)*y - (cos(phi)*x0 + sin(phi)*y0) = 0 - // - // We store the equation of this line in the extra data structure and also - // the sign (side of half-plane) our arc occupies with respect to the line. - m_extra_data = new Extra_data; - - m_extra_data->a = cos_phi; - m_extra_data->b = sin_phi; - m_extra_data->c = - (cos_phi*x0 + sin_phi*y0); - - // Make sure that the two endpoints are located on the same branch - // of the hyperbola. - m_extra_data->side = sign_of_extra_data(m_source.x(), m_source.y()); - - CGAL_assertion(m_extra_data->side != ZERO); - CGAL_assertion(m_extra_data->side == - sign_of_extra_data(m_target.x(), m_target.y())); - } //@} public: @@ -790,90 +392,6 @@ protected: return (CGAL::sign(val) == ZERO); } - /*! Check whether the given point is between the source and the target. - * The point is assumed to be on the conic's boundary. - * \param p The query point. - * \return true if the point is between the two endpoints, - * (false) if it is not. - */ - bool is_between_endpoints(const Point_2& p) const { - CGAL_precondition(! is_full_conic()); - - // Check if p is one of the endpoints. - Alg_kernel ker; - - if (ker.equal_2_object()(p, m_source) || ker.equal_2_object()(p, m_target)) - return true; - else return (is_strictly_between_endpoints(p)); - } - - /*! Check whether the given point is strictly between the source and the - * target (but not any of them). - * The point is assumed to be on the conic's boundary. - * \param p The query point. - * \return true if the point is strictly between the two endpoints, - * (false) if it is not. - */ - bool is_strictly_between_endpoints(const Point_2& p) const { - // In case this is a full conic, any point on its boundary is between - // its end points. - if (is_full_conic()) return true; - - // Check if we have extra data available. - if (m_extra_data != nullptr) { - if (m_extra_data->side != ZERO) { - // In case of a hyperbolic arc, make sure the point is located on the - // same branch as the arc. - if (sign_of_extra_data(p.x(), p.y()) != m_extra_data->side) - return false; - } - else { - // In case we have a segment of a line pair, make sure that p really - // satisfies the equation of the line. - if (sign_of_extra_data(p.x(), p.y()) != ZERO) return false; - } - } - - // Act according to the conic degree. - Alg_kernel ker; - - if (m_orient == COLLINEAR) { - Comparison_result res1; - Comparison_result res2; - - if (ker.compare_x_2_object()(m_source, m_target) == EQUAL) { - // In case of a vertical segment - just check whether the y coordinate - // of p is between those of the source's and of the target's. - res1 = ker.compare_y_2_object()(p, m_source); - res2 = ker.compare_y_2_object()(p, m_target); - } - else { - // Otherwise, since the segment is x-monotone, just check whether the - // x coordinate of p is between those of the source's and of the - // target's. - res1 = ker.compare_x_2_object()(p, m_source); - res2 = ker.compare_x_2_object()(p, m_target); - } - - // If p is not in the (open) x-range (or y-range) of the segment, it - // cannot be contained in the segment. - if ((res1 == EQUAL) || (res2 == EQUAL) || (res1 == res2)) return false; - - // Perform an orientation test: This is crucial for segment of line - // pairs, as we want to make sure that p lies on the same line as the - // source and the target. - return (ker.orientation_2_object()(m_source, p, m_target) == COLLINEAR); - } - else { - // In case of a conic of degree 2, make a decision based on the conic's - // orientation and whether (source,p,target) is a right or a left turn. - if (m_orient == COUNTERCLOCKWISE) - return (ker.orientation_2_object()(m_source, p, m_target) == LEFT_TURN); - else - return (ker.orientation_2_object()(m_source, p, m_target) == RIGHT_TURN); - } - } - /*! Find the vertical tangency points of the undelying conic. * \param ps The output points of vertical tangency. * This area must be allocated at the size of 2. @@ -930,7 +448,7 @@ protected: ++n; } else { - for (int j = 0; j < n_ys; j++) { + for (int j = 0; j < n_ys; ++j) { if (CGAL::compare(nt_traits.convert(two*m_s) * ys[j], -(nt_traits.convert(m_t) * xs[i] + nt_traits.convert(m_v))) == EQUAL) @@ -953,7 +471,7 @@ protected: * \return The number of horizontal tangency points. */ int conic_horizontal_tangency_points(Point_2* ps) const { - const Integer zero = 0; + const Integer zero(0); // In case the base conic is of degree 1 (and not 2), the arc has no // vertical tangency points. @@ -968,7 +486,7 @@ protected: const Integer four = 4; int n; Algebraic ys[2]; - Algebraic *ys_end; + Algebraic* ys_end; Nt_traits nt_traits; ys_end = nt_traits.solve_quadratic_equation(m_t*m_t - four*m_r*m_s, @@ -990,42 +508,6 @@ protected: return n; } - /*! Find the y coordinates of the underlying conic at a given x coordinate. - * \param x The x coordinate. - * \param ys The output y coordinates. - * \pre The vector ys must be allocated at the size of 2. - * \return The number of y coordinates computed (either 0, 1 or 2). - */ - int conic_get_y_coordinates(const Algebraic& x, Algebraic* ys) const { - // Solve the quadratic equation for a given x and find the y values: - // s*y^2 + (t*x + v)*y + (r*x^2 + u*x + w) = 0 - Nt_traits nt_traits; - Algebraic A = nt_traits.convert(m_s); - Algebraic B = nt_traits.convert(m_t)*x + nt_traits.convert(m_v); - Algebraic C = (nt_traits.convert(m_r)*x + nt_traits.convert(m_u))*x + - nt_traits.convert(m_w); - - return (solve_quadratic_equation(A, B, C, ys[0], ys[1])); - } - - /*! Find the x coordinates of the underlying conic at a given y coordinate. - * \param y The y coordinate. - * \param xs The output x coordinates. - * \pre The vector xs must be allocated at the size of 2. - * \return The number of x coordinates computed (either 0, 1 or 2). - */ - int conic_get_x_coordinates(const Algebraic& y, Algebraic* xs) const { - // Solve the quadratic equation for a given y and find the x values: - // r*x^2 + (t*y + u)*x + (s*y^2 + v*y + w) = 0 - Nt_traits nt_traits; - Algebraic A = nt_traits.convert(m_r); - Algebraic B = nt_traits.convert(m_t)*y + nt_traits.convert(m_u); - Algebraic C = (nt_traits.convert(m_s)*y + nt_traits.convert(m_v))*y + - nt_traits.convert(m_w); - - return (solve_quadratic_equation(A, B, C, xs[0], xs[1])); - } - /*! Solve the given quadratic equation: Ax^2 + B*x + C = 0. * \param x_minus The root obtained from taking -sqrt(discriminant). * \param x_plus The root obtained from taking -sqrt(discriminant). @@ -1064,7 +546,6 @@ protected: return 2; } //@} - }; /*! Exporter for conic arcs. diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h index 16eef6de002..cd993d7e7d0 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h @@ -45,14 +45,8 @@ public: // Type definition for the intersection points mapping. typedef typename Conic_point_2::Conic_id Conic_id; - typedef std::pair Conic_pair; - typedef std::pair Intersection_point; - typedef std::list Intersection_list; using Conic_arc_2::sign_of_extra_data; - using Conic_arc_2::is_between_endpoints; - using Conic_arc_2::is_strictly_between_endpoints; - using Conic_arc_2::conic_get_y_coordinates; using Conic_arc_2::IS_VALID; using Conic_arc_2::IS_FULL_CONIC; @@ -64,21 +58,6 @@ public: using Conic_arc_2::flip_flag; using Conic_arc_2::test_flag; - /*! \struct Less functor for Conic_pair. - */ - struct Less_conic_pair { - bool operator()(const Conic_pair& cp1, const Conic_pair& cp2) const { - // Compare the pairs of IDs lexicographically. - return ((cp1.first < cp2.first) || - ((cp1.first == cp2.first) && (cp1.second < cp2.second))); - } - }; - - typedef std::map - Intersection_map; - typedef typename Intersection_map::value_type Intersection_map_entry; - typedef typename Intersection_map::iterator Intersection_map_iterator; - private: typedef Conic_arc_2 Base; @@ -112,7 +91,7 @@ public: FACING_MASK = (0x1 << FACING_UP) | (0x1 << FACING_DOWN) }; - /// \name Constrcution methods. + /// \name Public constrcutors, assignment operators, and destructors. //@{ /*! Default constructor. @@ -136,14 +115,42 @@ public: m_id(arc.m_id) {} + /*! Assignment operator. + * \param arc The copied arc. + */ + const Self& operator=(const Self& arc) { + CGAL_precondition (arc.is_valid()); + + if (this == &arc) return (*this); + + // Copy the base arc. + Base::operator= (arc); + + // Set the rest of the properties. + m_alg_r = arc.m_alg_r; + m_alg_s = arc.m_alg_s; + m_alg_t = arc.m_alg_t; + m_alg_u = arc.m_alg_u; + m_alg_v = arc.m_alg_v; + m_alg_w = arc.m_alg_w; + + m_id = arc.m_id; + + return (*this); + } + //@} + +private: + template friend class Arr_conic_traits_2; + + /// \name private constrcutors to be used only by the traits class template. + //@{ + /*! Construct an x-monotone arc from a conic arc. * \param arc The given (base) arc. * \pre The given arc is x-monotone. */ - _Conic_x_monotone_arc_2(const Base& arc) : - Base(arc), - m_id() - {} + _Conic_x_monotone_arc_2(const Base& arc) : Base(arc), m_id() {} /*! Construct an x-monotone arc from a conic arc. * \param arc The given (base) arc. @@ -189,31 +196,16 @@ public: Base() {} - /*! Assignment operator. - * \param arc The copied arc. + /*! Obtain the non const reference to the curve source point. */ - const Self& operator=(const Self& arc) { - CGAL_precondition (arc.is_valid()); + Conic_point_2& source() { return (this->m_source); } - if (this == &arc) return (*this); - - // Copy the base arc. - Base::operator= (arc); - - // Set the rest of the properties. - m_alg_r = arc.m_alg_r; - m_alg_s = arc.m_alg_s; - m_alg_t = arc.m_alg_t; - m_alg_u = arc.m_alg_u; - m_alg_v = arc.m_alg_v; - m_alg_w = arc.m_alg_w; - - m_id = arc.m_id; - - return (*this); - } + /*! Obtain the non const reference to the curve source point. + */ + Conic_point_2& target() { return this->m_target; } //@} +public: /// \name Accessing the arc properties. //@{ @@ -238,13 +230,11 @@ public: * \return The source point. */ const Conic_point_2& source() const { return (this->m_source); } - Conic_point_2& source() { return (this->m_source); } /*! Obtain the arc's target. * \return The target point. */ const Conic_point_2& target() const { return this->m_target; } - Conic_point_2& target() { return this->m_target; } /*! Obtain the orientation of the arc. * \return The orientation. @@ -265,11 +255,37 @@ public: else return this->m_source; } - /*! Return true iff the conic arc is directed right iexicographically. + /*! Determine whether the conic arc is directed iexicographically right. */ - bool is_directed_right() const - { return test_flag(IS_DIRECTED_RIGHT); } + bool is_directed_right() const { return test_flag(IS_DIRECTED_RIGHT); } + /*! Determine whether the conic arc is a vertical segment. + */ + bool is_vertical() const { return test_flag(IS_VERTICAL_SEGMENT); } + + /*! Determine whether the conic arc is a facing up. + */ + bool is_upper() const { return test_flag(FACING_UP); } + + /*! Determine whether the conic arc is a facing down. + */ + bool is_lower() const { return test_flag(FACING_DOWN); } + + /*! Check whether the arc is a special segment connecting two algebraic + * endpoints (and has no undelying integer conic coefficients). + */ + bool is_special_segment() const { return test_flag(IS_SPECIAL_SEGMENT); } + + /*! Obtain the mask of the DEGREE_1 flag. + */ + static constexpr size_t degree_1_mask() { return flag_mask(DEGREE_1); } + + /*! Obtain the mask of the DEGREE_1 flag. + */ + static constexpr size_t degree_2_mask() { return flag_mask(DEGREE_2); } + + /*! Obtain the algebraic coefficients. + */ Algebraic alg_r() const { return m_alg_r; } Algebraic alg_s() const { return m_alg_s; } Algebraic alg_t() const { return m_alg_t; } @@ -289,6 +305,9 @@ public: // Setters //@{ + + /*! Set the algebraic coefficients. + */ void set_alg_coefficients(const Algebraic& alg_r, const Algebraic& alg_s, const Algebraic& alg_t, const Algebraic& alg_u, const Algebraic& alg_v, const Algebraic& alg_w) @@ -301,49 +320,12 @@ public: m_alg_w = alg_w; } - /*! Add a generating conic ID. */ + /*! Add a generating conic ID. + */ void set_generating_conic(const Conic_id& id) { this->m_source.set_generating_conic(id); this->m_target.set_generating_conic(id); } - - //@} - - /// \name Predicates. - //@{ - - /*! Check if the conic arc is a vertical segment. - */ - bool is_vertical() const - { return test_flag(IS_VERTICAL_SEGMENT); } - - /*! Check whether the given point lies on the arc. - * \param p The qury point. - * \param (true) if p lies on the arc; (false) otherwise. - */ - bool contains_point(const Conic_point_2& p) const { - // First check if p lies on the supporting conic. We first check whether - // it is one of p's generating conic curves. - bool p_on_conic(false); - - if (p.is_generating_conic(m_id)) p_on_conic = true; - else { - // Check whether p satisfies the supporting conic equation. - p_on_conic = is_on_supporting_conic(p.x(), p.y()); - - if (p_on_conic) { - // As p lies on the supporting conic of our arc, add its ID to - // the list of generating conics for p. - Conic_point_2& p_non_const = const_cast(p); - p_non_const.set_generating_conic(m_id); - } - } - - if (! p_on_conic) return false; - - // Check if p is between the endpoints of the arc. - return is_between_endpoints(p); - } //@} /// \name Constructing points on the arc. @@ -413,92 +395,6 @@ public: return oi; } - /*! Compute the intersections with the given arc. - * \param arc The given intersecting arc. - * \param inter_map Maps conic pairs to lists of their intersection points. - * \param oi The output iterator. - * \return The past-the-end iterator. - */ - template - OutputIterator intersect(const Self& arc, Intersection_map& inter_map, - OutputIterator oi) const - { - typedef boost::variant Intersection_result; - - if (has_same_supporting_conic(arc)) { - // Check for overlaps between the two arcs. - Self overlap; - - if (compute_overlap(arc, overlap)) { - // There can be just a single overlap between two x-monotone arcs: - *oi++ = Intersection_result(overlap); - return oi; - } - - // In case there is not overlap and the supporting conics are the same, - // there cannot be any intersection points, unless the two arcs share - // an end point. - // Note that in this case we do not define the multiplicity of the - // intersection points we report. - Alg_kernel ker; - - if (ker.equal_2_object()(left(), arc.left())) { - Intersection_point ip(left(), 0); - *oi++ = Intersection_result(ip); - } - - if (ker.equal_2_object()(right(), arc.right())) { - Intersection_point ip(right(), 0); - *oi++ = Intersection_result(ip); - } - - return oi; - } - - // Search for the pair of supporting conics in the map (the first conic - // ID in the pair should be smaller than the second one, to guarantee - // uniqueness). - Conic_pair conic_pair; - Intersection_map_iterator map_iter; - Intersection_list inter_list; - bool invalid_ids = false; - - if (m_id.is_valid() && arc.m_id.is_valid()) { - if (m_id < arc.m_id) conic_pair = Conic_pair(m_id, arc.m_id); - else conic_pair = Conic_pair(arc.m_id, m_id); - map_iter = inter_map.find(conic_pair); - } - else { - // In case one of the IDs is invalid, we do not look in the map neither - // we cache the results. - map_iter = inter_map.end(); - invalid_ids = true; - } - - if (map_iter == inter_map.end()) { - // In case the intersection points between the supporting conics have - // not been computed before, compute them now and store them in the map. - intersect_supporting_conics(arc, inter_list); - - if (! invalid_ids) inter_map[conic_pair] = inter_list; - } - else { - // Obtain the precomputed intersection points from the map. - inter_list = (*map_iter).second; - } - - // Go over the list of intersection points and report those that lie on - // both x-monotone arcs. - for (auto iter = inter_list.begin(); iter != inter_list.end(); ++iter) { - if (is_between_endpoints((*iter).first) && - arc.is_between_endpoints((*iter).first)) - { - *oi++ = Intersection_result(*iter); - } - } - - return oi; - } //@} /// \name Constructing x-monotone arcs. @@ -524,161 +420,12 @@ public: return arc; } - - /*! Check whether the two arcs are equal (have the same graph). - * \param arc The compared arc. - * \return (true) if the two arcs have the same graph; (false) otherwise. - */ - bool equals(const Self& arc) const { - // The two arc must have the same supporting conic curves. - if (! has_same_supporting_conic (arc)) return false; - - // Check that the arc endpoints are the same. - Alg_kernel ker; - - if (this->m_orient == COLLINEAR) { - CGAL_assertion(arc.m_orient == COLLINEAR); - return((ker.equal_2_object()(this->m_source, arc.m_source) && - ker.equal_2_object()(this->m_target, arc.m_target)) || - (ker.equal_2_object()(this->m_source, arc.m_target) && - ker.equal_2_object()(this->m_target, arc.m_source))); - } - - if (this->m_orient == arc.m_orient) { - // Same orientation - the source and target points must be the same. - return (ker.equal_2_object()(this->m_source, arc.m_source) && - ker.equal_2_object()(this->m_target, arc.m_target)); - } - else { - // Reverse orientation - the source and target points must be swapped. - return (ker.equal_2_object()(this->m_source, arc.m_target) && - ker.equal_2_object()(this->m_target, arc.m_source)); - } - } - - bool is_upper() const { return test_flag(FACING_UP); } - - bool is_lower() const { return test_flag(FACING_DOWN); } - - /*! Check whether the arc is a special segment connecting two algebraic - * endpoints (and has no undelying integer conic coefficients). - */ - bool is_special_segment() const { return test_flag(IS_SPECIAL_SEGMENT); } - //@} private: /// \name Auxiliary (private) functions. //@{ - /*! Set the properties of the x-monotone conic arc (for the usage of the - * constructors). - */ - void set_x_monotone() { - // Convert the coefficients of the supporting conic to algebraic numbers. - Nt_traits nt_traits; - - m_alg_r = nt_traits.convert(this->m_r); - m_alg_s = nt_traits.convert(this->m_s); - m_alg_t = nt_traits.convert(this->m_t); - m_alg_u = nt_traits.convert(this->m_u); - m_alg_v = nt_traits.convert(this->m_v); - m_alg_w = nt_traits.convert(this->m_w); - - // Set the generating conic ID for the source and target points. - this->m_source.set_generating_conic(m_id); - this->m_target.set_generating_conic(m_id); - - // Update the m_info bits. - set_flag(IS_VALID); - reset_flag(IS_FULL_CONIC); - - // Check if the arc is directed right (the target is lexicographically - // greater than the source point), or to the left. - Alg_kernel ker; - Comparison_result dir_res = - ker.compare_xy_2_object()(this->m_source, this->m_target); - - CGAL_assertion(dir_res != EQUAL); - - if (dir_res == SMALLER) set_flag(IS_DIRECTED_RIGHT); - - // Compute the degree of the underlying conic. - if ((CGAL::sign(this->m_r) != ZERO) || - (CGAL::sign(this->m_s) != ZERO) || - (CGAL::sign(this->m_t) != ZERO)) - { - set_flag(DEGREE_2); - - if (this->m_orient == COLLINEAR) { - set_flag(IS_SPECIAL_SEGMENT); - - // Check whether the arc is a vertical segment: - if (ker.compare_x_2_object()(this->m_source, this->m_target) == EQUAL) - set_flag(IS_VERTICAL_SEGMENT); - - return; - } - } - else { - CGAL_assertion(CGAL::sign(this->m_u) != ZERO || - CGAL::sign(this->m_v) != ZERO); - - if (CGAL::sign(this->m_v) == ZERO) { - - // The supporting curve is of the form: _u*x + _w = 0 - set_flag(IS_VERTICAL_SEGMENT); - } - - set_flag(DEGREE_1); - - return; - } - - if (this->m_orient == COLLINEAR) return; - - // Compute a midpoint between the source and the target and get the y-value - // of the arc at its x-coordiante. - Point_2 p_mid = - ker.construct_midpoint_2_object()(this->m_source, this->m_target); - Algebraic ys[2]; - CGAL_assertion_code(int n_ys = ) - conic_get_y_coordinates(p_mid.x(), ys); - - CGAL_assertion(n_ys != 0); - - // Check which solution lies on the x-monotone arc. - Point_2 p_arc_mid(p_mid.x(), ys[0]); - - if (is_strictly_between_endpoints(p_arc_mid)) { - // Mark that we should use the -sqrt(disc) root for points on this - // x-monotone arc. - reset_flag(PLUS_SQRT_DISC_ROOT); - } - else { - CGAL_assertion (n_ys == 2); - p_arc_mid = Point_2 (p_mid.x(), ys[1]); - - CGAL_assertion(is_strictly_between_endpoints(p_arc_mid)); - - // Mark that we should use the +sqrt(disc) root for points on this - // x-monotone arc. - set_flag(PLUS_SQRT_DISC_ROOT); - } - - // Check whether the conic is facing up or facing down: - // Check whether the arc (which is x-monotone of degree 2) lies above or - // below the segement that contects its two end-points (x1,y1) and (x2,y2). - // To do that, we find the y coordinate of a point on the arc whose x - // coordinate is (x1+x2)/2 and compare it to (y1+y2)/2. - Comparison_result res = ker.compare_y_2_object() (p_arc_mid, p_mid); - - // If the arc is above the connecting segment, so it is facing upwards. - if (res == LARGER) set_flag(FACING_UP); - // If the arc is below the connecting segment, so it is facing downwards. - else if (res == SMALLER) set_flag(FACING_DOWN); - } - /*! Check whether the given point lies on the supporting conic of the arc. * \param px The x-coordinate of query point. * \param py The y-coordinate of query point. @@ -702,66 +449,6 @@ private: return (_sign == ZERO); } - /*! Check whether the two arcs have the same supporting conic. - * \param arc The compared arc. - * \return (true) if the two supporting conics are the same. - */ - bool has_same_supporting_conic(const Self& arc) const { - // Check if the two arcs originate from the same conic: - if (m_id == arc.m_id && m_id.is_valid() && arc.m_id.is_valid()) return true; - - // In case both arcs are collinear, check if they have the same - // supporting lines. - if ((this->m_orient == COLLINEAR) && (arc.m_orient == COLLINEAR)) { - // Construct the two supporting lines and compare them. - Alg_kernel ker; - auto construct_line = ker.construct_line_2_object(); - typename Alg_kernel::Line_2 l1 = - construct_line(this->m_source, this->m_target); - typename Alg_kernel::Line_2 l2 = - construct_line(arc.m_source, arc.m_target); - auto equal = ker.equal_2_object(); - - if (equal(l1, l2)) return true; - - // Try to compare l1 with the opposite of l2. - l2 = construct_line(arc.m_target, arc.m_source); - - return equal(l1, l2); - } - else if ((this->m_orient == COLLINEAR) || (arc.m_orient == COLLINEAR)) { - // Only one arc is collinear, so the supporting curves cannot be the - // same: - return false; - } - - // Check whether the coefficients of the two supporting conics are equal - // up to a constant factor. - Integer factor1 = 1; - Integer factor2 = 1; - - if (CGAL::sign(this->m_r) != ZERO) factor1 = this->m_r; - else if (CGAL::sign(this->m_s) != ZERO) factor1 = this->m_s; - else if (CGAL::sign(this->m_t) != ZERO) factor1 = this->m_t; - else if (CGAL::sign(this->m_u) != ZERO) factor1 = this->m_u; - else if (CGAL::sign(this->m_v) != ZERO) factor1 = this->m_v; - else if (CGAL::sign(this->m_w) != ZERO) factor1 = this->m_w; - - if (CGAL::sign(arc.m_r) != ZERO) factor2 = arc.m_r; - else if (CGAL::sign(arc.m_s) != ZERO) factor2 = arc.m_s; - else if (CGAL::sign(arc.m_t) != ZERO) factor2 = arc.m_t; - else if (CGAL::sign(arc.m_u) != ZERO) factor2 = arc.m_u; - else if (CGAL::sign(arc.m_v) != ZERO) factor2 = arc.m_v; - else if (CGAL::sign(arc.m_w) != ZERO) factor2 = arc.m_w; - - return (CGAL::compare(this->m_r * factor2, arc.m_r * factor1) == EQUAL && - CGAL::compare(this->m_s * factor2, arc.m_s * factor1) == EQUAL && - CGAL::compare(this->m_t * factor2, arc.m_t * factor1) == EQUAL && - CGAL::compare(this->m_u * factor2, arc.m_u * factor1) == EQUAL && - CGAL::compare(this->m_v * factor2, arc.m_v * factor1) == EQUAL && - CGAL::compare(this->m_w * factor2, arc.m_w * factor1) == EQUAL); - } - public: /*! Obtain the i'th order derivative by x of the conic at the point p=(x,y). * \param p The point where we derive. @@ -886,7 +573,7 @@ public: // so their first-order derivative by x is simply -b/a. The higher-order // derivatives are all 0. if (i == 1) { - if (CGAL::sign (this->m_extra_data->a) != NEGATIVE) { + if (CGAL::sign(this->m_extra_data->a) != NEGATIVE) { slope_numer = - this->m_extra_data->b; slope_denom = this->m_extra_data->a; } @@ -982,264 +669,14 @@ public: } private: - /*! Compute the overlap with a given arc, which is supposed to have the same - * supporting conic curve as this arc. - * \param arc The given arc. - * \param overlap Output: The overlapping arc (if any). - * \return Whether we found an overlap. - */ - bool compute_overlap(const Self& arc, Self& overlap) const { - // Check if the two arcs are identical. - if (equals(arc)) { - overlap = arc; - return true; - } - - if (is_strictly_between_endpoints(arc.left())) { - if (is_strictly_between_endpoints(arc.right())) { - // Case 1 - *this: +-----------> - // arc: +=====> - overlap = arc; - return true; - } - else { - // Case 2 - *this: +-----------> - // arc: +=====> - overlap = *this; - - if (overlap.test_flag(IS_DIRECTED_RIGHT)) - overlap.m_source = arc.left(); - else - overlap.m_target = arc.left(); - - return true; - } - } - else if (is_strictly_between_endpoints(arc.right())) { - // Case 3 - *this: +-----------> - // arc: +=====> - overlap = *this; - - if (overlap.test_flag(IS_DIRECTED_RIGHT)) - overlap.m_target = arc.right(); - else - overlap.m_source = arc.right(); - - return true; - } - else if (arc.is_between_endpoints(this->m_source) && - arc.is_between_endpoints(this->m_target) && - (arc.is_strictly_between_endpoints(this->m_source) || - arc.is_strictly_between_endpoints(this->m_target))) - { - // Case 4 - *this: +-----------> - // arc: +================> - overlap = *this; - return true; - } - - // If we reached here, there are no overlaps: - return false; - } - - /*! Intersect the supporing conic curves of this arc and the given arc. - * \param arc The arc to intersect with. - * \param inter_list The list of intersection points. - */ - void intersect_supporting_conics(const Self& arc, - Intersection_list& inter_list) const { - if (is_special_segment() && ! arc.is_special_segment()) { - // If one of the arcs is a special segment, make sure it is (arc). - arc.intersect_supporting_conics(*this, inter_list); - return; - } - - const int deg1 = ((this->m_info & DEGREE_MASK) == flag_mask(DEGREE_1)) ? 1 : 2; - const int deg2 = ((arc.m_info & DEGREE_MASK) == flag_mask(DEGREE_1)) ? 1 : 2; - Nt_traits nt_traits; - Algebraic xs[4]; - int n_xs = 0; - Algebraic ys[4]; - int n_ys = 0; - - if (arc.is_special_segment()) { - // The second arc is a special segment (a*x + b*y + c = 0). - if (is_special_segment()) { - // Both arc are sepcial segment, so they have at most one intersection - // point. - Algebraic denom = this->m_extra_data->a * arc.m_extra_data->b - - this->m_extra_data->b * arc.m_extra_data->a; - - if (CGAL::sign (denom) != CGAL::ZERO) { - xs[0] = (this->m_extra_data->b * arc.m_extra_data->c - - this->m_extra_data->c * arc.m_extra_data->b) / denom; - n_xs = 1; - - ys[0] = (this->m_extra_data->c * arc.m_extra_data->a - - this->m_extra_data->a * arc.m_extra_data->c) / denom; - n_ys = 1; - } - } - else { - // Compute the x-coordinates of the intersection points. - n_xs = compute_resultant_roots(nt_traits, - m_alg_r, m_alg_s, m_alg_t, - m_alg_u, m_alg_v, m_alg_w, - deg1, - arc.m_extra_data->a, - arc.m_extra_data->b, - arc.m_extra_data->c, - xs); - CGAL_assertion (n_xs <= 2); - - // Compute the y-coordinates of the intersection points. - n_ys = compute_resultant_roots(nt_traits, - m_alg_s, m_alg_r, m_alg_t, - m_alg_v, m_alg_u, m_alg_w, - deg1, - arc.m_extra_data->b, - arc.m_extra_data->a, - arc.m_extra_data->c, - ys); - CGAL_assertion(n_ys <= 2); - } - } - else { - // Compute the x-coordinates of the intersection points. - n_xs = compute_resultant_roots(nt_traits, - this->m_r, this->m_s, this->m_t, - this->m_u, this->m_v, this->m_w, - deg1, - arc.m_r, arc.m_s, arc.m_t, - arc.m_u, arc.m_v, arc.m_w, - deg2, - xs); - CGAL_assertion(n_xs <= 4); - - // Compute the y-coordinates of the intersection points. - n_ys = compute_resultant_roots(nt_traits, - this->m_s, this->m_r, this->m_t, - this->m_v, this->m_u, this->m_w, - deg1, - arc.m_s, arc.m_r, arc.m_t, - arc.m_v, arc.m_u, arc.m_w, - deg2, - ys); - CGAL_assertion(n_ys <= 4); - } - - // Pair the coordinates of the intersection points. As the vectors of - // x and y-coordinates are sorted in ascending order, we output the - // intersection points in lexicographically ascending order. - unsigned int mult; - int i, j; - - if (arc.is_special_segment()) { - if ((n_xs == 0) || (n_ys == 0)) return; - - if ((n_xs == 1) && (n_ys == 1)) { - // Single intersection. - Conic_point_2 ip (xs[0], ys[0]); - - ip.set_generating_conic(m_id); - ip.set_generating_conic (arc.m_id); - - // In case the other curve is of degree 2, this is a tangency point. - mult = ((deg1 == 1) || is_special_segment()) ? 1 : 2; - inter_list.push_back(Intersection_point(ip, mult)); - } - else if ((n_xs == 1) && (n_ys == 2)) { - Conic_point_2 ip1(xs[0], ys[0]); - - ip1.set_generating_conic(m_id); - ip1.set_generating_conic(arc.m_id); - - inter_list.push_back(Intersection_point(ip1, 1)); - - Conic_point_2 ip2 (xs[0], ys[1]); - - ip2.set_generating_conic(m_id); - ip2.set_generating_conic(arc.m_id); - - inter_list.push_back(Intersection_point(ip2, 1)); - } - else if ((n_xs == 2) && (n_ys == 1)) { - Conic_point_2 ip1 (xs[0], ys[0]); - - ip1.set_generating_conic(m_id); - ip1.set_generating_conic (arc.m_id); - - inter_list.push_back(Intersection_point(ip1, 1)); - - Conic_point_2 ip2 (xs[1], ys[0]); - - ip2.set_generating_conic(m_id); - ip2.set_generating_conic(arc.m_id); - - inter_list.push_back(Intersection_point(ip2, 1)); - - } - else { - CGAL_assertion((n_xs == 2) && (n_ys == 2)); - - // The x-coordinates and the y-coordinates are given in ascending - // order. If the slope of the segment is positive, we pair the - // coordinates as is - otherwise, we swap the pairs. - int ind_first_y = 0, ind_second_y = 1; - - if (CGAL::sign(arc.m_extra_data->b) == CGAL::sign(arc.m_extra_data->a)) { - ind_first_y = 1; - ind_second_y = 0; - } - - Conic_point_2 ip1(xs[0], ys[ind_first_y]); - - ip1.set_generating_conic(m_id); - ip1.set_generating_conic(arc.m_id); - - inter_list.push_back(Intersection_point(ip1, 1)); - - Conic_point_2 ip2(xs[1], ys[ind_second_y]); - - ip2.set_generating_conic(m_id); - ip2.set_generating_conic(arc.m_id); - - inter_list.push_back(Intersection_point(ip2, 1)); - } - - return; - } - - for (i = 0; i < n_xs; ++i) { - for (j = 0; j < n_ys; ++j) { - if (is_on_supporting_conic (xs[i], ys[j]) && - arc.is_on_supporting_conic(xs[i], ys[j])) - { - // Create the intersection point and set its generating conics. - Conic_point_2 ip(xs[i], ys[j]); - - ip.set_generating_conic(m_id); - ip.set_generating_conic(arc.m_id); - - // Compute the multiplicity of the intersection point. - if (deg1 == 1 && deg2 == 1) mult = 1; - else mult = multiplicity_of_intersection_point(arc, ip); - - // Insert the intersection point to the output list. - inter_list.push_back(Intersection_point(ip, mult)); - } - } - } - } - /*! Compute the multiplicity of an intersection point. * \param arc The arc to intersect with. * \param p The intersection point. * \return The multiplicity of the intersection point. */ - unsigned int multiplicity_of_intersection_point(const Self& arc, + unsigned int multiplicity_of_intersection_point(const Self& xcv, const Point_2& p) const { - CGAL_assertion(! is_special_segment() || ! arc.is_special_segment()); + CGAL_assertion(! is_special_segment() || ! xcv.is_special_segment()); // Compare the slopes of the two arcs at p, using their first-order // partial derivatives. @@ -1247,7 +684,7 @@ private: Algebraic slope2_numer, slope2_denom; derive_by_x_at(p, 1, slope1_numer, slope1_denom); - arc.derive_by_x_at(p, 1, slope2_numer, slope2_denom); + xcv.derive_by_x_at(p, 1, slope2_numer, slope2_denom); if (CGAL::compare(slope1_numer*slope2_denom, slope2_numer*slope1_denom) != EQUAL) { @@ -1260,13 +697,13 @@ private: // The curves do not have a vertical slope at p. // Compare their second-order derivative by x: derive_by_x_at(p, 2, slope1_numer, slope1_denom); - arc.derive_by_x_at(p, 2, slope2_numer, slope2_denom); + xcv.derive_by_x_at(p, 2, slope2_numer, slope2_denom); } else { // Both curves have a vertical slope at p. // Compare their second-order derivative by y: derive_by_y_at(p, 2, slope1_numer, slope1_denom); - arc.derive_by_y_at(p, 2, slope2_numer, slope2_denom); + xcv.derive_by_y_at(p, 2, slope2_numer, slope2_denom); } if (CGAL::compare(slope1_numer*slope2_denom, @@ -1287,28 +724,28 @@ private: */ template std::ostream& operator<<(std::ostream& os, - const _Conic_x_monotone_arc_2& arc) + const _Conic_x_monotone_arc_2& xcv) { // Output the supporting conic curve. - os << "{" << CGAL::to_double(arc.r()) << "*x^2 + " - << CGAL::to_double(arc.s()) << "*y^2 + " - << CGAL::to_double(arc.t()) << "*xy + " - << CGAL::to_double(arc.u()) << "*x + " - << CGAL::to_double(arc.v()) << "*y + " - << CGAL::to_double(arc.w()) << "}"; + os << "{" << CGAL::to_double(xcv.r()) << "*x^2 + " + << CGAL::to_double(xcv.s()) << "*y^2 + " + << CGAL::to_double(xcv.t()) << "*xy + " + << CGAL::to_double(xcv.u()) << "*x + " + << CGAL::to_double(xcv.v()) << "*y + " + << CGAL::to_double(xcv.w()) << "}"; // Output the endpoints. - os << " : (" << CGAL::to_double(arc.source().x()) << "," - << CGAL::to_double(arc.source().y()) << ") "; + os << " : (" << CGAL::to_double(xcv.source().x()) << "," + << CGAL::to_double(xcv.source().y()) << ") "; - if (arc.orientation() == CLOCKWISE) os << "--cw-->"; - else if (arc.orientation() == COUNTERCLOCKWISE) os << "--ccw-->"; + if (xcv.orientation() == CLOCKWISE) os << "--cw-->"; + else if (xcv.orientation() == COUNTERCLOCKWISE) os << "--ccw-->"; else os << "--l-->"; - os << " (" << CGAL::to_double(arc.target().x()) << "," - << CGAL::to_double(arc.target().y()) << ")"; + os << " (" << CGAL::to_double(xcv.target().x()) << "," + << CGAL::to_double(xcv.target().y()) << ")"; - return (os); + return os; } } //namespace CGAL From c7ddd442746788b1d7e1ebc83c3db2281d6bc9b2 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Tue, 31 May 2022 20:48:23 +0300 Subject: [PATCH 026/105] Continued --- .../include/CGAL/Arr_conic_traits_2.h | 236 +++++++++++++++- .../CGAL/Arr_geometry_traits/Conic_arc_2.h | 252 ------------------ 2 files changed, 231 insertions(+), 257 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index e794c25c97f..e2f60532d11 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -2695,13 +2695,117 @@ public: return res_xcv; } - }; /*! Obtain a Trim_2 functor object. */ Trim_2 trim_2_object() const { return Trim_2(*this); } //@} + /// \name Extra functor definitions. + //@{ + + class Construct_bbox_2 { + protected: + using Traits = Arr_conic_traits_2; + + /*! The traits (in case it has state) */ + const Traits& m_traits; + + /*! Constructor + * \param traits the traits. + */ + Construct_bbox_2(const Traits& traits) : m_traits(traits) {} + + friend class Arr_conic_traits_2; + + public: + /*! Obtain a bounding box for the conic arc. + * \return The bounding box. + */ + Bbox_2 operator()(const X_monotone_curve_2& xcv) const { + CGAL_precondition(xcv.is_valid()); + + double x_min(0), y_min(0), x_max(0), y_max(0); + + if (xcv.is_full_conic()) { + // In case of a full conic (an ellipse or a circle), compute the + // horizontal and vertical tangency points and use them to bound the arc. + Alg_point_2 tan_ps[2]; + CGAL_assertion_code(int n_tan_ps); + + CGAL_assertion_code(n_tan_ps = vertical_tangency_points(xcv, tan_ps)); + CGAL_assertion(n_tan_ps == 2); + + if (CGAL::to_double(tan_ps[0].x()) < CGAL::to_double(tan_ps[1].x())) { + x_min = CGAL::to_double(tan_ps[0].x()); + x_max = CGAL::to_double(tan_ps[1].x()); + } + else { + x_min = CGAL::to_double(tan_ps[1].x()); + x_max = CGAL::to_double(tan_ps[0].x()); + } + + CGAL_assertion_code(n_tan_ps = xcv.horizontal_tangency_points(tan_ps)); + CGAL_assertion(n_tan_ps == 2); + + if (CGAL::to_double(tan_ps[0].y()) < CGAL::to_double(tan_ps[1].y())) { + y_min = CGAL::to_double(tan_ps[0].y()); + y_max = CGAL::to_double(tan_ps[1].y()); + } + else { + y_min = CGAL::to_double(tan_ps[1].y()); + y_max = CGAL::to_double(tan_ps[0].y()); + } + } + else { + // Use the source and target to initialize the exterme points. + bool source_left = + CGAL::to_double(xcv.source().x()) < CGAL::to_double(xcv.target().x()); + x_min = (source_left) ? + CGAL::to_double(xcv.source().x()) : + CGAL::to_double(xcv.target().x()); + x_max = source_left ? + CGAL::to_double(xcv.target().x()) : + CGAL::to_double(xcv.source().x()); + + bool source_down = + CGAL::to_double(xcv.source().y()) < CGAL::to_double(xcv.target().y()); + y_min = source_down ? + CGAL::to_double(xcv.source().y()) : + CGAL::to_double(xcv.target().y()); + y_max = source_down ? + CGAL::to_double(xcv.target().y()) : + CGAL::to_double(xcv.source().y()); + + // Go over the vertical tangency points and try to update the x-points. + Alg_point_2 tan_ps[2]; + auto n_tan_ps = vertical_tangency_points(xcv, tan_ps); + for (int i = 0; i < n_tan_ps; ++i) { + if (CGAL::to_double(tan_ps[i].x()) < x_min) + x_min = CGAL::to_double(tan_ps[i].x()); + if (CGAL::to_double(tan_ps[i].x()) > x_max) + x_max = CGAL::to_double(tan_ps[i].x()); + } + + // Go over the horizontal tangency points and try to update the y-points. + n_tan_ps = xcv.horizontal_tangency_points(tan_ps); + for (int i = 0; i < n_tan_ps; ++i) { + if (CGAL::to_double(tan_ps[i].y()) < y_min) + y_min = CGAL::to_double(tan_ps[i].y()); + if (CGAL::to_double(tan_ps[i].y()) > y_max) + y_max = CGAL::to_double(tan_ps[i].y()); + } + } + + // Return the resulting bounding box. + return Bbox_2(x_min, y_min, x_max, y_max); + } + }; + + /*! Obtain a Bbox_2 functor object. */ + Construct_bbox_2 bbox_2_object() const { return Construct_bbox_2(*this); } + //@} + /*! Set the properties of a conic arc (for the usage of the constructors). * \param rat_coeffs A vector of size 6, storing the rational coefficients * of x^2, y^2, xy, x, y and the free coefficient resp. @@ -3392,20 +3496,95 @@ public: return is_between_endpoints(xcv, p); } + /*! Find the vertical tangency points of the undelying conic. + * \param ps The output points of vertical tangency. + * This area must be allocated at the size of 2. + * \return The number of vertical tangency points. + */ + int conic_vertical_tangency_points(const Curve_2& cv, Alg_point_2* ps) const { + // In case the base conic is of degree 1 (and not 2), the arc has no + // vertical tangency points. + if (CGAL::sign(cv.s()) == ZERO) return 0; + + // We are interested in the x coordinates where the quadratic equation: + // s*y^2 + (t*x + v)*y + (r*x^2 + u*x + w) = 0 + // has a single solution (obviously if s = 0, there are no such points). + // We therefore demand that the discriminant of this equation is zero: + // (t*x + v)^2 - 4*s*(r*x^2 + u*x + w) = 0 + const Integer two(2); + const Integer four(4); + Algebraic xs[2]; + Nt_traits nt_traits; + + auto r = cv.r(); + auto s = cv.s(); + auto t = cv.t(); + auto u = cv.u(); + auto v = cv.v(); + auto w = cv.w(); + Algebraic* xs_end = m_nt_traits->solve_quadratic_equation(t*t - four*r*s, + two*t*v - four*s*u, + v*v - four*s*w, + xs); + auto n_xs = static_cast(xs_end - xs); + + // Find the y-coordinates of the vertical tangency points. + Algebraic ys[2]; + Algebraic* ys_end; + int n_ys; + + if (CGAL::sign(cv.t()) == ZERO) { + // The two vertical tangency points have the same y coordinate: + ys[0] = m_nt_traits->convert(-v) / m_nt_traits->convert(two*s); + n_ys = 1; + } + else { + ys_end = m_nt_traits->solve_quadratic_equation(four*r*s*s - s*t*t, + four*r*s*v - two*s*t*u, + r*v*v - t*u*v + + t*t*w, + ys); + n_ys = static_cast(ys_end - ys); + } + + // Pair the x and y coordinates and obtain the vertical tangency points. + int n(0); + + for (int i = 0; i < n_xs; ++i) { + if (n_ys == 1) { + ps[n++] = Point_2(xs[i], ys[0]); + } + else { + for (int j = 0; j < n_ys; ++j) { + if (CGAL::compare(m_nt_traits->convert(two*s) * ys[j], + -(m_nt_traits->convert(t) * xs[i] + + m_nt_traits->convert(v))) == EQUAL) + { + ps[n++] = Point_2(xs[i], ys[j]); + break; + } + } + } + } + + CGAL_assertion(n <= 2); + return n; + } + /*! Calculate the vertical tangency points of the arc. * \param vpts The vertical tangency points. * \pre The vpts vector should be allocated at the size of 2. * \return The number of vertical tangency points. */ - int vertical_tangency_points(const Curve_2& cv, Alg_point_2* vpts) const { + size_t vertical_tangency_points(const Curve_2& cv, Alg_point_2* vpts) const { // No vertical tangency points for line segments: if (cv.orientation() == COLLINEAR) return 0; // Calculate the vertical tangency points of the supporting conic. Alg_point_2 ps[2]; - auto n = cv.conic_vertical_tangency_points(ps); + auto n = conic_vertical_tangency_points(cv, ps); // Return only the points that are contained in the arc interior. - int m(0); + size_t m(0); for (int i = 0; i < n; ++i) { std::cout << ps[i] << std::endl; if (cv.is_full_conic() || is_strictly_between_endpoints(cv, ps[i])) @@ -3417,6 +3596,53 @@ public: return m; } + /*! Find the horizontal tangency points of the undelying conic. + * \param ps The output points of horizontal tangency. + * This area must be allocated at the size of 2. + * \return The number of horizontal tangency points. + */ + size_t conic_horizontal_tangency_points(const Curve_2& cv, Alg_point_2* ps) + const { + const Integer zero(0); + + // In case the base conic is of degree 1 (and not 2), the arc has no + // vertical tangency points. + if (CGAL::sign(cv.r()) == ZERO) return 0; + + // We are interested in the y coordinates were the quadratic equation: + // r*x^2 + (t*y + u)*x + (s*y^2 + v*y + w) = 0 + // has a single solution (obviously if r = 0, there are no such points). + // We therefore demand that the discriminant of this equation is zero: + // (t*y + u)^2 - 4*r*(s*y^2 + v*y + w) = 0 + const Integer two(2); + const Integer four(4); + Algebraic ys[2]; + + auto r = cv.r(); + auto s = cv.s(); + auto t = cv.t(); + auto u = cv.u(); + auto v = cv.v(); + auto w = cv.w(); + Algebraic* ys_end = m_nt_traits->solve_quadratic_equation(t*t - four*r*s, + two*t*u - four*r*v, + u*u - four*r*w, + ys); + auto n = static_cast(ys_end - ys); + + // Compute the x coordinates and construct the horizontal tangency points. + for (int i = 0; i < n; ++i) { + // Having computed y, x is the single solution to the quadratic equation + // above, and since its discriminant is 0, x is simply given by: + Algebraic x = -(m_nt_traits->convert(t)*ys[i] + m_nt_traits->convert(u)) / + m_nt_traits->convert(two*r); + ps[i] = Point_2(x, ys[i]); + } + + CGAL_assertion(n <= 2); + return n; + } + /*! Calculate the horizontal tangency points of the arc. * \param hpts The horizontal tangency points. * \pre The hpts vector should be allocated at the size of 2. @@ -3428,7 +3654,7 @@ public: // Calculate the horizontal tangency points of the conic. Alg_point_2 ps[2]; - int n = cv.conic_horizontal_tangency_points(ps); + int n = conic_horizontal_tangency_points(cv, ps); // Return only the points that are contained in the arc interior. int m = 0; diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h index 5f17cad0d82..99f7fd1913f 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h @@ -206,87 +206,6 @@ public: /*! Obtain the extra data. */ const Extra_data* extra_data() const { return m_extra_data; } - - /*! Obtain a bounding box for the conic arc. - * \return The bounding box. - */ - Bbox_2 bbox() const { - CGAL_precondition(is_valid()); - - double x_min(0), y_min(0), x_max(0), y_max(0); - - if (is_full_conic()) { - // In case of a full conic (an ellipse or a circle), compute the - // horizontal and vertical tangency points and use them to bound the arc. - Point_2 tan_ps[2]; - CGAL_assertion_code(int n_tan_ps); - - CGAL_assertion_code(n_tan_ps = vertical_tangency_points(tan_ps)); - CGAL_assertion(n_tan_ps == 2); - - if (CGAL::to_double(tan_ps[0].x()) < CGAL::to_double(tan_ps[1].x())) { - x_min = CGAL::to_double(tan_ps[0].x()); - x_max = CGAL::to_double(tan_ps[1].x()); - } - else { - x_min = CGAL::to_double(tan_ps[1].x()); - x_max = CGAL::to_double(tan_ps[0].x()); - } - - CGAL_assertion_code(n_tan_ps = horizontal_tangency_points(tan_ps)); - CGAL_assertion(n_tan_ps == 2); - - if (CGAL::to_double(tan_ps[0].y()) < CGAL::to_double(tan_ps[1].y())) { - y_min = CGAL::to_double(tan_ps[0].y()); - y_max = CGAL::to_double(tan_ps[1].y()); - } - else { - y_min = CGAL::to_double(tan_ps[1].y()); - y_max = CGAL::to_double(tan_ps[0].y()); - } - } - else { - // Use the source and target to initialize the exterme points. - bool source_left = - CGAL::to_double(m_source.x()) < CGAL::to_double(m_target.x()); - x_min = source_left ? - CGAL::to_double(m_source.x()) : CGAL::to_double(m_target.x()); - x_max = source_left ? - CGAL::to_double(m_target.x()) : CGAL::to_double(m_source.x()); - - bool source_down = - CGAL::to_double(m_source.y()) < CGAL::to_double(m_target.y()); - y_min = source_down ? - CGAL::to_double(m_source.y()) : CGAL::to_double(m_target.y()); - y_max = source_down ? - CGAL::to_double(m_target.y()) : CGAL::to_double(m_source.y()); - - // Go over the vertical tangency points and try to update the x-points. - Point_2 tan_ps[2]; - int n_tan_ps; - - n_tan_ps = vertical_tangency_points(tan_ps); - for (int i = 0; i < n_tan_ps; ++i) { - if (CGAL::to_double(tan_ps[i].x()) < x_min) - x_min = CGAL::to_double(tan_ps[i].x()); - if (CGAL::to_double(tan_ps[i].x()) > x_max) - x_max = CGAL::to_double(tan_ps[i].x()); - } - - // Go over the horizontal tangency points and try to update the y-points. - n_tan_ps = horizontal_tangency_points(tan_ps); - for (int i = 0; i < n_tan_ps; ++i) { - if (CGAL::to_double(tan_ps[i].y()) < y_min) - y_min = CGAL::to_double(tan_ps[i].y()); - if (CGAL::to_double(tan_ps[i].y()) > y_max) - y_max = CGAL::to_double(tan_ps[i].y()); - } - } - - // Return the resulting bounding box. - return Bbox_2(x_min, y_min, x_max, y_max); - } - //@} protected: @@ -374,177 +293,6 @@ public: return CGAL::sign(val); } -protected: - /*! Check whether the given point lies on the supporting conic of the arc. - * \param p The query point. - * \return true if p lies on the supporting conic; (false) otherwise. - */ - bool is_on_supporting_conic(const Point_2& p) const { - // Check whether p satisfies the conic equation. - // The point must satisfy: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0. - Nt_traits nt_traits; - const Algebraic val = (nt_traits.convert(m_r)*p.x() + - nt_traits.convert(m_t)*p.y() + - nt_traits.convert(m_u)) * p.x() + - (nt_traits.convert(m_s) * p.y() + nt_traits.convert(m_v)) * p.y() + - nt_traits.convert(m_w); - - return (CGAL::sign(val) == ZERO); - } - - /*! Find the vertical tangency points of the undelying conic. - * \param ps The output points of vertical tangency. - * This area must be allocated at the size of 2. - * \return The number of vertical tangency points. - */ - int conic_vertical_tangency_points(Point_2* ps) const { - // In case the base conic is of degree 1 (and not 2), the arc has no - // vertical tangency points. - if (CGAL::sign(m_s) == ZERO) return 0; - - // We are interested in the x coordinates where the quadratic equation: - // s*y^2 + (t*x + v)*y + (r*x^2 + u*x + w) = 0 - // has a single solution (obviously if s = 0, there are no such points). - // We therefore demand that the discriminant of this equation is zero: - // (t*x + v)^2 - 4*s*(r*x^2 + u*x + w) = 0 - const Integer two = 2; - const Integer four = 4; - Algebraic xs[2]; - Algebraic* xs_end; - int n_xs; - Nt_traits nt_traits; - - xs_end = nt_traits.solve_quadratic_equation(m_t*m_t - four*m_r*m_s, - two*m_t*m_v - four*m_s*m_u, - m_v*m_v - four*m_s*m_w, - xs); - n_xs = static_cast(xs_end - xs); - - // Find the y-coordinates of the vertical tangency points. - Algebraic ys[2]; - Algebraic* ys_end; - int n_ys; - - if (CGAL::sign(m_t) == ZERO) { - // The two vertical tangency points have the same y coordinate: - ys[0] = nt_traits.convert(-m_v) / nt_traits.convert(two*m_s); - n_ys = 1; - } - else { - ys_end = - nt_traits.solve_quadratic_equation(four*m_r*m_s*m_s - m_s*m_t*m_t, - four*m_r*m_s*m_v - two*m_s*m_t*m_u, - m_r*m_v*m_v - m_t*m_u*m_v + m_t*m_t*m_w, - ys); - n_ys = static_cast(ys_end - ys); - } - - // Pair the x and y coordinates and obtain the vertical tangency points. - int n(0); - - for (int i = 0; i < n_xs; ++i) { - if (n_ys == 1) { - ps[n] = Point_2(xs[i], ys[0]); - ++n; - } - else { - for (int j = 0; j < n_ys; ++j) { - if (CGAL::compare(nt_traits.convert(two*m_s) * ys[j], - -(nt_traits.convert(m_t) * xs[i] + - nt_traits.convert(m_v))) == EQUAL) - { - ps[n] = Point_2(xs[i], ys[j]); - ++n; - break; - } - } - } - } - - CGAL_assertion(n <= 2); - return n; - } - - /*! Find the horizontal tangency points of the undelying conic. - * \param ps The output points of horizontal tangency. - * This area must be allocated at the size of 2. - * \return The number of horizontal tangency points. - */ - int conic_horizontal_tangency_points(Point_2* ps) const { - const Integer zero(0); - - // In case the base conic is of degree 1 (and not 2), the arc has no - // vertical tangency points. - if (CGAL::sign(m_r) == ZERO) return 0; - - // We are interested in the y coordinates were the quadratic equation: - // r*x^2 + (t*y + u)*x + (s*y^2 + v*y + w) = 0 - // has a single solution (obviously if r = 0, there are no such points). - // We therefore demand that the discriminant of this equation is zero: - // (t*y + u)^2 - 4*r*(s*y^2 + v*y + w) = 0 - const Integer two = 2; - const Integer four = 4; - int n; - Algebraic ys[2]; - Algebraic* ys_end; - Nt_traits nt_traits; - - ys_end = nt_traits.solve_quadratic_equation(m_t*m_t - four*m_r*m_s, - two*m_t*m_u - four*m_r*m_v, - m_u*m_u - four*m_r*m_w, - ys); - n = static_cast(ys_end - ys); - - // Compute the x coordinates and construct the horizontal tangency points. - for (int i = 0; i < n; ++i) { - // Having computed y, x is the single solution to the quadratic equation - // above, and since its discriminant is 0, x is simply given by: - Algebraic x = -(nt_traits.convert(m_t)*ys[i] + nt_traits.convert(m_u)) / - nt_traits.convert(two*m_r); - ps[i] = Point_2(x, ys[i]); - } - - CGAL_assertion(n <= 2); - return n; - } - - /*! Solve the given quadratic equation: Ax^2 + B*x + C = 0. - * \param x_minus The root obtained from taking -sqrt(discriminant). - * \param x_plus The root obtained from taking -sqrt(discriminant). - * \return The number of disticnt solutions to the equation. - */ - int solve_quadratic_equation(const Algebraic& A, - const Algebraic& B, - const Algebraic& C, - Algebraic& x_minus, Algebraic& x_plus) const { - // Check if we actually have a linear equation. - if (CGAL::sign(A) == ZERO) { - if (CGAL::sign(B) == ZERO) return 0; - x_minus = x_plus = -C / B; - return 1; - } - - // Compute the discriminant and act according to its sign. - const Algebraic disc = B*B - 4*A*C; - Sign sign_disc = CGAL::sign(disc); - - // Check whether there are no real-valued solutions: - if (sign_disc == NEGATIVE) return 0; - else if (sign_disc == ZERO) { - // One distinct solution: - x_minus = x_plus = -B / (2*A); - return 1; - } - - // Compute the two distinct solutions: - Algebraic _2A = 2*A; - Nt_traits nt_traits; - Algebraic sqrt_disc = nt_traits.sqrt (disc); - - x_minus = -(B + sqrt_disc) / _2A; - x_plus = (sqrt_disc - B) / _2A; - return 2; - } //@} }; From 4083266a4d7aeaed7214209eb2076ef83f661cd3 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Tue, 7 Jun 2022 20:31:50 +0300 Subject: [PATCH 027/105] Added trully random colors. Fixed face handling. --- .../include/CGAL/draw_arrangement_2.h | 47 +++++++++++++------ 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h index 82270ff35f2..011b79896d7 100644 --- a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h +++ b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -39,10 +40,16 @@ public: //! void add_elements() { clear(); + m_visited.clear(); + + std::random_device rd; + m_rng.seed(rd()); + m_uni = std::uniform_int_distribution(0, 255); + if (m_arr.is_empty()) return; for (auto it = m_arr.unbounded_faces_begin(); it != m_arr.unbounded_faces_end(); ++it) - add_face(it, Face_const_handle()); + add_face(it); // Add edges that do not separe faces. for (auto it = m_arr.edges_begin(); it != m_arr.edges_end(); ++it) @@ -51,6 +58,8 @@ public: // Add all points for (auto it = m_arr.vertices_begin(); it != m_arr.vertices_end(); ++it) draw_point(it->point()); + + m_visited.clear(); } protected: @@ -98,7 +107,7 @@ protected: //! virtual void draw_region(Ccb_halfedge_const_circulator circ) { - CGAL::IO::Color color(std::rand()%256, std::rand()%256, std::rand()%256); + CGAL::IO::Color color(m_uni(m_rng), m_uni(m_rng), m_uni(m_rng)); this->face_begin(color); auto ext = find_smallest(circ); @@ -128,27 +137,25 @@ protected: virtual void draw_point(const Point& p) { this->add_point(p); } //! - void add_ccb(Ccb_halfedge_const_circulator circ, Face_const_handle parent) { - std::unordered_map visited; + void add_ccb(Ccb_halfedge_const_circulator circ) { auto face = circ->face(); auto curr = circ; do { auto new_face = curr->twin()->face(); - if ((new_face == face) || (new_face == parent)) continue; - if (visited.find(new_face) != visited.end()) continue; - visited[new_face] = true; - add_face(new_face, face); + if (m_visited.find(new_face) != m_visited.end()) continue; + m_visited[new_face] = true; + add_face(new_face); } while (++curr != circ); } //! - void add_face(Face_const_handle face, Face_const_handle parent) { + void add_face(Face_const_handle face) { for (auto it = face->inner_ccbs_begin(); it != face->inner_ccbs_end(); ++it) - add_ccb(*it, parent); + add_ccb(*it); for (auto it = face->outer_ccbs_begin(); it != face->outer_ccbs_end(); ++it) { - add_ccb(*it, parent); + add_ccb(*it); draw_region(*it); } } @@ -172,6 +179,12 @@ protected: protected: //! The arrangement to draw const Arr& m_arr; + + std::unordered_map m_visited; + + std::mt19937 m_rng; + std::uniform_int_distribution m_uni; // guaranteed unbiased + }; //! Basic viewer of a 2D arrangement. @@ -225,7 +238,9 @@ public: //! virtual void draw_region(Ccb_halfedge_const_circulator circ) { - CGAL::IO::Color color(std::rand()%256, std::rand()%256, std::rand()%256); + auto& uni = this->m_uni; + auto& rng = this->m_rng; + CGAL::IO::Color color(uni(rng), uni(rng), uni(rng)); this->face_begin(color); const auto* traits = this->m_arr.geometry_traits(); @@ -242,7 +257,9 @@ public: curr = curr->twin()->next(); std::vector polyline; - approx(curr->curve(), std::back_inserter(polyline), 10); + double density(10); + bool l2r = curr->direction() == ARR_LEFT_TO_RIGHT; + approx(std::back_inserter(polyline), density, curr->curve(), l2r); auto it = polyline.begin(); auto prev = it++; for (; it != polyline.end(); prev = it++) { @@ -260,8 +277,8 @@ public: const auto* traits = this->m_arr.geometry_traits(); auto approx = traits->approximate_2_object(); std::vector polyline; - approx(curve, std::back_inserter(polyline), 10); - + double density(10); + approx(std::back_inserter(polyline), density, curve); auto it = polyline.begin(); auto prev = it++; for (; it != polyline.end(); prev = it++) this->add_segment(*prev, *it); From 2282f9f0e5fdcf1801daf762c89e6317b0d230e0 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Tue, 7 Jun 2022 20:32:24 +0300 Subject: [PATCH 028/105] Continued. Fixed treating source and target vertices --- .../include/CGAL/Arr_conic_traits_2.h | 386 ++++++++++++------ 1 file changed, 265 insertions(+), 121 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index e2f60532d11..c29f2099068 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -1535,29 +1535,37 @@ public: /*! Obtain an approximation of an x-monotone curve. */ template - OutputIterator operator()(const X_monotone_curve_2& arc, OutputIterator oi, - double density = 1) const { + OutputIterator operator()(OutputIterator oi, double density, + const X_monotone_curve_2& arc, + bool l2r = true) const { if (arc.orientation() == COLLINEAR) - return approximate_segment(arc, oi, density); + return approximate_segment(oi, density, arc, l2r); CGAL::Sign sign_conic = CGAL::sign(4*arc.r()*arc.s() - arc.t()*arc.t()); if (sign_conic == POSITIVE) - return approximate_hyperbola(arc, oi, density); + return approximate_ellipse(oi, density, arc, l2r); if (sign_conic == NEGATIVE) - return approximate_ellipse(arc, oi, density); - return approximate_parabola(arc, oi, density); + return approximate_hyperbola(oi, density, arc, l2r); + return approximate_parabola(oi, density, arc, l2r); } private: /*! Handle segments. */ template - OutputIterator approximate_segment(const X_monotone_curve_2& arc, - OutputIterator oi, - double density = 1) const { - auto xs = CGAL::to_double(arc.source().x()); - auto ys = CGAL::to_double(arc.source().y()); - auto xt = CGAL::to_double(arc.target().x()); - auto yt = CGAL::to_double(arc.target().y()); + OutputIterator approximate_segment(OutputIterator oi, double density, + const X_monotone_curve_2& arc, + bool l2r) const { + // std::cout << "SEGMENT\n"; + auto min_vertex = m_traits.construct_min_vertex_2_object(); + auto max_vertex = m_traits.construct_max_vertex_2_object(); + const auto& src = (l2r) ? + min_vertex(arc) : max_vertex(arc); + const auto& trg = (l2r) ? + max_vertex(arc) : min_vertex(arc); + auto xs = CGAL::to_double(src.x()); + auto ys = CGAL::to_double(src.y()); + auto xt = CGAL::to_double(trg.x()); + auto yt = CGAL::to_double(trg.y()); *oi++ = Approximate_point_2(xs, ys); *oi++ = Approximate_point_2(xt, yt); return oi; @@ -1631,50 +1639,30 @@ public: * spans a unit length. */ template - OutputIterator approximate_ellipse(const X_monotone_curve_2& arc, - OutputIterator oi, - double density = 1) const { - auto xs = CGAL::to_double(arc.source().x()); - auto ys = CGAL::to_double(arc.source().y()); - auto xt = CGAL::to_double(arc.target().x()); - auto yt = CGAL::to_double(arc.target().y()); - if (arc.orientation() == CLOCKWISE) { - std::swap(xs, xt); - std::swap(ys, yt); - } - auto r = CGAL::to_double(arc.r()); - auto s = CGAL::to_double(arc.s()); - auto t = CGAL::to_double(arc.t()); - auto u = CGAL::to_double(arc.u()); - auto v = CGAL::to_double(arc.v()); - auto w = CGAL::to_double(arc.w()); - std::cout << r << "," << s << "," << t << "," << u << "," << v << "," << w - << std::endl; - std::cout << "curve: (" << xs << "," << ys - << ") => (" << xt << "," << yt << ")" - << std::endl; - // Compute the cos and sin of the rotation angle - // In case of a circle, cost == 1 and sint = 0 - double cost(1), sint(0); + OutputIterator approximate_ellipse(OutputIterator oi, double density, + const X_monotone_curve_2& arc, + bool l2r) const { + // std::cout << "ELLIPSE\n"; + auto min_vertex = m_traits.construct_min_vertex_2_object(); + auto max_vertex = m_traits.construct_max_vertex_2_object(); + const auto& src = (l2r) ? + min_vertex(arc) : max_vertex(arc); + const auto& trg = (l2r) ? + max_vertex(arc) : min_vertex(arc); + auto xs = CGAL::to_double(src.x()); + auto ys = CGAL::to_double(src.y()); + auto xt = CGAL::to_double(trg.x()); + auto yt = CGAL::to_double(trg.y()); + // std::cout << "curve: (" << xs << "," << ys + // << ") => (" << xt << "," << yt << ")" + // << std::endl; - if (r != s) { - auto tan_2t = t / (r - s); - auto cos_2t = std::sqrt(1 / (tan_2t*tan_2t + 1)); - cost = std::sqrt((1 + cos_2t) / 2); - sint = std::sqrt((1 - cos_2t) / 2); - } - std::cout << "sint, cost: " << sint << "," << cost << std::endl; - - // Compute the coefficients of the unrotated ellipse - auto r_m = r * cost*cost + t*cost*sint + s*sint*sint; - auto t_m = 0; - auto s_m = r * sint*sint - t*cost*sint + s*cost*cost; - auto u_m = u*cost + v*sint; - auto v_m = - u*sint + v*cost; - auto w_m = w; - - std::cout << r_m << "," << s_m << "," << t_m << "," - << u_m << "," << v_m << "," << w_m << std::endl; + double r_m, t_m, s_m, u_m, v_m, w_m; + double cost, sint; + inverse_transform(arc, r_m, s_m, t_m, u_m, v_m, w_m, cost, sint); + // std::cout << r_m << "," << s_m << "," << t_m << "," + // << u_m << "," << v_m << "," << w_m << std::endl; + // std::cout << "sint, cost: " << sint << "," << cost << std::endl; // Compute the center of the inversly rotated ellipse: auto cx_m = -u_m / (2*r_m); @@ -1684,80 +1672,217 @@ public: auto numerator = -4*w_m*r_m*s_m + s_m*u_m*u_m + r_m*v_m*v_m; auto a = std::sqrt(numerator / (4*r_m*r_m*s_m)); auto b = std::sqrt(numerator / (4*r_m*s_m*s_m)); - std::cout << "a, b: " << a << "," << b << std::endl; + // std::cout << "a, b: " << a << "," << b << std::endl; // Compute the center (cx,cy) of the ellipse, rotating back: auto cx = cx_m*cost - cy_m*sint; auto cy = cx_m*sint + cy_m*cost; - std::cout << "center: " << cx << "," << cy << std::endl; + // std::cout << "center: " << cx << "," << cy << std::endl; - // Compute the parameters ps and pt such that - // source == (x(ps),y(ps)), and - // target == (x(pt),y(pt)) + // Compute the parameters ts and tt such that + // source == (x(ts),y(ts)), and + // target == (x(tt),y(tt)) auto xds = xs - cx; auto yds = ys - cy; - auto ps = std::atan2(a*(cost*yds - sint*xds),b*(sint*yds + cost*xds)); - if (ps < 0) ps += 2*M_PI; + auto ts = std::atan2(a*(cost*yds - sint*xds),b*(sint*yds + cost*xds)); + if (ts < 0) ts += 2*M_PI; auto xdt = xt - cx; auto ydt = yt - cy; - auto pt = std::atan2(a*(cost*ydt - sint*xdt),b*(sint*ydt + cost*xdt)); - if (pt < 0) pt += 2*M_PI; - if (pt < ps) pt += 2*M_PI; - std::cout << "ps,pt: " << ps << "," << pt << std::endl; + auto tt = std::atan2(a*(cost*ydt - sint*xdt),b*(sint*ydt + cost*xdt)); + if (tt < 0) tt += 2*M_PI; + auto orient(arc.orientation()); + if (arc.source() != src) orient = CGAL::opposite(orient); + if (orient == COUNTERCLOCKWISE) { + if (tt < ts) tt += 2*M_PI; + } + else { + if (ts < tt) ts += 2*M_PI; + } + // std::cout << "ts,tt: " << ts << "," << tt << std::endl; namespace bm = boost::math; auto ratio = b/a; auto k = std::sqrt(1 - (ratio*ratio)); - auto ds = a*bm::ellint_2(k, ps); - auto dt = a*bm::ellint_2(k, pt); - std::cout << "ds,dt: " << ds << ", " << dt << std::endl; - auto len = dt - ds; - auto size = static_cast(len*density); - - auto delta = (pt - ps) / (size-1); - auto p(ps); + auto ds = a*bm::ellint_2(k, ts); + auto dt = a*bm::ellint_2(k, tt); + auto d = std::abs(dt - ds); + // std::cout << "d,ds,dt: " << d << "," << ds << ", " << dt << std::endl; + auto size = static_cast(d*density); + if (size == 0) size = 1; + auto delta_t = (tt - ts) / size; + auto t(ts); *oi++ = Approximate_point_2(xs, ys); - p += delta; - for (size_t i = 1; i < size-1; ++i) { - auto x = a*std::cos(p)*cost - b*std::sin(p)*sint + cx; - auto y = a*std::cos(p)*sint + b*std::sin(p)*cost + cy; - std::cout << "t, (x, y): " << t << ", (" << x << "," << y << ")" - << std::endl; - *oi++ = Approximate_point_2(x, y); - t += delta; + t += delta_t; + if (ts < tt) { + while (t < tt) { + oi = add_elliptic_point(oi, t, a, b, cost, sint, cx, cy); + t += delta_t; + } + } + else { + while (t > tt) { + oi = add_elliptic_point(oi, t, a, b, cost, sint, cx, cy); + t += delta_t; + } } *oi++ = Approximate_point_2(xt, yt); return oi; } + template + OutputIterator add_elliptic_point(OutputIterator oi, double t, + double a, double b, + double cost, double sint, + double cx, double cy) const { + auto x = a*std::cos(t)*cost - b*std::sin(t)*sint + cx; + auto y = a*std::cos(t)*sint + b*std::sin(t)*cost + cy; + // std::cout << "t,(x, y): " << t << ",(" << x << "," << y << ")" + // << std::endl; + *oi++ = Approximate_point_2(x, y); + return oi; + } + /*! Handle parabolas. */ template - OutputIterator approximate_parabola(const X_monotone_curve_2& arc, - OutputIterator oi, - double density = 1) const { - auto xs = CGAL::to_double(arc.source().x()); - auto ys = CGAL::to_double(arc.source().y()); - auto xt = CGAL::to_double(arc.target().x()); - auto yt = CGAL::to_double(arc.target().y()); - if (arc.orientation() == CLOCKWISE) { - std::swap(xs, xt); - std::swap(ys, yt); + OutputIterator approximate_parabola(OutputIterator oi, double density, + const X_monotone_curve_2& arc, + bool l2r) const { + // std::cout << "PARABOLA\n"; + auto min_vertex = m_traits.construct_min_vertex_2_object(); + auto max_vertex = m_traits.construct_max_vertex_2_object(); + const auto& src = (l2r) ? + min_vertex(arc) : max_vertex(arc); + const auto& trg = (l2r) ? + max_vertex(arc) : min_vertex(arc); + auto xs = CGAL::to_double(src.x()); + auto ys = CGAL::to_double(src.y()); + auto xt = CGAL::to_double(trg.x()); + auto yt = CGAL::to_double(trg.y()); + // std::cout << "curve: (" << xs << "," << ys + // << ") => (" << xt << "," << yt << ")" + // << std::endl; + + double r_m, t_m, s_m, u_m, v_m, w_m; + double cost, sint; + inverse_transform(arc, r_m, s_m, t_m, u_m, v_m, w_m, cost, sint); + // std::cout << r_m << "," << s_m << "," << t_m << "," + // << u_m << "," << v_m << "," << w_m << std::endl; + // std::cout << "sint, cost: " << sint << "," << cost << std::endl; + + // Compute the center of the inversly rotated ellipse: + auto cx_m = -u_m / (2*r_m); + auto cy_m = (u_m*u_m - 4*r_m*w_m) / (4*r_m*v_m); + + // Compute the center (cx,cy) of the ellipse, rotating back: + auto cx = cx_m*cost - cy_m*sint; + auto cy = cx_m*sint + cy_m*cost; + // std::cout << "center: " << cx << "," << cy << std::endl; + + // Transform the source and target + auto xs_t = xs*cost + ys*sint - cx_m; + auto ys_t = -xs*sint + ys*cost - cy_m; + auto xt_t = xt*cost + yt*sint - cx_m; + auto yt_t = -xt*sint + yt*cost - cy_m; + + auto a = -v_m/(4.0*r_m); + auto ts = xs_t/(2.0*a); + auto tt = xt_t/(2.0*a); + + // std::cout << "xs' = " << xs_t << "," << ys_t << std::endl; + // std::cout << "xt' = " << xt_t << "," << yt_t << std::endl; + // std::cout << "ts,tt = " << ts << "," << tt << std::endl; + + auto ds = parabolic_arc_length(ys_t, 2.0*std::abs(xs_t)); + auto dt = parabolic_arc_length(yt_t, 2.0*std::abs(xt_t)); + auto d = (CGAL::sign(xs_t) == CGAL::sign(xt_t)) ? + std::abs(ds - dt)/2.0 : (ds + dt)/2.0; + // std::cout << "d, ds, dt = " << d << ", " << ds << "," << dt << std::endl; + + auto t(ts); + auto size = static_cast(d*density); + if (size == 0) size = 1; + *oi++ = Approximate_point_2(xs, ys); + auto delta_t = (tt - ts) / size; + auto delta_d = d / size; + adjust(t, delta_t, delta_d, a, 1.0/(density*2.0)); + + if (ts < tt) { + while (t < tt) { + oi = add_parabolic_point(oi, t, a, cost, sint, cx, cy); + adjust(t, delta_t, delta_d, a, 1.0/(density*2.0)); + } } + else { + while (t > tt) { + oi = add_parabolic_point(oi, t, a, cost, sint, cx, cy); + adjust(t, delta_t, delta_d, a, 1.0/(density*2.0)); + } + } + *oi++ = Approximate_point_2(xt, yt); + return oi; + } + + template + OutputIterator add_parabolic_point(OutputIterator oi, double t, double a, + double cost, double sint, + double cx, double cy) const { + auto xt = 2.0*a*t; + auto yt = a*t*t; + auto x = xt*cost - yt*sint + cx; + auto y = xt*sint + yt*cost + cy; + // std::cout << "t,(x,y): " << t << ",(" << x << "," << y << ")" + // << std::endl; + *oi++ = Approximate_point_2(x, y); + return oi; + } + + void adjust(double& t, double delta_t, double delta_d, double a, + double e) const { +#if 1 + t += delta_t; +#else + auto xt_prev = 2.0*a*t; + auto yt_prev = a*t*t; + auto dt_prev = parabolic_arc_length(yt_prev, 2.0*std::abs(xt_prev)); + + double d_t(delta_t); + double d; + double s(1); + do { + std::cout << "t: " << t << std::endl; + t += d_t*s; + + auto xt = 2.0*a*t; + auto yt = a*t*t; + auto dt = parabolic_arc_length(yt, 2.0*std::abs(xt)); + d = (CGAL::sign(xt_prev) == CGAL::sign(xt)) ? + std::abs(dt - dt_prev)/2.0 : (dt + dt_prev)/2.0; + + if (std::abs(d - delta_d) <= e) break; + d_t /= 2.0; + s = (d > delta_d) ? -1 : 1; + } while (true); + std::cout << "d: " << d << "," << e << std::endl; +#endif + } + + void inverse_transform(const X_monotone_curve_2& arc, + double& r_m, double& s_m, double& t_m, + double& u_m, double& v_m, double& w_m, + double& cost, double& sint) const { auto r = CGAL::to_double(arc.r()); auto s = CGAL::to_double(arc.s()); auto t = CGAL::to_double(arc.t()); auto u = CGAL::to_double(arc.u()); auto v = CGAL::to_double(arc.v()); auto w = CGAL::to_double(arc.w()); - std::cout << r << "," << s << "," << t << "," << u << "," << v << "," << w - << std::endl; - std::cout << "curve: (" << xs << "," << ys - << ") => (" << xt << "," << yt << ")" - << std::endl; + // std::cout << r << "," << s << "," << t << "," << u << "," << v << "," << w + // << std::endl; // Compute the cos and sin of the rotation angle // In case of a circle, cost == 1 and sint = 0 - double cost(1), sint(0); + cost = 1.0; + sint = 0.0; if (r != s) { auto tan_2t = t / (r - s); @@ -1765,34 +1890,54 @@ public: cost = std::sqrt((1 + cos_2t) / 2); sint = std::sqrt((1 - cos_2t) / 2); } - std::cout << "sint, cost: " << sint << "," << cost << std::endl; - // Compute the coefficients of the unrotated ellipse - auto r_m = r * cost*cost + t*cost*sint + s*sint*sint; - auto t_m = 0; - auto s_m = r * sint*sint - t*cost*sint + s*cost*cost; - auto u_m = u*cost + v*sint; - auto v_m = - u*sint + v*cost; - auto w_m = w; + // Compute the coefficients of the unrotated parabola + r_m = r * cost*cost + t*cost*sint + s*sint*sint; + t_m = 0; + s_m = r * sint*sint - t*cost*sint + s*cost*cost; + u_m = u*cost + v*sint; + v_m = - u*sint + v*cost; + w_m = w; + } - std::cout << r_m << "," << s_m << "," << t_m << "," - << u_m << "," << v_m << "," << w_m << std::endl; - - *oi++ = Approximate_point_2(xs, ys); - *oi++ = Approximate_point_2(xt, yt); - return oi; + /*! The formula for the arc length of a parabola is: + * L = 1/2 * √(b^2+16⋅a^2) + b^2/(8*a) * ln((4*a+√(b^2+16⋅a^2))/b) + * where: + * L is the length of the parabola arc. + * a is the length along the parabola axis. + * b is the length perpendicular to the axis making a chord. + * + * --- + * / | \ + * / |a \ + * / | \ + * /---------\ + * / b \ + * + */ + double parabolic_arc_length(double a, double b) const { + auto b_sqr = b*b; + auto tmp = std::sqrt(b_sqr+16.0*a*a); + return tmp/2.0 + b_sqr*std::log((4.0*a + tmp)/b)/(8.0*a); } /*! Handle hyperbolas. */ template - OutputIterator approximate_hyperbola(const X_monotone_curve_2& arc, - OutputIterator oi, - double density = 1) const { - auto xs = CGAL::to_double(arc.source().x()); - auto ys = CGAL::to_double(arc.source().y()); - auto xt = CGAL::to_double(arc.target().x()); - auto yt = CGAL::to_double(arc.target().y()); + OutputIterator approximate_hyperbola(OutputIterator oi, double density, + const X_monotone_curve_2& arc, + bool l2r) const { + // std::cout << "HYPERBOLA\n"; + auto min_vertex = m_traits.construct_min_vertex_2_object(); + auto max_vertex = m_traits.construct_max_vertex_2_object(); + const auto& src = (l2r) ? + min_vertex(arc) : max_vertex(arc); + const auto& trg = (l2r) ? + max_vertex(arc) : min_vertex(arc); + auto xs = CGAL::to_double(src.x()); + auto ys = CGAL::to_double(src.y()); + auto xt = CGAL::to_double(trg.x()); + auto yt = CGAL::to_double(trg.y()); *oi++ = Approximate_point_2(xs, ys); *oi++ = Approximate_point_2(xt, yt); return oi; @@ -3586,7 +3731,6 @@ public: // Return only the points that are contained in the arc interior. size_t m(0); for (int i = 0; i < n; ++i) { - std::cout << ps[i] << std::endl; if (cv.is_full_conic() || is_strictly_between_endpoints(cv, ps[i])) vpts[m++] = ps[i]; } From e61d5eb52f3bbe6d83ac59fc240e6a7d34dcfd01 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Thu, 9 Jun 2022 19:20:49 +0300 Subject: [PATCH 029/105] Continued --- .../Arrangement_on_surface_2/conics.cpp | 14 - .../include/CGAL/Arr_conic_traits_2.h | 281 ++++++++++++++---- .../include/CGAL/draw_arrangement_2.h | 4 +- 3 files changed, 226 insertions(+), 73 deletions(-) diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conics.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conics.cpp index 3eea95f1127..b750fdf6ca3 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conics.cpp +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conics.cpp @@ -14,39 +14,28 @@ int main() { Arrangement arr(&traits); auto ctr_cv = traits.construct_curve_2_object(); -#if 0 // Insert a hyperbolic arc (C1), supported by the hyperbola y = 1/x // (or: xy - 1 = 0) with the endpoints (1/4, 4) and (2, 1/2). // The arc is counterclockwise oriented. insert(arr, ctr_cv(0, 0, 1, 0, 0, -1, CGAL::COUNTERCLOCKWISE, Point(Rational(1,4), 4), Point(2, Rational(1,2)))); -#endif -#if 0 // Insert a full ellipse (C2), which is (x/4)^2 + (y/2)^2 = 0 rotated by // phi = 36.87 degrees (such that sin(phi) = 0.6, cos(phi) = 0.8), // yielding: 58x^2 + 72y^2 - 48xy - 360 = 0. insert(arr, ctr_cv(58, 72, -48, 0, 0, -360)); -#endif -#if 0 // Insert the segment (C3) (1, 1) -- (0, -3). insert(arr, ctr_cv(Rat_segment(Rat_point(1, 1), Rat_point(0, -3)))); -#endif -#if 0 // Insert a circular arc (C4) supported by the circle x^2 + y^2 = 5^2, // with (-3, 4) and (4, 3) as its endpoints. We want the arc to be // clockwise-oriented, so it passes through (0, 5) as well. insert(arr, ctr_cv(Rat_point(-3, 4), Rat_point(0, 5), Rat_point(4, 3))); -#endif -#if 0 // Insert a full unit circle (C5) that is centered at (0, 4). insert(arr, ctr_cv(Rat_circle(Rat_point(0,4), 1))); -#endif -#if 1 // Insert a parabolic arc (C6) supported by the parabola y = -x^2 with // endpoints (-sqrt(3),-3) (~(-1.73,-3)) and (sqrt(2),-2) (~(1.41,-2)). // Since the x-coordinates of the endpoints cannot be acccurately represented, @@ -60,14 +49,11 @@ int main() { 0, 0, 0, 0, 1, 2); // the line: y = -2. insert(arr, c6); -#endif -#if 0 // Insert the right half of the circle centered at (4, 2.5) whose radius // is 1/2 (therefore its squared radius is 1/4) (C7). Rat_circle circ7(Rat_point(4, Rational(5,2)), Rational(1,4)); insert(arr, ctr_cv(circ7, CGAL::CLOCKWISE, Point(4, 3), Point(4, 2))); -#endif print_arrangement_size(arr); diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index c29f2099068..81f308a40d2 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -1594,11 +1594,11 @@ public: * ----------- + ------------ = 1 * 𝑎^2 𝑏^2 * We get: - * u′ + * -u′ * 𝐶𝑥′ = ---- * 2·r′ * - * v′ + * -v′ * 𝐶𝑦′ = ---- * 2·s′ * @@ -1629,8 +1629,8 @@ public: * 𝑥(𝛼) = a·𝑐𝑜𝑠(𝛼)·𝑐𝑜𝑠(𝜃) − b·𝑠𝑖𝑛(𝛼)·𝑠𝑖𝑛(𝜃) * 𝑦(𝛼) = a·𝑐𝑜𝑠(𝛼)·𝑠𝑖𝑛(𝜃) + b·𝑠𝑖𝑛(𝛼)·𝑐𝑜𝑠(𝜃) * - * To shift any equation from the center we add 𝐶𝑥 to the 𝑥 equation and 𝐶𝑦 - * to the 𝑦 equation. Therefore the equation of a Rotated Ellipse is: + * To shift from the center we add 𝐶𝑥 to the 𝑥(𝛼) and 𝐶𝑦 to 𝑦(𝛼). + * Therefore, the equations of a Rotated Ellipse are: * 𝑥(𝛼) = a·𝑐𝑜𝑠(𝛼)·𝑐𝑜𝑠(𝜃) − b·𝑠𝑖𝑛(𝛼)·𝑠𝑖𝑛(𝜃) + 𝐶𝑥 * 𝑦(𝛼) = a·𝑐𝑜𝑠(𝛼)·𝑠𝑖𝑛(𝜃) + b·𝑠𝑖𝑛(𝛼)·𝑐𝑜𝑠(𝜃) + 𝐶𝑦 * @@ -1659,7 +1659,7 @@ public: double r_m, t_m, s_m, u_m, v_m, w_m; double cost, sint; - inverse_transform(arc, r_m, s_m, t_m, u_m, v_m, w_m, cost, sint); + canonical_conic(arc, r_m, s_m, t_m, u_m, v_m, w_m, cost, sint); // std::cout << r_m << "," << s_m << "," << t_m << "," // << u_m << "," << v_m << "," << w_m << std::endl; // std::cout << "sint, cost: " << sint << "," << cost << std::endl; @@ -1668,17 +1668,17 @@ public: auto cx_m = -u_m / (2*r_m); auto cy_m = -v_m / (2*s_m); + // Compute the center (cx,cy) of the ellipse, rotating back: + auto cx = cx_m*cost - cy_m*sint; + auto cy = cx_m*sint + cy_m*cost; + // std::cout << "center: " << cx << "," << cy << std::endl; + // Compute the radi of the ellipse: auto numerator = -4*w_m*r_m*s_m + s_m*u_m*u_m + r_m*v_m*v_m; auto a = std::sqrt(numerator / (4*r_m*r_m*s_m)); auto b = std::sqrt(numerator / (4*r_m*s_m*s_m)); // std::cout << "a, b: " << a << "," << b << std::endl; - // Compute the center (cx,cy) of the ellipse, rotating back: - auto cx = cx_m*cost - cy_m*sint; - auto cy = cx_m*sint + cy_m*cost; - // std::cout << "center: " << cx << "," << cy << std::endl; - // Compute the parameters ts and tt such that // source == (x(ts),y(ts)), and // target == (x(tt),y(tt)) @@ -1734,15 +1734,17 @@ public: double a, double b, double cost, double sint, double cx, double cy) const { - auto x = a*std::cos(t)*cost - b*std::sin(t)*sint + cx; - auto y = a*std::cos(t)*sint + b*std::sin(t)*cost + cy; - // std::cout << "t,(x, y): " << t << ",(" << x << "," << y << ")" - // << std::endl; - *oi++ = Approximate_point_2(x, y); + auto x = a*std::cos(t)*cost - b*std::sin(t)*sint + cx; + auto y = a*std::cos(t)*sint + b*std::sin(t)*cost + cy; + // std::cout << "t,(x, y): " << t << ",(" << x << "," << y << ")" + // << std::endl; + *oi++ = Approximate_point_2(x, y); return oi; } /*! Handle parabolas. + * The arc-length closed form can be found here: + * https://www.vcalc.com/wiki/vCalc/Parabola+-+arc+length */ template OutputIterator approximate_parabola(OutputIterator oi, double density, @@ -1765,19 +1767,32 @@ public: double r_m, t_m, s_m, u_m, v_m, w_m; double cost, sint; - inverse_transform(arc, r_m, s_m, t_m, u_m, v_m, w_m, cost, sint); + canonical_conic(arc, r_m, s_m, t_m, u_m, v_m, w_m, cost, sint); // std::cout << r_m << "," << s_m << "," << t_m << "," // << u_m << "," << v_m << "," << w_m << std::endl; // std::cout << "sint, cost: " << sint << "," << cost << std::endl; - // Compute the center of the inversly rotated ellipse: - auto cx_m = -u_m / (2*r_m); - auto cy_m = (u_m*u_m - 4*r_m*w_m) / (4*r_m*v_m); + /* If the axis of the parabola is the 𝑌-axis, shift + * the parabola by 90, essentially, converting the + * parabola to one the axis of which is the 𝑋-axis, as the + * remaining code assume that the 𝑋-axis is the parabola axis. + * This is somehow inefficient, because we repeat the computation of + * cost, sint, r_m,..., and w_m. An alternative, is to add code that + * directly handles the case where the conjugate axis is the 𝑌-axis. + */ + if (s_m == 0) { + // Shift phase: + auto tmp(cost); + cost = sint; + sint = -tmp; - // Compute the center (cx,cy) of the ellipse, rotating back: - auto cx = cx_m*cost - cy_m*sint; - auto cy = cx_m*sint + cy_m*cost; - // std::cout << "center: " << cx << "," << cy << std::endl; + // Recompute: + inverse_conic(arc, cost, sint, r_m, s_m, t_m, u_m, v_m, w_m); + } + + // Compute the center of the inversly rotated parabola: + double cx_m = -u_m / (2*r_m); + double cy_m = (u_m*u_m - 4*r_m*w_m) / (4*r_m*v_m); // Transform the source and target auto xs_t = xs*cost + ys*sint - cx_m; @@ -1788,7 +1803,6 @@ public: auto a = -v_m/(4.0*r_m); auto ts = xs_t/(2.0*a); auto tt = xt_t/(2.0*a); - // std::cout << "xs' = " << xs_t << "," << ys_t << std::endl; // std::cout << "xt' = " << xt_t << "," << yt_t << std::endl; // std::cout << "ts,tt = " << ts << "," << tt << std::endl; @@ -1799,6 +1813,11 @@ public: std::abs(ds - dt)/2.0 : (ds + dt)/2.0; // std::cout << "d, ds, dt = " << d << ", " << ds << "," << dt << std::endl; + // Compute the center (cx,cy) of the ellipse, rotating back: + auto cx = cx_m*cost - cy_m*sint; + auto cy = cx_m*sint + cy_m*cost; + // std::cout << "center: " << cx << "," << cy << std::endl; + auto t(ts); auto size = static_cast(d*density); if (size == 0) size = 1; @@ -1867,39 +1886,6 @@ public: #endif } - void inverse_transform(const X_monotone_curve_2& arc, - double& r_m, double& s_m, double& t_m, - double& u_m, double& v_m, double& w_m, - double& cost, double& sint) const { - auto r = CGAL::to_double(arc.r()); - auto s = CGAL::to_double(arc.s()); - auto t = CGAL::to_double(arc.t()); - auto u = CGAL::to_double(arc.u()); - auto v = CGAL::to_double(arc.v()); - auto w = CGAL::to_double(arc.w()); - // std::cout << r << "," << s << "," << t << "," << u << "," << v << "," << w - // << std::endl; - // Compute the cos and sin of the rotation angle - // In case of a circle, cost == 1 and sint = 0 - cost = 1.0; - sint = 0.0; - - if (r != s) { - auto tan_2t = t / (r - s); - auto cos_2t = std::sqrt(1 / (tan_2t*tan_2t + 1)); - cost = std::sqrt((1 + cos_2t) / 2); - sint = std::sqrt((1 - cos_2t) / 2); - } - - // Compute the coefficients of the unrotated parabola - r_m = r * cost*cost + t*cost*sint + s*sint*sint; - t_m = 0; - s_m = r * sint*sint - t*cost*sint + s*cost*cost; - u_m = u*cost + v*sint; - v_m = - u*sint + v*cost; - w_m = w; - } - /*! The formula for the arc length of a parabola is: * L = 1/2 * √(b^2+16⋅a^2) + b^2/(8*a) * ln((4*a+√(b^2+16⋅a^2))/b) * where: @@ -1938,10 +1924,191 @@ public: auto ys = CGAL::to_double(src.y()); auto xt = CGAL::to_double(trg.x()); auto yt = CGAL::to_double(trg.y()); + // std::cout << "curve: (" << xs << "," << ys + // << ") => (" << xt << "," << yt << ")" + // << std::endl; + + double r_m, t_m, s_m, u_m, v_m, w_m; + double cost, sint; + // If the hyperbola conjugate axis is the Y-axis, add + canonical_conic(arc, r_m, s_m, t_m, u_m, v_m, w_m, cost, sint); + // std::cout << r_m << "," << s_m << "," << t_m << "," + // << u_m << "," << v_m << "," << w_m << std::endl; + + // Compute the center of the inversly rotated ellipse: + auto cx_m = -u_m / (2*r_m); + auto cy_m = -v_m / (2*s_m); + + // Transform the source and target + auto xs_t = xs*cost + ys*sint - cx_m; + auto ys_t = -xs*sint + ys*cost - cy_m; + auto xt_t = xt*cost + yt*sint - cx_m; + auto yt_t = -xt*sint + yt*cost - cy_m; + + auto numerator = -4*w_m*r_m*s_m + s_m*u_m*u_m + r_m*v_m*v_m; + auto a_sqr = numerator / (4*r_m*r_m*s_m); + auto b_sqr = -numerator / (4*r_m*s_m*s_m); + + /* If the conjugate axis of the canonical hyperbula is the 𝑌-axis, shift + * the canonical hyperbula by 90, essentially, converting the canonical + * hyperbula to one the conjugate axis of which is the 𝑋-axis, as the + * remaining code assume that the conjugate axis is the 𝑋-axis. + * This is somehow inefficient, because we repeat the computation of + * cost, sint, r_m,...,w_m, cx_m, ...a_sqr, and b_sqr. An alternative, is + * to add code that directly handles the case where the conjugate axis + * is the 𝑌-axis. Here, + * 1. a_sqr = -a_sqr, b_sqr = -b_sqr, and + * 2. x(t),y(t) = a*sinh(t), b*cosh(t) + */ + if (a_sqr < 0) { + // Shift phase: + auto tmp(cost); + cost = sint; + sint = -tmp; + + // Recompute: + inverse_conic(arc, cost, sint, r_m, s_m, t_m, u_m, v_m, w_m); + cx_m = -u_m / (2*r_m); + cy_m = -v_m / (2*s_m); + xs_t = xs*cost + ys*sint - cx_m; + ys_t = -xs*sint + ys*cost - cy_m; + xt_t = xt*cost + yt*sint - cx_m; + yt_t = -xt*sint + yt*cost - cy_m; + numerator = -4*w_m*r_m*s_m + s_m*u_m*u_m + r_m*v_m*v_m; + a_sqr = numerator / (4*r_m*r_m*s_m); + b_sqr = -numerator / (4*r_m*s_m*s_m); + } + // std::cout << "sint, cost: " << sint << "," << cost << std::endl; + // std::cout << "xs_t,ys_t: " << xs_t << "," << ys_t << std::endl; + // std::cout << "xt_t,yt_t: " << xt_t << "," << yt_t << std::endl; + + // Compute the center (cx,cy) of the hyperbola, rotating back: + auto cx = cx_m*cost - cy_m*sint; + auto cy = cx_m*sint + cy_m*cost; + // std::cout << "center: " << cx << "," << cy << std::endl; + + auto a = std::sqrt(a_sqr); + auto b = std::sqrt(b_sqr); + + // We use the parametric representation x(t),y(t) = a*cosh(t), b*sinh(t) + // cosh(t) = (e^t + e^(-t))/2 + // sinh(t) = (e^t - e^(-t))/2 + // Compute the parameters ts and tt such that + // source == (x(ts),y(ts)), and + // target == (x(tt),y(tt)) + // Compute the radi of the hyperbola: + auto ts = std::asinh(ys_t/b); + auto tt = std::asinh(yt_t/b); + assert(std::signbit(xs_t) == std::signbit(xt_t)); + // std::cout << "a, b: " << a << "," << b << std::endl; + // std::cout << "ts, tt: " << ts << "," << tt << std::endl; + + if (std::signbit(xs_t)) a = -a; + + auto t(ts); + auto size = static_cast(density); + if (size == 0) size = 1; *oi++ = Approximate_point_2(xs, ys); + auto delta_t = (tt - ts) / size; + t += delta_t; + + if (ts < tt) { + while (t < tt) { + oi = add_hyperbolic_point(oi, t, a, b, cost, sint, cx, cy); + t += delta_t; + } + } + else { + while (t > tt) { + oi = add_hyperbolic_point(oi, t, a, b, cost, sint, cx, cy); + t += delta_t; + } + } *oi++ = Approximate_point_2(xt, yt); return oi; } + + template + OutputIterator add_hyperbolic_point(OutputIterator oi, double t, + double a, double b, + double cost, double sint, + double cx, double cy) const { + auto xt = a * std::cosh(t); + auto yt = b * std::sinh(t); + + auto x = xt*cost - yt*sint + cx; + auto y = xt*sint + yt*cost + cy; + // std::cout << "t,(x,y): " << t << ",(" << x << "," << y << ")" + // << std::endl; + *oi++ = Approximate_point_2(x, y); + return oi; + } + + /*! Obtain (i) the rotation that yields the given conic arc when applied + * to the canonical arc, and (ii) the canonical arc. + * \param[in] arc the given arc + * \param[out] r_m the coefficients of the canonical conic. + * \param[out] s_m + * \param[out] t_m + * \param[out] u_m + * \param[out] v_m + * \param[out] w_m + * \param[out] cost the cosine of the rotation angle. + * \param[out] sint the sine of the rotation angle. + */ + void canonical_conic(const X_monotone_curve_2& arc, + double& r_m, double& s_m, double& t_m, + double& u_m, double& v_m, double& w_m, + double& cost, double& sint) const { + auto r = CGAL::to_double(arc.r()); + auto s = CGAL::to_double(arc.s()); + auto t = CGAL::to_double(arc.t()); + auto u = CGAL::to_double(arc.u()); + auto v = CGAL::to_double(arc.v()); + auto w = CGAL::to_double(arc.w()); + // std::cout << r << "," << s << "," << t << "," + // << u << "," << v << "," << w << std::endl; + + // Compute the cos and sin of the rotation angle + // This eliminates the t coefficinet (which multiplies x·y). + cost = 1.0; + sint = 0.0; + + double cos_2t; + if (r != s) { + auto tan_2t = t / (r - s); + cos_2t = std::sqrt(1 / (tan_2t*tan_2t + 1)); + } + else if (r != 0) cos_2t = 1; + else cos_2t = 0; + + cost = std::sqrt((1 + cos_2t) / 2); + sint = std::sqrt((1 - cos_2t) / 2); + + inverse_conic(arc, cost, sint, r_m, s_m, t_m, u_m, v_m, w_m); + } + + /*! Apply the inverse of the rotation given by the sin and cosine of the + * rotation angle to the given conic arc. + */ + void inverse_conic(const X_monotone_curve_2& arc, + double cost, double sint, + double& r_m, double& s_m, double& t_m, + double& u_m, double& v_m, double& w_m) const { + auto r = CGAL::to_double(arc.r()); + auto s = CGAL::to_double(arc.s()); + auto t = CGAL::to_double(arc.t()); + auto u = CGAL::to_double(arc.u()); + auto v = CGAL::to_double(arc.v()); + auto w = CGAL::to_double(arc.w()); + + r_m = r * cost*cost + t*cost*sint + s*sint*sint; + t_m = 0; + s_m = r * sint*sint - t*cost*sint + s*cost*cost; + u_m = u*cost + v*sint; + v_m = - u*sint + v*cost; + w_m = w; + } }; /*! Obtain an Approximate_2 functor object. */ diff --git a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h index 011b79896d7..33fd1b03d45 100644 --- a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h +++ b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h @@ -34,7 +34,8 @@ public: const char* title = "2D Arrangement Basic Viewer") : // First draw: vertices; edges, faces; multi-color; no inverse normal Base(parent, title, true, true, true, false, false), - m_arr(arr) + m_arr(arr), + m_uni(0, 255) {} //! @@ -44,7 +45,6 @@ public: std::random_device rd; m_rng.seed(rd()); - m_uni = std::uniform_int_distribution(0, 255); if (m_arr.is_empty()) return; for (auto it = m_arr.unbounded_faces_begin(); From bb6c56c45c3c598e3526350038d6ba66dde3f651 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Sat, 11 Jun 2022 19:57:18 +0300 Subject: [PATCH 030/105] eaned up --- .../examples/Arrangement_on_surface_2/conics.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conics.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conics.cpp index b750fdf6ca3..9f700c55ce7 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conics.cpp +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conics.cpp @@ -47,7 +47,6 @@ int main() { 0, 0, 0, 0, 1, 3, // the line: y = -3. Point(1.41, -2), // approximation of the target. 0, 0, 0, 0, 1, 2); // the line: y = -2. - insert(arr, c6); // Insert the right half of the circle centered at (4, 2.5) whose radius From 3f8b2501ad0a6db60c73c45ac7d26987c8cafdd2 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Sat, 11 Jun 2022 19:58:48 +0300 Subject: [PATCH 031/105] Fixed x- and y- major parabolas --- .../include/CGAL/Arr_conic_traits_2.h | 88 +++++++++++-------- 1 file changed, 52 insertions(+), 36 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index 81f308a40d2..2b266ff9dec 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -1668,17 +1668,34 @@ public: auto cx_m = -u_m / (2*r_m); auto cy_m = -v_m / (2*s_m); + // Compute the radi of the ellipse: + auto numerator = -4*w_m*r_m*s_m + s_m*u_m*u_m + r_m*v_m*v_m; + auto a_sqr = numerator / (4*r_m*r_m*s_m); + auto b_sqr = numerator / (4*r_m*s_m*s_m); + if (a_sqr < 0) { + // Shift phase: + auto tmp(cost); + cost = sint; + sint = -tmp; + + // Recompute: + inverse_conic(arc, cost, sint, r_m, s_m, t_m, u_m, v_m, w_m); + cx_m = -u_m / (2*r_m); + cy_m = -v_m / (2*s_m); + numerator = -4*w_m*r_m*s_m + s_m*u_m*u_m + r_m*v_m*v_m; + a_sqr = numerator / (4*r_m*r_m*s_m); + b_sqr = -numerator / (4*r_m*s_m*s_m); + } + + auto a = std::sqrt(a_sqr); + auto b = std::sqrt(b_sqr); + // std::cout << "a, b: " << a << "," << b << std::endl; + // Compute the center (cx,cy) of the ellipse, rotating back: auto cx = cx_m*cost - cy_m*sint; auto cy = cx_m*sint + cy_m*cost; // std::cout << "center: " << cx << "," << cy << std::endl; - // Compute the radi of the ellipse: - auto numerator = -4*w_m*r_m*s_m + s_m*u_m*u_m + r_m*v_m*v_m; - auto a = std::sqrt(numerator / (4*r_m*r_m*s_m)); - auto b = std::sqrt(numerator / (4*r_m*s_m*s_m)); - // std::cout << "a, b: " << a << "," << b << std::endl; - // Compute the parameters ts and tt such that // source == (x(ts),y(ts)), and // target == (x(tt),y(tt)) @@ -1768,9 +1785,6 @@ public: double r_m, t_m, s_m, u_m, v_m, w_m; double cost, sint; canonical_conic(arc, r_m, s_m, t_m, u_m, v_m, w_m, cost, sint); - // std::cout << r_m << "," << s_m << "," << t_m << "," - // << u_m << "," << v_m << "," << w_m << std::endl; - // std::cout << "sint, cost: " << sint << "," << cost << std::endl; /* If the axis of the parabola is the 𝑌-axis, shift * the parabola by 90, essentially, converting the @@ -1789,10 +1803,16 @@ public: // Recompute: inverse_conic(arc, cost, sint, r_m, s_m, t_m, u_m, v_m, w_m); } + // std::cout << r_m << "," << s_m << "," << t_m << "," + // << u_m << "," << v_m << "," << w_m << std::endl; + // std::cout << "sint, cost: " << sint << "," << cost << std::endl; // Compute the center of the inversly rotated parabola: - double cx_m = -u_m / (2*r_m); - double cy_m = (u_m*u_m - 4*r_m*w_m) / (4*r_m*v_m); + // double cx_m = -u_m / (2*r_m); + // double cy_m = (u_m*u_m - 4*r_m*w_m) / (4*r_m*v_m); + double cx_m = (v_m*v_m - 4*s_m*w_m) / (4*s_m*u_m); + double cy_m = -v_m / (2*s_m); + // std::cout << "cx_m, cy_m: " << cx_m << "," << cy_m << std::endl; // Transform the source and target auto xs_t = xs*cost + ys*sint - cx_m; @@ -1800,16 +1820,16 @@ public: auto xt_t = xt*cost + yt*sint - cx_m; auto yt_t = -xt*sint + yt*cost - cy_m; - auto a = -v_m/(4.0*r_m); - auto ts = xs_t/(2.0*a); - auto tt = xt_t/(2.0*a); + auto a = -u_m/(4.0*s_m); + auto ts = ys_t/(2.0*a); + auto tt = yt_t/(2.0*a); // std::cout << "xs' = " << xs_t << "," << ys_t << std::endl; // std::cout << "xt' = " << xt_t << "," << yt_t << std::endl; // std::cout << "ts,tt = " << ts << "," << tt << std::endl; - auto ds = parabolic_arc_length(ys_t, 2.0*std::abs(xs_t)); - auto dt = parabolic_arc_length(yt_t, 2.0*std::abs(xt_t)); - auto d = (CGAL::sign(xs_t) == CGAL::sign(xt_t)) ? + auto ds = parabolic_arc_length(xs_t, 2.0*std::abs(ys_t)); + auto dt = parabolic_arc_length(xt_t, 2.0*std::abs(yt_t)); + auto d = (CGAL::sign(ys_t) == CGAL::sign(yt_t)) ? std::abs(ds - dt)/2.0 : (ds + dt)/2.0; // std::cout << "d, ds, dt = " << d << ", " << ds << "," << dt << std::endl; @@ -1846,8 +1866,8 @@ public: OutputIterator add_parabolic_point(OutputIterator oi, double t, double a, double cost, double sint, double cx, double cy) const { - auto xt = 2.0*a*t; - auto yt = a*t*t; + auto xt = a*t*t; + auto yt = 2.0*a*t; auto x = xt*cost - yt*sint + cx; auto y = xt*sint + yt*cost + cy; // std::cout << "t,(x,y): " << t << ",(" << x << "," << y << ")" @@ -1902,6 +1922,8 @@ public: * */ double parabolic_arc_length(double a, double b) const { + if (a == 0) return b; + if (b == 0) return a; auto b_sqr = b*b; auto tmp = std::sqrt(b_sqr+16.0*a*a); return tmp/2.0 + b_sqr*std::log((4.0*a + tmp)/b)/(8.0*a); @@ -1935,16 +1957,6 @@ public: // std::cout << r_m << "," << s_m << "," << t_m << "," // << u_m << "," << v_m << "," << w_m << std::endl; - // Compute the center of the inversly rotated ellipse: - auto cx_m = -u_m / (2*r_m); - auto cy_m = -v_m / (2*s_m); - - // Transform the source and target - auto xs_t = xs*cost + ys*sint - cx_m; - auto ys_t = -xs*sint + ys*cost - cy_m; - auto xt_t = xt*cost + yt*sint - cx_m; - auto yt_t = -xt*sint + yt*cost - cy_m; - auto numerator = -4*w_m*r_m*s_m + s_m*u_m*u_m + r_m*v_m*v_m; auto a_sqr = numerator / (4*r_m*r_m*s_m); auto b_sqr = -numerator / (4*r_m*s_m*s_m); @@ -1954,7 +1966,7 @@ public: * hyperbula to one the conjugate axis of which is the 𝑋-axis, as the * remaining code assume that the conjugate axis is the 𝑋-axis. * This is somehow inefficient, because we repeat the computation of - * cost, sint, r_m,...,w_m, cx_m, ...a_sqr, and b_sqr. An alternative, is + * cost, sint, r_m,...,w_m, a_sqr, and b_sqr. An alternative, is * to add code that directly handles the case where the conjugate axis * is the 𝑌-axis. Here, * 1. a_sqr = -a_sqr, b_sqr = -b_sqr, and @@ -1968,17 +1980,21 @@ public: // Recompute: inverse_conic(arc, cost, sint, r_m, s_m, t_m, u_m, v_m, w_m); - cx_m = -u_m / (2*r_m); - cy_m = -v_m / (2*s_m); - xs_t = xs*cost + ys*sint - cx_m; - ys_t = -xs*sint + ys*cost - cy_m; - xt_t = xt*cost + yt*sint - cx_m; - yt_t = -xt*sint + yt*cost - cy_m; numerator = -4*w_m*r_m*s_m + s_m*u_m*u_m + r_m*v_m*v_m; a_sqr = numerator / (4*r_m*r_m*s_m); b_sqr = -numerator / (4*r_m*s_m*s_m); } // std::cout << "sint, cost: " << sint << "," << cost << std::endl; + + // Compute the center of the inversly rotated ellipse: + auto cx_m = -u_m / (2*r_m); + auto cy_m = -v_m / (2*s_m); + + // Transform the source and target + auto xs_t = xs*cost + ys*sint - cx_m; + auto ys_t = -xs*sint + ys*cost - cy_m; + auto xt_t = xt*cost + yt*sint - cx_m; + auto yt_t = -xt*sint + yt*cost - cy_m; // std::cout << "xs_t,ys_t: " << xs_t << "," << ys_t << std::endl; // std::cout << "xt_t,yt_t: " << xt_t << "," << yt_t << std::endl; From 7988148710bac06be67237c303df103cc1dcad6f Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Sun, 19 Jun 2022 12:39:43 +0300 Subject: [PATCH 032/105] Cleaned up --- .../Arrangement_on_surface_2/conics.cpp | 3 +- .../include/CGAL/Arr_conic_traits_2.h | 359 +++-- .../CGAL/Arr_geometry_traits/Conic_arc_2.h | 1261 ++++++++++++++++- .../CGAL/Arr_geometry_traits/Conic_point_2.h | 37 +- .../Conic_x_monotone_arc_2.h | 333 +++-- .../include/CGAL/Surface_sweep_2_algorithms.h | 4 +- .../test/Surface_sweep_2/test_sweep_conic.cpp | 8 +- 7 files changed, 1739 insertions(+), 266 deletions(-) diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conics.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conics.cpp index 9f700c55ce7..5221db2a415 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conics.cpp +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conics.cpp @@ -2,10 +2,11 @@ // Constructing an arrangement of various conic arcs. #include -#include #ifdef CGAL_USE_CORE +#include + #include "arr_conics.h" #include "arr_print.h" diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index 2b266ff9dec..a21ea135aac 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -10,6 +10,7 @@ // // Author(s): Ron Wein // Waqar Khan +// Efi Fogel #ifndef CGAL_ARR_CONIC_TRAITS_2_H #define CGAL_ARR_CONIC_TRAITS_2_H @@ -26,7 +27,9 @@ #include #include #include +#include +#include #include #include @@ -35,6 +38,8 @@ #include #include #include +#include +#include namespace CGAL { @@ -82,10 +87,10 @@ public: typedef Arr_oblivious_side_tag Right_side_category; // Traits objects: - typedef _Conic_arc_2 Curve_2; - typedef _Conic_x_monotone_arc_2 X_monotone_curve_2; - typedef _Conic_point_2 Point_2; - typedef unsigned int Multiplicity; + typedef Conic_arc_2 Curve_2; + typedef Conic_x_monotone_arc_2 X_monotone_curve_2; + typedef Conic_point_2 Point_2; + typedef size_t Multiplicity; private: // Type definition for the intersection points mapping. @@ -102,7 +107,7 @@ private: } }; - typedef std::pair Intersection_point; + typedef std::pair Intersection_point; typedef std::list Intersection_list; typedef std::map Intersection_map; @@ -136,11 +141,11 @@ public: {} /*! Obtain the next conic index. */ - static unsigned int get_index() { + static size_t get_index() { #ifdef CGAL_NO_ATOMIC - static unsigned int index; + static size_t index; #else - static std::atomic index; + static std::atomic index; #endif return (++index); } @@ -270,8 +275,8 @@ public: * LARGER if y(p) > cv(x(p)), i.e. the point is above the curve; * EQUAL if p lies on the curve. */ - Comparison_result operator()(const Point_2& p, const X_monotone_curve_2& xcv) - const { + Comparison_result operator()(const Point_2& p, + const X_monotone_curve_2& xcv) const { auto cmp_y = m_traits.m_alg_kernel->compare_y_2_object(); if (xcv.is_vertical()) { @@ -439,20 +444,94 @@ public: } private: - /*! Compare to arcs immediately to the leftt of their intersection point. - * \param arc The compared arc. - * \param p The reference intersection point. - * \return The relative position of the arcs to the left of p. - * \pre Both arcs we compare are not vertical segments. - */ - Comparison_result compare_to_left(const X_monotone_curve_2& xcv1, - const X_monotone_curve_2& xcv2, - const Point_2& p) const { - CGAL_precondition(! xcv1.is_vertical() && ! xcv2.is_vertical()); + /*! Compare to arcs immediately to the leftt of their intersection point. + * \param arc The compared arc. + * \param p The reference intersection point. + * \return The relative position of the arcs to the left of p. + * \pre Both arcs we compare are not vertical segments. + */ + Comparison_result compare_to_left(const X_monotone_curve_2& xcv1, + const X_monotone_curve_2& xcv2, + const Point_2& p) const { + CGAL_precondition(! xcv1.is_vertical() && ! xcv2.is_vertical()); - // In case one arc is facing upwards and another facing downwards, it is - // clear that the one facing upward is above the one facing downwards. - if (m_traits.has_same_supporting_conic(xcv1, xcv2)) { + // In case one arc is facing upwards and another facing downwards, it is + // clear that the one facing upward is above the one facing downwards. + if (m_traits.has_same_supporting_conic(xcv1, xcv2)) { + if (xcv1.test_flag(X_monotone_curve_2::FACING_UP) && + xcv2.test_flag(X_monotone_curve_2::FACING_DOWN)) + return LARGER; + else if (xcv1.test_flag(X_monotone_curve_2::FACING_DOWN) && + xcv2.test_flag(X_monotone_curve_2::FACING_UP)) + return SMALLER; + + // In this case the two arcs overlap. + CGAL_assertion(xcv1.facing_mask() == xcv2.facing_mask()); + + return EQUAL; + } + + // Compare the slopes of the two arcs at p, using their first-order + // partial derivatives. + Algebraic slope1_numer, slope1_denom; + Algebraic slope2_numer, slope2_denom; + + xcv1.derive_by_x_at(p, 1, slope1_numer, slope1_denom); + xcv2.derive_by_x_at(p, 1, slope2_numer, slope2_denom); + + // Check if any of the slopes is vertical. + const bool is_vertical_slope1 = (CGAL::sign (slope1_denom) == ZERO); + const bool is_vertical_slope2 = (CGAL::sign (slope2_denom) == ZERO); + + if (! is_vertical_slope1 && ! is_vertical_slope2) { + // The two derivatives at p are well-defined: use them to determine + // which arc is above the other (the one with a larger slope is below). + Comparison_result slope_res = CGAL::compare(slope2_numer*slope1_denom, + slope1_numer*slope2_denom); + + if (slope_res != EQUAL) return slope_res; + + // Use the second-order derivative. + xcv1.derive_by_x_at(p, 2, slope1_numer, slope1_denom); + xcv2.derive_by_x_at(p, 2, slope2_numer, slope2_denom); + + slope_res = CGAL::compare(slope1_numer*slope2_denom, + slope2_numer*slope1_denom); + + if (slope_res != EQUAL) return (slope_res); + + // Use the third-order derivative. + xcv1.derive_by_x_at(p, 3, slope1_numer, slope1_denom); + xcv2.derive_by_x_at(p, 3, slope2_numer, slope2_denom); + + slope_res = CGAL::compare(slope2_numer*slope1_denom, + slope1_numer*slope2_denom); + + // \todo Handle higher-order derivatives: + CGAL_assertion(slope_res != EQUAL); + + return slope_res; + } + else if (! is_vertical_slope2) { + // The first arc has a vertical slope at p: check whether it is + // facing upwards or downwards and decide accordingly. + CGAL_assertion(xcv1.facing_mask() != 0); + + return (xcv1.test_flag(X_monotone_curve_2::FACING_UP)) ? + LARGER : SMALLER; + } + else if (! is_vertical_slope1) { + // The second arc has a vertical slope at p_int: check whether it is + // facing upwards or downwards and decide accordingly. + CGAL_assertion(xcv2.facing_mask() != 0); + + return (xcv2.test_flag(X_monotone_curve_2::FACING_UP)) ? + SMALLER : LARGER; + } + + // The two arcs have vertical slopes at p_int: + // First check whether one is facing up and one down. In this case the + // comparison result is trivial. if (xcv1.test_flag(X_monotone_curve_2::FACING_UP) && xcv2.test_flag(X_monotone_curve_2::FACING_DOWN)) return LARGER; @@ -460,106 +539,34 @@ public: xcv2.test_flag(X_monotone_curve_2::FACING_UP)) return SMALLER; - // In this case the two arcs overlap. - CGAL_assertion(xcv1.facing_mask() == xcv2.facing_mask()); + // Compute the second-order derivative by y and act according to it. + xcv1.derive_by_y_at(p, 2, slope1_numer, slope1_denom); + xcv2.derive_by_y_at(p, 2, slope2_numer, slope2_denom); - return EQUAL; - } + Comparison_result slope_res = + CGAL::compare(slope2_numer*slope1_denom, slope1_numer*slope2_denom); - // Compare the slopes of the two arcs at p, using their first-order - // partial derivatives. - Algebraic slope1_numer, slope1_denom; - Algebraic slope2_numer, slope2_denom; + // If necessary, use the third-order derivative by y. + if (slope_res == EQUAL) { + // \todo Check this! + xcv1.derive_by_y_at(p, 3, slope1_numer, slope1_denom); + xcv2.derive_by_y_at(p, 3, slope2_numer, slope2_denom); - xcv1.derive_by_x_at(p, 1, slope1_numer, slope1_denom); - xcv2.derive_by_x_at(p, 1, slope2_numer, slope2_denom); - - // Check if any of the slopes is vertical. - const bool is_vertical_slope1 = (CGAL::sign (slope1_denom) == ZERO); - const bool is_vertical_slope2 = (CGAL::sign (slope2_denom) == ZERO); - - if (! is_vertical_slope1 && ! is_vertical_slope2) { - // The two derivatives at p are well-defined: use them to determine - // which arc is above the other (the one with a larger slope is below). - Comparison_result slope_res = CGAL::compare(slope2_numer*slope1_denom, - slope1_numer*slope2_denom); - - if (slope_res != EQUAL) return slope_res; - - // Use the second-order derivative. - xcv1.derive_by_x_at(p, 2, slope1_numer, slope1_denom); - xcv2.derive_by_x_at(p, 2, slope2_numer, slope2_denom); - - slope_res = CGAL::compare(slope1_numer*slope2_denom, - slope2_numer*slope1_denom); - - if (slope_res != EQUAL) return (slope_res); - - // Use the third-order derivative. - xcv1.derive_by_x_at(p, 3, slope1_numer, slope1_denom); - xcv2.derive_by_x_at(p, 3, slope2_numer, slope2_denom); - - slope_res = CGAL::compare(slope2_numer*slope1_denom, - slope1_numer*slope2_denom); + slope_res = + CGAL::compare(slope2_numer*slope1_denom, slope1_numer*slope2_denom); + } // \todo Handle higher-order derivatives: CGAL_assertion(slope_res != EQUAL); + // Check whether both are facing up. + if (xcv1.test_flag(X_monotone_curve_2::FACING_UP) && + xcv2.test_flag(X_monotone_curve_2::FACING_UP)) + return ((slope_res == LARGER) ? SMALLER : LARGER); + + // Both are facing down. return slope_res; } - else if (! is_vertical_slope2) { - // The first arc has a vertical slope at p: check whether it is - // facing upwards or downwards and decide accordingly. - CGAL_assertion(xcv1.facing_mask() != 0); - - return (xcv1.test_flag(X_monotone_curve_2::FACING_UP)) ? LARGER : SMALLER; - } - else if (! is_vertical_slope1) { - // The second arc has a vertical slope at p_int: check whether it is - // facing upwards or downwards and decide accordingly. - CGAL_assertion(xcv2.facing_mask() != 0); - - return (xcv2.test_flag(X_monotone_curve_2::FACING_UP)) ? SMALLER : LARGER; - } - - // The two arcs have vertical slopes at p_int: - // First check whether one is facing up and one down. In this case the - // comparison result is trivial. - if (xcv1.test_flag(X_monotone_curve_2::FACING_UP) && - xcv2.test_flag(X_monotone_curve_2::FACING_DOWN)) - return LARGER; - else if (xcv1.test_flag(X_monotone_curve_2::FACING_DOWN) && - xcv2.test_flag(X_monotone_curve_2::FACING_UP)) - return SMALLER; - - // Compute the second-order derivative by y and act according to it. - xcv1.derive_by_y_at(p, 2, slope1_numer, slope1_denom); - xcv2.derive_by_y_at(p, 2, slope2_numer, slope2_denom); - - Comparison_result slope_res = - CGAL::compare(slope2_numer*slope1_denom, slope1_numer*slope2_denom); - - // If necessary, use the third-order derivative by y. - if (slope_res == EQUAL) { - // \todo Check this! - xcv1.derive_by_y_at(p, 3, slope1_numer, slope1_denom); - xcv2.derive_by_y_at(p, 3, slope2_numer, slope2_denom); - - slope_res = - CGAL::compare(slope2_numer*slope1_denom, slope1_numer*slope2_denom); - } - - // \todo Handle higher-order derivatives: - CGAL_assertion(slope_res != EQUAL); - - // Check whether both are facing up. - if (xcv1.test_flag(X_monotone_curve_2::FACING_UP) && - xcv2.test_flag(X_monotone_curve_2::FACING_UP)) - return ((slope_res == LARGER) ? SMALLER : LARGER); - - // Both are facing down. - return slope_res; - } }; @@ -811,6 +818,86 @@ public: Equal_2 equal_2_object() const { return Equal_2(*this); } //@} + /// \name Functor definitions to handle boundaries + //@{ + + /*! A function object that obtains the parameter space of a geometric + * entity along the x-axis + */ + class Parameter_space_in_x_2 { + public: + /*! Obtains the parameter space at the end of a line along the x-axis. + * \param xcv the line + * \param ce the line end indicator: + * ARR_MIN_END - the minimal end of xc or + * ARR_MAX_END - the maximal end of xc + * \return the parameter space at the ce end of the line xcv. + * ARR_LEFT_BOUNDARY - the line approaches the identification arc from + * the right at the line left end. + * ARR_INTERIOR - the line does not approache the identification arc. + * ARR_RIGHT_BOUNDARY - the line approaches the identification arc from + * the left at the line right end. + */ + Arr_parameter_space operator()(const X_monotone_curve_2 & xcv, + Arr_curve_end ce) const { + CGAL_error_msg("Not implemented yet!"); + return ARR_INTERIOR; + } + + /*! Obtains the parameter space at a point along the x-axis. + * \param p the point. + * \return the parameter space at p. + */ + Arr_parameter_space operator()(const Point_2 ) const + { return ARR_INTERIOR; } + }; + + /*! Obtain a Parameter_space_in_x_2 function object */ + Parameter_space_in_x_2 parameter_space_in_x_2_object() const + { return Parameter_space_in_x_2(); } + + /*! A function object that obtains the parameter space of a geometric + * entity along the y-axis + */ + class Parameter_space_in_y_2 { + public: + /*! Obtains the parameter space at the end of a line along the y-axis . + * Note that if the line end coincides with a pole, then unless the line + * coincides with the identification arc, the line end is considered to + * be approaching the boundary, but not on the boundary. + * If the line coincides with the identification arc, it is assumed to + * be smaller than any other object. + * \param xcv the line + * \param ce the line end indicator: + * ARR_MIN_END - the minimal end of xc or + * ARR_MAX_END - the maximal end of xc + * \return the parameter space at the ce end of the line xcv. + * ARR_BOTTOM_BOUNDARY - the line approaches the south pole at the line + * left end. + * ARR_INTERIOR - the line does not approache a contraction point. + * ARR_TOP_BOUNDARY - the line approaches the north pole at the line + * right end. + */ + Arr_parameter_space operator()(const X_monotone_curve_2& xcv, + Arr_curve_end ce) const { + CGAL_error_msg("Not implemented yet!"); + return ARR_INTERIOR; + } + + /*! Obtains the parameter space at a point along the y-axis. + * \param p the point. + * \return the parameter space at p. + */ + Arr_parameter_space operator()(const Point_2 /* p */) const + { return ARR_INTERIOR; } + }; + + /*! Obtain a Parameter_space_in_y_2 function object */ + Parameter_space_in_y_2 parameter_space_in_y_2_object() const + { return Parameter_space_in_y_2(); } + + //@} + /// \name Intersections, subdivisions, and mergings //@{ @@ -1010,18 +1097,13 @@ public: protected: using Traits = Arr_conic_traits_2; - Intersection_map& m_inter_map; // The map of intersection points. - /*! The traits (in case it has state) */ const Traits& m_traits; /*! Constructor. * \param traits the traits. */ - Intersect_2(Intersection_map& map, const Traits& traits) : - m_inter_map(map), - m_traits(traits) - {} + Intersect_2(const Traits& traits) : m_traits(traits) {} friend class Arr_conic_traits_2; @@ -1038,7 +1120,7 @@ public: OutputIterator operator()(const X_monotone_curve_2& xcv1, const X_monotone_curve_2& xcv2, OutputIterator oi) const - { return intersect(xcv1, xcv2, m_inter_map, oi); } + { return intersect(xcv1, xcv2, m_traits.m_inter_map, oi); } private: /*! Compute the overlap with a given arc, which is supposed to have the same @@ -1127,7 +1209,6 @@ public: const auto* extra_data2 = xcv2.extra_data(); Algebraic denom = extra_data1->a * extra_data2->b - extra_data1->b * extra_data2->a; - if (CGAL::sign (denom) != CGAL::ZERO) { xs[0] = (extra_data1->b * extra_data2->c - extra_data1->c * extra_data2->b) / denom; @@ -1193,7 +1274,7 @@ public: // Pair the coordinates of the intersection points. As the vectors of // x and y-coordinates are sorted in ascending order, we output the // intersection points in lexicographically ascending order. - unsigned int mult; + Multiplicity mult; int i, j; if (xcv2.is_special_segment()) { @@ -1355,7 +1436,6 @@ public: // In case the intersection points between the supporting conics have // not been computed before, compute them now and store them in the map. intersect_supporting_conics(xcv1, xcv2, inter_list); - if (! invalid_ids) inter_map[conic_pair] = inter_list; } else { @@ -1378,8 +1458,7 @@ public: }; /*! Obtain an Intersect_2 functor object. */ - Intersect_2 intersect_2_object() const - { return Intersect_2(m_inter_map, *this); } + Intersect_2 intersect_2_object() const { return Intersect_2(*this); } class Are_mergeable_2 { protected: @@ -2194,7 +2273,8 @@ public: */ X_monotone_curve_2 operator()(const Point_2& source, const Point_2& target) const { - X_monotone_curve_2 xcv(source, target); + X_monotone_curve_2 xcv; + xcv->set_endpoints(source, target); xcv.set_flag(X_monotone_curve_2::DEGREE_1); auto cmp_xy = m_traits.m_alg_kernel->compare_xy_2_object(); Comparison_result dir_res = cmp_xy(source, target); @@ -3050,9 +3130,12 @@ public: /*! Obtain a bounding box for the conic arc. * \return The bounding box. */ - Bbox_2 operator()(const X_monotone_curve_2& xcv) const { - CGAL_precondition(xcv.is_valid()); + Bbox_2 operator()(const X_monotone_curve_2& xcv) const { return bbox(xcv); } + Bbox_2 operator()(const Curve_2& cv) const { return bbox(cv); } + private: + Bbox_2 bbox(const X_monotone_curve_2& xcv) const { + CGAL_precondition(xcv.is_valid()); double x_min(0), y_min(0), x_max(0), y_max(0); if (xcv.is_full_conic()) { @@ -3061,7 +3144,8 @@ public: Alg_point_2 tan_ps[2]; CGAL_assertion_code(int n_tan_ps); - CGAL_assertion_code(n_tan_ps = vertical_tangency_points(xcv, tan_ps)); + CGAL_assertion_code + (n_tan_ps = m_traits.vertical_tangency_points(xcv, tan_ps)); CGAL_assertion(n_tan_ps == 2); if (CGAL::to_double(tan_ps[0].x()) < CGAL::to_double(tan_ps[1].x())) { @@ -3073,7 +3157,8 @@ public: x_max = CGAL::to_double(tan_ps[0].x()); } - CGAL_assertion_code(n_tan_ps = xcv.horizontal_tangency_points(tan_ps)); + CGAL_assertion_code + (n_tan_ps = m_traits.horizontal_tangency_points(xcv, tan_ps)); CGAL_assertion(n_tan_ps == 2); if (CGAL::to_double(tan_ps[0].y()) < CGAL::to_double(tan_ps[1].y())) { @@ -3107,7 +3192,7 @@ public: // Go over the vertical tangency points and try to update the x-points. Alg_point_2 tan_ps[2]; - auto n_tan_ps = vertical_tangency_points(xcv, tan_ps); + auto n_tan_ps = m_traits.vertical_tangency_points(xcv, tan_ps); for (int i = 0; i < n_tan_ps; ++i) { if (CGAL::to_double(tan_ps[i].x()) < x_min) x_min = CGAL::to_double(tan_ps[i].x()); @@ -3116,7 +3201,7 @@ public: } // Go over the horizontal tangency points and try to update the y-points. - n_tan_ps = xcv.horizontal_tangency_points(tan_ps); + n_tan_ps = m_traits.horizontal_tangency_points(xcv, tan_ps); for (int i = 0; i < n_tan_ps; ++i) { if (CGAL::to_double(tan_ps[i].y()) < y_min) y_min = CGAL::to_double(tan_ps[i].y()); @@ -3131,7 +3216,8 @@ public: }; /*! Obtain a Bbox_2 functor object. */ - Construct_bbox_2 bbox_2_object() const { return Construct_bbox_2(*this); } + Construct_bbox_2 construct_bbox_2_object() const + { return Construct_bbox_2(*this); } //@} /*! Set the properties of a conic arc (for the usage of the constructors). @@ -3179,6 +3265,7 @@ public: ! is_on_supporting_conic(arc, target)) { arc.reset_flags(); // inavlid arc + return; } // Check whether we have a degree 2 curve. @@ -3202,7 +3289,6 @@ public: return; } - // We have a segment of a line pair with rational coefficients. // Compose the equation of the underlying line // (with algebraic coefficients). @@ -3975,7 +4061,7 @@ public: * \pre The hpts vector should be allocated at the size of 2. * \return The number of horizontal tangency points. */ - int horizontal_tangency_points(const Curve_2& cv, Point_2* hpts) const { + int horizontal_tangency_points(const Curve_2& cv, Alg_point_2* hpts) const { // No horizontal tangency points for line segments: if (cv.orientation() == COLLINEAR) return 0; @@ -4000,4 +4086,5 @@ public: #include } //namespace CGAL + #endif diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h index 99f7fd1913f..457739c9fb5 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h @@ -8,7 +8,8 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s): Ron Wein +// Author(s): Ron Wein +// Efi Fogel #ifndef CGAL_CONIC_ARC_2_H #define CGAL_CONIC_ARC_2_H @@ -16,12 +17,14 @@ #include /*! \file - * Header file for the _Conic_arc_2 class. + * Header file for the Conic_arc_2 class. */ #include #include + +// The following is included for the benefit of deprecated functions. #include #include @@ -42,13 +45,13 @@ namespace CGAL { */ template -class _Conic_arc_2 { +class Conic_arc_2 { public: typedef RatKernel Rat_kernel; typedef AlgKernel Alg_kernel; typedef NtTraits Nt_traits; - typedef _Conic_arc_2 Self; + typedef Conic_arc_2 Self; typedef typename Rat_kernel::FT Rational; typedef typename Rat_kernel::Point_2 Rat_point_2; @@ -58,8 +61,8 @@ public: typedef typename Nt_traits::Integer Integer; typedef typename Alg_kernel::FT Algebraic; - typedef typename Alg_kernel::Point_2 Point_2; - typedef _Conic_point_2 Conic_point_2; + typedef typename Alg_kernel::Point_2 Alg_point_2; + typedef Conic_point_2 Point_2; /*! \struct * For arcs whose base is a hyperbola we store the axis (a*x + b*y + c = 0) @@ -93,18 +96,1239 @@ protected: Orientation m_orient; // The orientation of the conic. int m_info; // does the arc represent a full conic curve. - Conic_point_2 m_source; // the source of the arc (if not a full curve). - Conic_point_2 m_target; // the target of the arc (if not a full curve). + Point_2 m_source; // the source of the arc (if not a full curve). + Point_2 m_target; // the target of the arc (if not a full curve). Extra_data* m_extra_data; // The extra data stored with the arc // (may be nullptr). +public: + /// \name Deprecated Constructions. + //@{ + + /*!Construct a conic arc which is the full conic: + * C: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0 + * \pre The conic C must be an ellipse (so 4rs - t^2 > 0). + */ + CGAL_DEPRECATED Conic_arc_2(const Rational& r, const Rational& s, + const Rational& t, const Rational& u, + const Rational& v, const Rational& w) : + m_info(0), + m_extra_data(nullptr) + { + // Ensure that the given curve is an ellipse (4rs - t^2 is positive). + CGAL_precondition(CGAL::sign(4*r*s - t*t) == POSITIVE); + + // Set the arc to be the full conic (and compute the orientation). + Rational rat_coeffs[6]; + rat_coeffs[0] = r; + rat_coeffs[1] = s; + rat_coeffs[2] = t; + rat_coeffs[3] = u; + rat_coeffs[4] = v; + rat_coeffs[5] = w; + _set_full(rat_coeffs, true); + } + + /*! Construct a conic arc which lies on the conic: + * C: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0 + * \param orient The orientation of the arc (clockwise or counterclockwise). + * \param source The source point. + * \param target The target point. + * \pre The source and the target must be on the conic boundary and must + * not be the same. + */ + CGAL_DEPRECATED + Conic_arc_2(const Rational& r, const Rational& s, const Rational& t, + const Rational& u, const Rational& v, const Rational& w, + const Orientation& orient, + const Point_2& source, const Point_2& target) : + m_orient(orient), + m_source(source), + m_target(target), + m_extra_data(nullptr) + { + // Make sure that the source and the taget are not the same. + CGAL_precondition(Alg_kernel().compare_xy_2_object()(source, target) != + EQUAL); + + // Set the arc properties (no need to compute the orientation). + Rational rat_coeffs[6] = {r, s, t, u, v, w}; + _set(rat_coeffs); + } + + /*! Construct a segment conic arc from two endpoints. + * \param source the source point with rational coordinates. + */ + CGAL_DEPRECATED Conic_arc_2(const Point_2& source, const Point_2& target) : + m_orient(COLLINEAR), + m_info(0), + m_source(source), + m_target(target), + m_extra_data(nullptr) + { + set_flag(IS_VALID); + CGAL_precondition(Alg_kernel().compare_xy_2_object()(source, target) != + EQUAL); + + // Compose the equation of the underlying line. + const Algebraic x1 = source.x(); + const Algebraic y1 = source.y(); + const Algebraic x2 = target.x(); + const Algebraic y2 = target.y(); + + // The supporting line is A*x + B*y + C = 0, where: + // A = y2 - y1, B = x1 - x2, C = x2*y1 - x1*y2 + // We use the extra data field to store the equation of this line. + m_extra_data = new Extra_data; + m_extra_data->a = y2 - y1; + m_extra_data->b = x1 - x2; + m_extra_data->c = x2*y1 - x1*y2; + m_extra_data->side = ZERO; + } + + /*! Construct a conic arc from the given line segment. + * \param seg The line segment with rational endpoints. + */ + CGAL_DEPRECATED Conic_arc_2 (const Rat_segment_2& seg) : + m_orient(COLLINEAR), + m_info(0), + m_extra_data(nullptr) + { + // Set the source and target. + Rat_kernel ker; + Rat_point_2 source = ker.construct_vertex_2_object()(seg, 0); + Rat_point_2 target = ker.construct_vertex_2_object()(seg, 1); + Rational x1 = source.x(); + Rational y1 = source.y(); + Rational x2 = target.x(); + Rational y2 = target.y(); + Nt_traits nt_traits; + + m_source = Point_2(nt_traits.convert (x1), nt_traits.convert(y1)); + m_target = Point_2(nt_traits.convert (x2), nt_traits.convert(y2)); + + // Make sure that the source and the taget are not the same. + CGAL_precondition (Alg_kernel().compare_xy_2_object()(m_source, m_target) + != EQUAL); + + // The supporting conic is r=s=t=0, and u*x + v*y + w = 0 should hold + // for both the source (x1,y1) and the target (x2, y2). + const Rational zero (0); + const Rational one (1); + Rational rat_coeffs[6]; + + rat_coeffs[0] = zero; + rat_coeffs[1] = zero; + rat_coeffs[2] = zero; + + if (CGAL::compare(x1, x2) == EQUAL) { + // The supporting conic is a vertical line, of the form x = CONST. + rat_coeffs[3] = one; + rat_coeffs[4] = zero; + rat_coeffs[5] = -x1; + } + else { + // The supporting line is A*x + B*y + C = 0, where: + // + // A = y2 - y1, B = x1 - x2, C = x2*y1 - x1*y2 + // + rat_coeffs[3] = y2 - y1; + rat_coeffs[4] = x1 - x2; + rat_coeffs[5] = x2*y1 - x1*y2; + } + + // Set the arc properties (no need to compute the orientation). + _set(rat_coeffs); + } + + /*! Set a circular arc that corresponds to a full circle. + * \param circ The circle (with rational center and rational squared radius). + */ + CGAL_DEPRECATED Conic_arc_2(const Rat_circle_2& circ) : + m_orient(CLOCKWISE), + m_info(0), + m_extra_data(nullptr) + { + // Get the circle properties. + Rat_kernel ker; + Rat_point_2 center = ker.construct_center_2_object() (circ); + Rational x0 = center.x(); + Rational y0 = center.y(); + Rational R_sqr = ker.compute_squared_radius_2_object() (circ); + + // Produce the correponding conic: if the circle center is (x0,y0) + // and its squared radius is R^2, that its equation is: + // x^2 + y^2 - 2*x0*x - 2*y0*y + (x0^2 + y0^2 - R^2) = 0 + // Note that this equation describes a curve with a negative (clockwise) + // orientation. + const Rational zero(0); + const Rational one (1); + const Rational minus_two(-2); + Rational rat_coeffs[6]; + + rat_coeffs[0] = one; + rat_coeffs[1] = one; + rat_coeffs[2] = zero; + rat_coeffs[3] = minus_two*x0; + rat_coeffs[4] = minus_two*y0; + rat_coeffs[5] = x0*x0 + y0*y0 - R_sqr; + + // Set the arc to be the full conic (no need to compute the orientation). + _set_full(rat_coeffs, false); + } + + /*! Set a circular arc that lies on the given circle: + * C: (x - x0)^2 + (y - y0)^2 = R^2 + * \param orient The orientation of the circle. + * \param source The source point. + * \param target The target point. + * \pre The source and the target must be on the conic boundary and must + * not be the same. + */ + CGAL_DEPRECATED + Conic_arc_2(const Rat_circle_2& circ, const Orientation& orient, + const Point_2& source, const Point_2& target) : + m_orient(orient), + m_info(0), + m_source(source), + m_target(target), + m_extra_data(nullptr) + { + // Make sure that the source and the taget are not the same. + CGAL_precondition(Alg_kernel().compare_xy_2_object()(source, target) != + EQUAL); + CGAL_precondition(orient != COLLINEAR); + + // Get the circle properties. + Rat_kernel ker; + Rat_point_2 center = ker.construct_center_2_object()(circ); + Rational x0 = center.x(); + Rational y0 = center.y(); + Rational R_sqr = ker.compute_squared_radius_2_object()(circ); + + // Produce the correponding conic: if the circle center is (x0,y0) + // and it squared radius is R^2, that its equation is: + // x^2 + y^2 - 2*x0*x - 2*y0*y + (x0^2 + y0^2 - R^2) = 0 + // Since this equation describes a curve with a negative (clockwise) + // orientation, we multiply it by -1 if nece_Conic_arc_2 ssary to obtain a + // positive (counterclockwise) orientation. + const Rational zero (0); + Rational rat_coeffs[6]; + + if (m_orient == COUNTERCLOCKWISE) { + const Rational minus_one(-1); + const Rational two(2); + + rat_coeffs[0] = minus_one; + rat_coeffs[1] = minus_one; + rat_coeffs[2] = zero; + rat_coeffs[3] = two*x0; + rat_coeffs[4] = two*y0; + rat_coeffs[5] = R_sqr - x0*x0 - y0*y0; + } + else { + const Rational one(1); + const Rational minus_two(-2); + + rat_coeffs[0] = one; + rat_coeffs[1] = one; + rat_coeffs[2] = zero; + rat_coeffs[3] = minus_two*x0; + rat_coeffs[4] = minus_two*y0; + rat_coeffs[5] = x0*x0 + y0*y0 - R_sqr; + } + + // Set the arc properties (no need to compute the orientation). + _set(rat_coeffs); + } + + /*! Construct a circular arc from the given three points. + * \param p1 The arc source. + * \param p2 A point in the interior of the arc. + * \param p3 The arc target. + * \pre The three points must not be collinear. + */ + CGAL_DEPRECATED Conic_arc_2(const Rat_point_2& p1, const Rat_point_2& p2, + const Rat_point_2& p3) : + m_info(0), + m_extra_data(nullptr) + { + // Set the source and target. + Rational x1 = p1.x(); + Rational y1 = p1.y(); + Rational x2 = p2.x(); + Rational y2 = p2.y(); + Rational x3 = p3.x(); + Rational y3 = p3.y(); + Nt_traits nt_traits; + + m_source = Point_2(nt_traits.convert (x1), nt_traits.convert(y1)); + m_target = Point_2(nt_traits.convert (x3), nt_traits.convert(y3)); + + // Make sure that the source and the taget are not the same. + CGAL_precondition(Alg_kernel().compare_xy_2_object()(m_source, m_target) != + EQUAL); + + // Compute the lines: A1*x + B1*y + C1 = 0, + // and: A2*x + B2*y + C2 = 0, + // where: + const Rational two = 2; + + const Rational A1 = two*(x1 - x2); + const Rational B1 = two*(y1 - y2); + const Rational C1 = y2*y2 - y1*y1 + x2*x2 - x1*x1; + + const Rational A2 = two*(x2 - x3); + const Rational B2 = two*(y2 - y3); + const Rational C2 = y3*y3 - y2*y2 + x3*x3 - x2*x2; + + // Compute the coordinates of the intersection point between the + // two lines, given by (Nx / D, Ny / D), where: + const Rational Nx = B1*C2 - B2*C1; + const Rational Ny = A2*C1 - A1*C2; + const Rational D = A1*B2 - A2*B1; + + // Make sure the three points are not collinear. + const bool points_collinear = (CGAL::sign(D) == ZERO); + + if (points_collinear) { + reset_flags(); // inavlid arc + return; + } + + // The equation of the underlying circle is given by: + Rational rat_coeffs[6]; + rat_coeffs[0] = D*D; + rat_coeffs[1] = D*D; + rat_coeffs[2] = 0; + rat_coeffs[3] = -two*D*Nx; + rat_coeffs[4] = -two*D*Ny; + rat_coeffs[5] = + Nx*Nx + Ny*Ny - ((D*x2 - Nx)*(D*x2 - Nx) + (D*y2 - Ny)*(D*y2 - Ny)); + + // Determine the orientation: If the mid-point forms a left-turn with + // the source and the target points, the orientation is positive (going + // counterclockwise). + // Otherwise, it is negative (going clockwise). + Alg_kernel ker; + typename Alg_kernel::Orientation_2 orient_f = ker.orientation_2_object(); + + Point_2 p_mid = Point_2(nt_traits.convert(x2), nt_traits.convert(y2)); + + if (orient_f(m_source, p_mid, m_target) == LEFT_TURN) + m_orient = COUNTERCLOCKWISE; + else + m_orient = CLOCKWISE; + + // Set the arc properties (no need to compute the orientation). + _set(rat_coeffs); + } + + /*! Construct a conic arc from the given five points, specified by the + * points p1, p2, p3, p4 and p5. + * \param p1 The source point of the given arc. + * \param p2,p3,p4 Points lying on the conic arc, between p1 and p5. + * \param p5 The target point of the given arc. + * \pre No three points are collinear. + */ + CGAL_DEPRECATED Conic_arc_2(const Rat_point_2& p1, const Rat_point_2& p2, + const Rat_point_2& p3, const Rat_point_2& p4, + const Rat_point_2& p5) : + m_info(0), + m_extra_data(nullptr) + { + // Make sure that no three points are collinear. + Rat_kernel ker; + typename Rat_kernel::Orientation_2 orient_f = ker.orientation_2_object(); + const bool point_collinear = + (orient_f (p1, p2, p3) == COLLINEAR || + orient_f (p1, p2, p4) == COLLINEAR || + orient_f (p1, p2, p5) == COLLINEAR || + orient_f (p1, p3, p4) == COLLINEAR || + orient_f (p1, p3, p5) == COLLINEAR || + orient_f (p1, p4, p5) == COLLINEAR || + orient_f (p2, p3, p4) == COLLINEAR || + orient_f (p2, p3, p5) == COLLINEAR || + orient_f (p2, p4, p5) == COLLINEAR || + orient_f (p3, p4, p5) == COLLINEAR); + + if (point_collinear) { + reset_flags(); // inavlid arc + return; + } + + // Set the source and target. + Rational x1 = p1.x(); + Rational y1 = p1.y(); + Rational x5 = p5.x(); + Rational y5 = p5.y(); + Nt_traits nt_traits; + + m_source = Point_2(nt_traits.convert (x1), nt_traits.convert(y1)); + m_target = Point_2(nt_traits.convert (x5), nt_traits.convert(y5)); + + // Set a conic curve that passes through the five given point. + typename Rat_kernel::Conic_2 temp_conic; + Rational rat_coeffs [6]; + + temp_conic.set(p1, p2, p3, p4, p5); + + // Get the conic coefficients. + rat_coeffs[0] = temp_conic.r(); + rat_coeffs[1] = temp_conic.s(); + rat_coeffs[2] = temp_conic.t(); + rat_coeffs[3] = temp_conic.u(); + rat_coeffs[4] = temp_conic.v(); + rat_coeffs[5] = temp_conic.w(); + + // Determine the orientation: If one of the midpoints forms a left-turn + // with the source and the target points, the orientation is positive + // (going counterclockwise). + // Otherwise, it is negative (going clockwise). + const Orientation turn = orient_f(p1, p2, p5); + + if (turn == LEFT_TURN) { + m_orient = COUNTERCLOCKWISE; + CGAL_precondition(orient_f(p1, p3, p5) == LEFT_TURN && + orient_f(p1, p4, p5) == LEFT_TURN); + } + else { + m_orient = CLOCKWISE; + CGAL_precondition(orient_f(p1, p3, p5) != LEFT_TURN && + orient_f(p1, p4, p5) != LEFT_TURN); + } + + // Set the arc properties (no need to compute the orientation). + _set(rat_coeffs); + + // Make sure that all midpoints are strictly between the + // source and the target. + Point_2 mp2 = Point_2(nt_traits.convert(p2.x()), nt_traits.convert(p2.y())); + Point_2 mp3 = Point_2(nt_traits.convert(p3.x()), nt_traits.convert(p3.y())); + Point_2 mp4 = Point_2(nt_traits.convert(p4.x()), nt_traits.convert(p4.y())); + + if (! _is_strictly_between_endpoints(mp2) || + ! _is_strictly_between_endpoints(mp3) || + ! _is_strictly_between_endpoints(mp4)) + { + reset_flags(); // inavlid arc + } + } + + /*! Construct a conic arc which lies on the conic: + * C: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0 + * The source and the target are specified by the intersection of the + * conic with: + * C_1: r_1*x^2 + s_1*y^2 + t_1*xy + u_1*x + v_1*y + w_1 = 0 + * C_2: r_2*x^2 + s_2*y^2 + t_2*xy + u_2*x + v_2*y + w_2 = 0 + * The user must also specify the source and the target with approximated + * coordinates. The actual intersection points that best fits the source + * (or the target) will be selected. + */ + CGAL_DEPRECATED + Conic_arc_2(const Rational& r, const Rational& s, const Rational& t, + const Rational& u, const Rational& v, const Rational& w, + const Orientation& orient, + const Point_2& app_source, + const Rational& r_1, const Rational& s_1, const Rational& t_1, + const Rational& u_1, const Rational& v_1, const Rational& w_1, + const Point_2& app_target, + const Rational& r_2, const Rational& s_2, const Rational& t_2, + const Rational& u_2, const Rational& v_2, const Rational& w_2): + m_orient(orient), + m_info(0), + m_extra_data(nullptr) + { + // Create the integer coefficients of the base conic. + Nt_traits nt_traits; + Integer base_coeffs[6]; + int deg_base; + Rational rat_coeffs [6] = {r, s, t, u, v, w}; + nt_traits.convert_coefficients(rat_coeffs, rat_coeffs + 6, base_coeffs); + + if (CGAL::sign (base_coeffs[0]) == ZERO && + CGAL::sign (base_coeffs[1]) == ZERO && + CGAL::sign (base_coeffs[2]) == ZERO) { + deg_base = 1; + } + else { + deg_base = 2; + } + + // Compute the endpoints. + Rational aux_rat_coeffs [6]; + Integer aux_coeffs[6]; + int deg_aux; + Algebraic xs[4]; + int n_xs; + Algebraic ys[4]; + int n_ys; + int i, j; + Algebraic val; + bool found; + double dx, dy; + double curr_dist; + double min_dist = -1; + int k; + + for (k = 1; k <= 2; ++k) { + // Get the integer coefficients of the k'th auxiliary conic curve. + aux_rat_coeffs[0] = (k == 1) ? r_1 : r_2; + aux_rat_coeffs[1] = (k == 1) ? s_1 : s_2; + aux_rat_coeffs[2] = (k == 1) ? t_1 : t_2; + aux_rat_coeffs[3] = (k == 1) ? u_1 : u_2; + aux_rat_coeffs[4] = (k == 1) ? v_1 : v_2; + aux_rat_coeffs[5] = (k == 1) ? w_1 : w_2; + + nt_traits.convert_coefficients(aux_rat_coeffs, aux_rat_coeffs + 6, + aux_coeffs); + + if (CGAL::sign (aux_coeffs[0]) == ZERO && + CGAL::sign (aux_coeffs[1]) == ZERO && + CGAL::sign (aux_coeffs[2]) == ZERO) { + deg_aux = 1; + } + else { + deg_aux = 2; + } + + // Compute the x- and y-coordinates of intersection points of the base + // conic and the k'th auxiliary conic. + n_xs = compute_resultant_roots(nt_traits, + base_coeffs[0], base_coeffs[1], + base_coeffs[2], + base_coeffs[3], base_coeffs[4], + base_coeffs[5], + deg_base, + aux_coeffs[0], aux_coeffs[1], + aux_coeffs[2], + aux_coeffs[3], aux_coeffs[4], + aux_coeffs[5], + deg_aux, + xs); + + n_ys = compute_resultant_roots(nt_traits, + base_coeffs[1], base_coeffs[0], + base_coeffs[2], + base_coeffs[4], base_coeffs[3], + base_coeffs[5], + deg_base, + aux_coeffs[1], aux_coeffs[0], + aux_coeffs[2], + aux_coeffs[4], aux_coeffs[3], + aux_coeffs[5], + deg_aux, + ys); + + // Find the intersection point which is nearest the given approximation + // and set it as the endpoint. + found = false; + for (i = 0; i < n_xs; ++i) { + for (j = 0; j < n_ys; ++j) { + // Check if the point (xs[i], ys[j]) lies on both conics. + val = nt_traits.convert(base_coeffs[0]) * xs[i]*xs[i] + + nt_traits.convert(base_coeffs[1]) * ys[j]*ys[j] + + nt_traits.convert(base_coeffs[2]) * xs[i]*ys[j] + + nt_traits.convert(base_coeffs[3]) * xs[i] + + nt_traits.convert(base_coeffs[4]) * ys[j] + + nt_traits.convert(base_coeffs[5]); + + if (CGAL::sign (val) != ZERO) continue; + + val = nt_traits.convert(aux_coeffs[0]) * xs[i]*xs[i] + + nt_traits.convert(aux_coeffs[1]) * ys[j]*ys[j] + + nt_traits.convert(aux_coeffs[2]) * xs[i]*ys[j] + + nt_traits.convert(aux_coeffs[3]) * xs[i] + + nt_traits.convert(aux_coeffs[4]) * ys[j] + + nt_traits.convert(aux_coeffs[5]); + + if (CGAL::sign (val) == ZERO) { + // Compute the distance of (xs[i], ys[j]) from the approximated + // endpoint. + if (k == 1) { + dx = CGAL::to_double (xs[i] - app_source.x()); + dy = CGAL::to_double (ys[j] - app_source.y()); + } + else { + dx = CGAL::to_double (xs[i] - app_target.x()); + dy = CGAL::to_double (ys[j] - app_target.y()); + } + + curr_dist = dx*dx + dy*dy; + + // Update the endpoint if (xs[i], ys[j]) is the nearest pair so + // far. + if (! found || curr_dist < min_dist) { + if (k == 1) m_source = Point_2 (xs[i], ys[j]); + else m_target = Point_2 (xs[i], ys[j]); + min_dist = curr_dist; + found = true; + } + } + } + } + + if (! found) { + reset_flags(); // inavlid arc + return; + } + } + + // Make sure that the source and the target are not the same. + if (Alg_kernel().compare_xy_2_object()(m_source, m_target) == EQUAL) { + reset_flags(); // inavlid arc + return; + } + + // Set the arc properties (no need to compute the orientation). + _set(rat_coeffs); + } + + /*! Get a bounding box for the conic arc. + * \return The bounding box. + */ + CGAL_DEPRECATED Bbox_2 bbox() const { + CGAL_precondition (is_valid()); + + double x_min(0), y_min(0); + double x_max(0), y_max(0); + + if (is_full_conic()) { + // In case of a full conic (an ellipse or a circle), compute the + // horizontal and vertical tangency points and use them to bound the arc. + Point_2 tan_ps[2]; + CGAL_assertion_code(int n_tan_ps); + + CGAL_assertion_code(n_tan_ps = vertical_tangency_points(tan_ps)); + CGAL_assertion(n_tan_ps == 2); + + if (CGAL::to_double(tan_ps[0].x()) < CGAL::to_double(tan_ps[1].x())) { + x_min = CGAL::to_double(tan_ps[0].x()); + x_max = CGAL::to_double(tan_ps[1].x()); + } + else { + x_min = CGAL::to_double(tan_ps[1].x()); + x_max = CGAL::to_double(tan_ps[0].x()); + } + + CGAL_assertion_code(n_tan_ps = horizontal_tangency_points(tan_ps)); + CGAL_assertion(n_tan_ps == 2); + + if (CGAL::to_double(tan_ps[0].y()) < CGAL::to_double(tan_ps[1].y())) { + y_min = CGAL::to_double(tan_ps[0].y()); + y_max = CGAL::to_double(tan_ps[1].y()); + } + else { + y_min = CGAL::to_double(tan_ps[1].y()); + y_max = CGAL::to_double(tan_ps[0].y()); + } + } + else { + // Use the source and target to initialize the exterme points. + bool source_left = + CGAL::to_double(m_source.x()) < CGAL::to_double(m_target.x()); + x_min = source_left ? + CGAL::to_double(m_source.x()) : CGAL::to_double(m_target.x()); + x_max = source_left ? + CGAL::to_double(m_target.x()) : CGAL::to_double(m_source.x()); + + bool source_down = + CGAL::to_double(m_source.y()) < CGAL::to_double(m_target.y()); + y_min = source_down ? + CGAL::to_double(m_source.y()) : CGAL::to_double(m_target.y()); + y_max = source_down ? + CGAL::to_double(m_target.y()) : CGAL::to_double(m_source.y()); + + // Go over the vertical tangency points and try to update the x-points. + Point_2 tan_ps[2]; + int n_tan_ps; + int i; + + n_tan_ps = vertical_tangency_points(tan_ps); + for (i = 0; i < n_tan_ps; ++i) { + if (CGAL::to_double(tan_ps[i].x()) < x_min) + x_min = CGAL::to_double(tan_ps[i].x()); + if (CGAL::to_double(tan_ps[i].x()) > x_max) + x_max = CGAL::to_double(tan_ps[i].x()); + } + + // Go over the horizontal tangency points and try to update the y-points. + n_tan_ps = horizontal_tangency_points(tan_ps); + for (i = 0; i < n_tan_ps; ++i) { + if (CGAL::to_double(tan_ps[i].y()) < y_min) + y_min = CGAL::to_double(tan_ps[i].y()); + if (CGAL::to_double(tan_ps[i].y()) > y_max) + y_max = CGAL::to_double(tan_ps[i].y()); + } + } + + // Return the resulting bounding box. + return Bbox_2(x_min, y_min, x_max, y_max); + } + + //@} + +protected: + /*! Calculate the vertical tangency points of the arc. + * \param vpts The vertical tangency points. + * \pre The vpts vector should be allocated at the size of 2. + * \return The number of vertical tangency points. + */ + CGAL_DEPRECATED int vertical_tangency_points(Point_2* vpts) const { + // No vertical tangency points for line segments: + if (m_orient == COLLINEAR) return 0; + + // Calculate the vertical tangency points of the supporting conic. + Point_2 ps[2]; + int n = _conic_vertical_tangency_points(ps); + + // Return only the points that are contained in the arc interior. + int m(0); + + for (int i = 0; i < n; ++i) { + if (is_full_conic() || _is_strictly_between_endpoints(ps[i])) { + vpts[m] = ps[i]; + ++m; + } + } + + // Return the number of vertical tangency points found. + CGAL_assertion(m <= 2); + return m; + } + + /*! Calculate the horizontal tangency points of the arc. + * \param hpts The horizontal tangency points. + * \pre The hpts vector should be allocated at the size of 2. + * \return The number of horizontal tangency points. + */ + CGAL_DEPRECATED int horizontal_tangency_points(Point_2* hpts) const { + // No horizontal tangency points for line segments: + if (m_orient == COLLINEAR) return 0; + + // Calculate the horizontal tangency points of the conic. + Point_2 ps[2]; + int n = _conic_horizontal_tangency_points(ps); + + // Return only the points that are contained in the arc interior. + int m = 0; + + for (int i = 0; i < n; ++i) { + if (is_full_conic() || _is_strictly_between_endpoints(ps[i])) { + hpts[m] = ps[i]; + ++m; + } + } + + // Return the number of horizontal tangency points found. + CGAL_assertion(m <= 2); + return m; + } + + /*! Check whether the given point is strictly between the source and the + * target (but not any of them). + * The point is assumed to be on the conic's boundary. + * \param p The query point. + * \return (true) if the point is strictly between the two endpoints, + * (false) if it is not. + */ + CGAL_DEPRECATED bool _is_strictly_between_endpoints(const Point_2& p) const { + // In case this is a full conic, any point on its boundary is between + // its end points. + if (is_full_conic()) return true; + + // Check if we have extra data available. + if (m_extra_data != nullptr) { + if (m_extra_data->side != ZERO) { + // In case of a hyperbolic arc, make sure the point is located on the + // same branch as the arc. + if (sign_of_extra_data(p.x(), p.y()) != m_extra_data->side) + return false; + } + else { + // In case we have a segment of a line pair, make sure that p really + // satisfies the equation of the line. + if (sign_of_extra_data(p.x(), p.y()) != ZERO) return false; + } + } + + // Act according to the conic degree. + Alg_kernel ker; + + if (m_orient == COLLINEAR) { + Comparison_result res1; + Comparison_result res2; + + if (ker.compare_x_2_object()(m_source, m_target) == EQUAL) { + // In case of a vertical segment - just check whether the y coordinate + // of p is between those of the source's and of the target's. + res1 = ker.compare_y_2_object()(p, m_source); + res2 = ker.compare_y_2_object()(p, m_target); + } + else { + // Otherwise, since the segment is x-monotone, just check whether the + // x coordinate of p is between those of the source's and of the + // target's. + res1 = ker.compare_x_2_object()(p, m_source); + res2 = ker.compare_x_2_object()(p, m_target); + } + + // If p is not in the (open) x-range (or y-range) of the segment, it + // cannot be contained in the segment. + if (res1 == EQUAL || res2 == EQUAL || res1 == res2) return false; + + // Perform an orientation test: This is crucial for segment of line + // pairs, as we want to make sure that p lies on the same line as the + // source and the target. + return (ker.orientation_2_object()(m_source, p, m_target) == COLLINEAR); + } + else { + // In case of a conic of degree 2, make a decision based on the conic's + // orientation and whether (source,p,target) is a right or a left turn. + if (m_orient == COUNTERCLOCKWISE) + return (ker.orientation_2_object()(m_source, p, m_target) == LEFT_TURN); + else + return (ker.orientation_2_object()(m_source, p, m_target) == RIGHT_TURN); + } + } + + /*! Set the properties of a conic arc that is really a full curve + * (that is, an ellipse). + * \param rat_coeffs A vector of size 6, storing the rational coefficients + * of x^2, y^2, xy, x, y and the free coefficient resp. + * \param comp_orient Should we compute the orientation of the given curve. + */ + CGAL_DEPRECATED + void _set_full(const Rational* rat_coeffs, const bool& comp_orient) { + // Convert the coefficients vector to an equivalent vector of integer + // coefficients. + Nt_traits nt_traits; + Integer int_coeffs[6]; + + nt_traits.convert_coefficients(rat_coeffs, rat_coeffs + 6, int_coeffs); + + // Check the orientation of conic curve, and negate the conic coefficients + // if its given orientation. + typename Rat_kernel::Conic_2 temp_conic(rat_coeffs[0], rat_coeffs[1], + rat_coeffs[2], rat_coeffs[3], + rat_coeffs[4], rat_coeffs[5]); + const Orientation temp_orient = temp_conic.orientation(); + + if (comp_orient) set_orientation(temp_orient); + + if (orientation() == temp_orient) { + m_r = int_coeffs[0]; + m_s = int_coeffs[1]; + m_t = int_coeffs[2]; + m_u = int_coeffs[3]; + m_v = int_coeffs[4]; + m_w = int_coeffs[5]; + } + else { + m_r = -int_coeffs[0]; + m_s = -int_coeffs[1]; + m_t = -int_coeffs[2]; + m_u = -int_coeffs[3]; + m_v = -int_coeffs[4]; + m_w = -int_coeffs[5]; + } + + // Make sure the conic is a non-degenerate ellipse: + // The coefficients should satisfy (4rs - t^2) > 0. + const bool is_ellipse = (CGAL::sign(4*m_r*m_s - m_t*m_t) == POSITIVE); + CGAL_assertion(is_ellipse); + + // Mark that this arc is a full conic curve. + if (is_ellipse) { + set_flag(IS_VALID); + set_flag(IS_FULL_CONIC); + } + else reset_flags(); // inavlid arc + } + + /*! Check whether the given point lies on the supporting conic of the arc. + * \param p The query point. + * \return (true) if p lies on the supporting conic; (false) otherwise. + */ + CGAL_DEPRECATED bool _is_on_supporting_conic(const Point_2& p) const { + // Check whether p satisfies the conic equation. + // The point must satisfy: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0. + Nt_traits nt_traits; + const Algebraic val = + (nt_traits.convert(m_r)*p.x() + + nt_traits.convert(m_t)*p.y() + + nt_traits.convert(m_u)) * p.x() + + (nt_traits.convert(m_s)*p.y() + + nt_traits.convert(m_v)) * p.y() + + nt_traits.convert(m_w); + + return (CGAL::sign(val) == ZERO); + } + + /*! Build the data for hyperbolic arc, contaning the characterization of the + * hyperbolic branch the arc is placed on. + */ + CGAL_DEPRECATED void _build_hyperbolic_arc_data() { + // Let phi be the rotation angle of the conic from its canonic form. + // We can write: + // + // t + // sin(2*phi) = ----------------------- + // sqrt((r - s)^2 + t^2) + // + // r - s + // cos(2*phi) = ----------------------- + // sqrt((r - s)^2 + t^2) + // + Nt_traits nt_traits; + const int or_fact = (m_orient == CLOCKWISE) ? -1 : 1; + const Algebraic r = nt_traits.convert(or_fact * m_r); + const Algebraic s = nt_traits.convert(or_fact * m_s); + const Algebraic t = nt_traits.convert(or_fact * m_t); + const Algebraic cos_2phi = (r - s) / nt_traits.sqrt((r-s)*(r-s) + t*t); + const Algebraic zero = 0; + const Algebraic one = 1; + const Algebraic two = 2; + Algebraic sin_phi; + Algebraic cos_phi; + + // Calculate sin(phi) and cos(phi) according to the half-angle formulae: + // + // sin(phi)^2 = 0.5 * (1 - cos(2*phi)) + // cos(phi)^2 = 0.5 * (1 + cos(2*phi)) + Sign sign_t = CGAL::sign(t); + + if (sign_t == ZERO) { + // sin(2*phi) == 0, so phi = 0 or phi = PI/2 + if (CGAL::sign(cos_2phi) == POSITIVE) { + // phi = 0. + sin_phi = zero; + cos_phi = one; + } + else { + // phi = PI/2. + sin_phi = one; + cos_phi = zero; + } + } + else if (sign_t == POSITIVE) { + // sin(2*phi) > 0 so 0 < phi < PI/2. + sin_phi = nt_traits.sqrt((one + cos_2phi) / two); + cos_phi = nt_traits.sqrt((one - cos_2phi) / two); + } + else + { + // sin(2*phi) < 0 so PI/2 < phi < PI. + sin_phi = nt_traits.sqrt((one + cos_2phi) / two); + cos_phi = -nt_traits.sqrt((one - cos_2phi) / two); + } + + // Calculate the center (x0, y0) of the conic, given by the formulae: + // + // t*v - 2*s*u t*u - 2*r*v + // x0 = ------------- , y0 = ------------- + // 4*r*s - t^2 4*r*s - t^2 + // + // The denominator (4*r*s - t^2) must be negative for hyperbolas. + const Algebraic u = nt_traits.convert(or_fact * m_u); + const Algebraic v = nt_traits.convert(or_fact * m_v); + const Algebraic det = 4*r*s - t*t; + Algebraic x0, y0; + + CGAL_assertion (CGAL::sign(det) == NEGATIVE); + + x0 = (t*v - two*s*u) / det; + y0 = (t*u - two*r*v) / det; + + // The axis separating the two branches of the hyperbola is now given by: + // + // cos(phi)*x + sin(phi)*y - (cos(phi)*x0 + sin(phi)*y0) = 0 + // + // We store the equation of this line in the extra data structure and also + // the sign (side of half-plane) our arc occupies with respect to the line. + m_extra_data = new Extra_data; + + m_extra_data->a = cos_phi; + m_extra_data->b = sin_phi; + m_extra_data->c = - (cos_phi*x0 + sin_phi*y0); + + // Make sure that the two endpoints are located on the same branch + // of the hyperbola. + m_extra_data->side = sign_of_extra_data(m_source.x(), m_source.y()); + + CGAL_assertion(m_extra_data->side != ZERO); + CGAL_assertion(m_extra_data->side == + sign_of_extra_data(m_target.x(), m_target.y())); + } + + /*! Check whether the given point is between the source and the target. + * The point is assumed to be on the conic's boundary. + * \param p The query point. + * \return (true) if the point is between the two endpoints, + * (false) if it is not. + */ + CGAL_DEPRECATED bool _is_between_endpoints(const Point_2& p) const { + CGAL_precondition(! is_full_conic()); + + // Check if p is one of the endpoints. + Alg_kernel ker; + if (ker.equal_2_object()(p, m_source) || + ker.equal_2_object()(p, m_target)) + return true; + else return _is_strictly_between_endpoints(p); + } + + /*! Find the y coordinates of the underlying conic at a given x coordinate. + * \param x The x coordinate. + * \param ys The output y coordinates. + * \pre The vector ys must be allocated at the size of 2. + * \return The number of y coordinates computed (either 0, 1 or 2). + */ + CGAL_DEPRECATED + int _conic_get_y_coordinates(const Algebraic& x, Algebraic* ys) const { + // Solve the quadratic equation for a given x and find the y values: + // s*y^2 + (t*x + v)*y + (r*x^2 + u*x + w) = 0 + Nt_traits nt_traits; + Algebraic A = nt_traits.convert(m_s); + Algebraic B = nt_traits.convert(m_t)*x + nt_traits.convert(m_v); + Algebraic C = (nt_traits.convert(m_r)*x + + nt_traits.convert(m_u))*x + nt_traits.convert(m_w); + return (_solve_quadratic_equation(A, B, C, ys[0], ys[1])); + } + + /*! Find all points on the arc with a given x-coordinate. + * \param p A placeholder for the x-coordinate. + * \param ps The point on the arc at x(p). + * \pre The vector ps should be allocated at the size of 2. + * \return The number of points found. + */ + CGAL_DEPRECATED int _points_at_x(const Point_2& p, Point_2* ps) const { + // Get the y coordinates of the points on the conic. + Algebraic ys[2]; + int n = _conic_get_y_coordinates(p.x(), ys); + + // Find all the points that are contained in the arc. + int m(0); + + for (int i = 0; i < n; ++i) { + ps[m] = Point_2 (p.x(), ys[i]); + if (is_full_conic() || _is_between_endpoints(ps[m])) ++m; + } + + // Return the number of points on the arc. + CGAL_assertion(m <= 2); + return m; + } + + /*! Solve the given quadratic equation: Ax^2 + B*x + C = 0. + * \param x_minus The root obtained from taking -sqrt(discriminant). + * \param x_plus The root obtained from taking -sqrt(discriminant). + * \return The number of disticnt solutions to the equation. + */ + CGAL_DEPRECATED int _solve_quadratic_equation(const Algebraic& A, + const Algebraic& B, + const Algebraic& C, + Algebraic& x_minus, + Algebraic& x_plus) const { + // Check if we actually have a linear equation. + if (CGAL::sign(A) == ZERO) { + if (CGAL::sign(B) == ZERO) return (0); + x_minus = x_plus = -C / B; + return 1; + } + + // Compute the discriminant and act according to its sign. + const Algebraic disc = B*B - 4*A*C; + Sign sign_disc = CGAL::sign(disc); + + if (sign_disc == NEGATIVE) { + // No real-valued solutions: + return 0; + } + else if (sign_disc == ZERO) { + // One distinct solution: + x_minus = x_plus = -B / (2*A); + return 1; + } + + // Compute the two distinct solutions: + Algebraic _2A = 2*A; + Nt_traits nt_traits; + Algebraic sqrt_disc = nt_traits.sqrt (disc); + + x_minus = -(B + sqrt_disc) / _2A; + x_plus = (sqrt_disc - B) / _2A; + return 2; + } + + /*! Find the x coordinates of the underlying conic at a given y coordinate. + * \param y The y coordinate. + * \param xs The output x coordinates. + * \pre The vector xs must be allocated at the size of 2. + * \return The number of x coordinates computed (either 0, 1 or 2). + */ + CGAL_DEPRECATED + int _conic_get_x_coordinates(const Algebraic& y, Algebraic* xs) const { + // Solve the quadratic equation for a given y and find the x values: + // r*x^2 + (t*y + u)*x + (s*y^2 + v*y + w) = 0 + Nt_traits nt_traits; + Algebraic A = nt_traits.convert(m_r); + Algebraic B = nt_traits.convert(m_t)*y + nt_traits.convert(m_u); + Algebraic C = (nt_traits.convert(m_s)*y + + nt_traits.convert(m_v))*y + nt_traits.convert(m_w); + + return (_solve_quadratic_equation(A, B, C, xs[0], xs[1])); + } + + /*! Find all points on the arc with a given y-coordinate. + * \param p A placeholder for the y-coordinate. + * \param ps The point on the arc at x(p). + * \pre The vector ps should be allocated at the size of 2. + * \return The number of points found. + */ + CGAL_DEPRECATED int _points_at_y(const Point_2& p, Point_2* ps) const { + // Get the y coordinates of the points on the conic. + Algebraic xs[2]; + int n = _conic_get_x_coordinates(p.y(), xs); + + // Find all the points that are contained in the arc. + int m(0); + + for (int i = 0; i < n; ++i) { + ps[m] = Point_2 (xs[i], p.y()); + if (is_full_conic() || _is_between_endpoints(ps[m])) ++m; + } + + // Return the number of points on the arc. + CGAL_assertion(m <= 2); + return m; + } + + /*! Set the properties of a conic arc (for the usage of the constructors). + * \param rat_coeffs A vector of size 6, storing the rational coefficients + * of x^2, y^2, xy, x, y and the free coefficient resp. + */ + CGAL_DEPRECATED void _set(const Rational* rat_coeffs) { + set_flag(IS_VALID); + Nt_traits nt_traits; + + // Convert the coefficients vector to an equivalent vector of integer + // coefficients. + Integer int_coeffs[6]; + nt_traits.convert_coefficients(rat_coeffs, rat_coeffs + 6, int_coeffs); + + // Check the orientation of conic curve, and negate the conic coefficients + // if its given orientation. + typename Rat_kernel::Conic_2 temp_conic(rat_coeffs[0], rat_coeffs[1], + rat_coeffs[2], rat_coeffs[3], + rat_coeffs[4], rat_coeffs[5]); + + if (orientation() == temp_conic.orientation()) { + m_r = int_coeffs[0]; + m_s = int_coeffs[1]; + m_t = int_coeffs[2]; + m_u = int_coeffs[3]; + m_v = int_coeffs[4]; + m_w = int_coeffs[5]; + } + else { + m_r = -int_coeffs[0]; + m_s = -int_coeffs[1]; + m_t = -int_coeffs[2]; + m_u = -int_coeffs[3]; + m_v = -int_coeffs[4]; + m_w = -int_coeffs[5]; + } + + // Make sure both endpoint lie on the supporting conic. + if (! _is_on_supporting_conic(m_source) || + ! _is_on_supporting_conic(m_target)) + { + reset_flags(); // inavlid arc + return; + } + + // Check whether we have a degree 2 curve. + if ((CGAL::sign(m_r) != ZERO) || (CGAL::sign(m_s) != ZERO) || + (CGAL::sign(m_t) != ZERO)) + { + if (orientation() == COLLINEAR) { + // Make sure the midpoint is on the line pair (thus making sure that + // the two points are not taken from different lines). + Alg_kernel ker; + auto ctr_mid_point = ker.construct_midpoint_2_object(); + Point_2 p_mid = ctr_mid_point(m_source, m_target); + // if (! is_on_supporting_conic(arc, p_mid)) + if (CGAL::sign((nt_traits.convert(m_r)*p_mid.x() + + nt_traits.convert(m_t)*p_mid.y() + + nt_traits.convert(m_u)) * p_mid.x() + + (nt_traits.convert(m_s)*p_mid.y() + + nt_traits.convert(m_v)) * p_mid.y() + + nt_traits.convert(m_w)) != ZERO) + { + reset_flags(); // inavlid arc + return; + } + + // We have a segment of a line pair with rational coefficients. + // Compose the equation of the underlying line + // (with algebraic coefficients). + const Algebraic& x1 = m_source.x(); + const Algebraic& y1 = m_source.y(); + const Algebraic& x2 = m_target.x(); + const Algebraic& y2 = m_target.y(); + + // The supporting line is A*x + B*y + C = 0, where: + // + // A = y2 - y1, B = x1 - x2, C = x2*y1 - x1*y2 + // + // We use the extra dat field to store the equation of this line. + m_extra_data = new Extra_data; + m_extra_data->a = y2 - y1; + m_extra_data->b = x1 - x2; + m_extra_data->c = x2*y1 - x1*y2; + m_extra_data->side = ZERO; + } + else { + // The sign of (4rs - t^2) detetmines the conic type: + // - if it is possitive, the conic is an ellipse, + // - if it is negative, the conic is a hyperbola, + // - if it is zero, the conic is a parabola. + CGAL::Sign sign_conic = CGAL::sign(4*m_r*m_s - m_t*m_t); + + // Build the extra hyperbolic data if necessary + if (sign_conic == NEGATIVE) _build_hyperbolic_arc_data(); + + if (sign_conic != POSITIVE) { + // In case of a non-degenerate parabola or a hyperbola, make sure + // the arc is not infinite. + Alg_kernel ker; + Point_2 p_mid = ker.construct_midpoint_2_object()(m_source, m_target); + Point_2 ps[2]; + + bool finite_at_x = (_points_at_x(p_mid, ps) > 0); + bool finite_at_y = (_points_at_y(p_mid, ps) > 0); + + if (! finite_at_x && ! finite_at_y) { + reset_flags(); // inavlid arc + return; + } + } + } + } + + + set_flag(IS_VALID); // arc is valid + reset_flag(IS_FULL_CONIC); // not a full conic + } + public: /// \name Construction and destruction functions. //@{ /*! Default constructor. */ - _Conic_arc_2() : + Conic_arc_2() : m_r(0), m_s(0), m_t(0), m_u(0), m_v(0), m_w(0), m_orient(COLLINEAR), m_info(0), @@ -114,7 +1338,7 @@ public: /*! Copy constructor. * \param arc The copied arc. */ - _Conic_arc_2(const Self& arc) : + Conic_arc_2(const Self& arc) : m_r(arc.m_r), m_s(arc.m_s), m_t(arc.m_t), m_u(arc.m_u), m_v(arc.m_v), m_w(arc.m_w), m_orient(arc.m_orient), @@ -128,7 +1352,7 @@ public: /*! Destructor. */ - virtual ~_Conic_arc_2() { if (m_extra_data != nullptr) delete m_extra_data; } + virtual ~Conic_arc_2() { if (m_extra_data != nullptr) delete m_extra_data; } /*! Assignment operator. * \param arc The copied arc. @@ -266,7 +1490,7 @@ public: /*! Set the endpoints. */ - void set_endpoints(const Conic_point_2& source, const Conic_point_2& target) { + void set_endpoints(const Point_2& source, const Point_2& target) { m_source = source; m_target = target; } @@ -301,7 +1525,7 @@ public: template std::ostream& operator<< (std::ostream& os, - const _Conic_arc_2& arc) + const Conic_arc_2& arc) { os << "{" << CGAL::to_double(arc.r()) << "*x^2 + " << CGAL::to_double(arc.s()) << "*y^2 + " @@ -315,18 +1539,15 @@ operator<< (std::ostream& os, os << " : (" << CGAL::to_double(arc.source().x()) << "," << CGAL::to_double(arc.source().y()) << ") "; - if (arc.orientation() == CLOCKWISE) - os << "--cw-->"; - else if (arc.orientation() == COUNTERCLOCKWISE) - os << "--ccw-->"; - else - os << "--l-->"; + if (arc.orientation() == CLOCKWISE) os << "--cw-->"; + else if (arc.orientation() == COUNTERCLOCKWISE) os << "--ccw-->"; + else os << "--l-->"; os << " (" << CGAL::to_double(arc.target().x()) << "," << CGAL::to_double(arc.target().y()) << ")"; } - return (os); + return os; } } //namespace CGAL diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_point_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_point_2.h index 2e57b4269c4..6361c0bfe7c 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_point_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_point_2.h @@ -8,7 +8,8 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Ron Wein +// Author(s): Ron Wein +// Efi Fogel #ifndef CGAL_CONIC_POINT_2_H #define CGAL_CONIC_POINT_2_H @@ -16,7 +17,7 @@ #include /*! \file - * Header file for the _Conic_point_2 class. + * Header file for the Conic_point_2 class. */ #include @@ -30,11 +31,11 @@ namespace CGAL { * coordinates, namely the conic IDs of the generating curves. */ template -class _Conic_point_2 : public AlgKernel::Point_2 { +class Conic_point_2 : public AlgKernel::Point_2 { public: typedef AlgKernel Alg_kernel; typedef typename Alg_kernel::Point_2 Base; - typedef _Conic_point_2 Self; + typedef Conic_point_2 Self; typedef typename Alg_kernel::FT Algebraic; @@ -43,35 +44,29 @@ public: */ class Conic_id { private: - unsigned int index; // the index of the conic arc + size_t index; // the index of the conic arc public: /*! Default constructor. */ Conic_id() : index(0) {} /*! Constructor. */ - Conic_id(unsigned int ind) : - index (ind) - { CGAL_precondition(ind != 0); } + Conic_id(size_t ind) : index(ind) { CGAL_precondition(ind != 0); } /*! Check if the ID is valid. */ bool is_valid() const { return (index != 0); } /*! Equality operator. */ - bool operator==(const Conic_id& id) const - { return (index == id.index); } + bool operator==(const Conic_id& id) const { return (index == id.index); } /*! Inequality operator. */ - bool operator!=(const Conic_id& id) const - { return (index != id.index); } + bool operator!=(const Conic_id& id) const { return (index != id.index); } /*! Less-than operator. */ - bool operator< (const Conic_id& id) const - { return (index < id.index); } + bool operator<(const Conic_id& id) const { return (index < id.index); } /*! Greater-than operator. */ - bool operator>(const Conic_id& id) const - { return (index > id.index); } + bool operator>(const Conic_id& id) const { return (index > id.index); } }; private: @@ -85,20 +80,18 @@ public: //@{ /*! Default constructors. */ - _Conic_point_2() : Base() {} + Conic_point_2() : Base() {} /*! Constrcutor from the base class. */ - _Conic_point_2(const Base& p) : Base(p) {} + Conic_point_2(const Base& p) : Base(p) {} /*! Constructor with homegeneous coordinates. */ - _Conic_point_2(const Algebraic& hx, - const Algebraic& hy, - const Algebraic& hz) : + Conic_point_2(const Algebraic& hx, const Algebraic& hy, const Algebraic& hz) : Base(hx, hy, hz) {} /*! Constructor with Cartesian coordinates. */ - _Conic_point_2(const Algebraic& x, const Algebraic& y) : Base(x, y) {} + Conic_point_2(const Algebraic& x, const Algebraic& y) : Base(x, y) {} //@} /// \name Maintaining the generating conic IDs. diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h index cd993d7e7d0..53c2c62e440 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h @@ -7,7 +7,8 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s): Ron Wein +// Author(s): Ron Wein +// Efi Fogel #ifndef CGAL_CONIC_X_MONOTONE_ARC_2_H #define CGAL_CONIC_X_MONOTONE_ARC_2_H @@ -15,36 +16,30 @@ #include /*! \file - * Header file for the _Conic_x_monotone_arc_2 class. + * Header file for the Conic_x_monotone_arc_2 class. */ -#include #include -#include - -#include - namespace CGAL { /*! Representation of an x-monotone conic arc. * The class is templated by a representation of a general bounded conic arc. */ - template -class _Conic_x_monotone_arc_2 : public ConicArc { +class Conic_x_monotone_arc_2 : public ConicArc { public: - typedef ConicArc Conic_arc_2; - typedef _Conic_x_monotone_arc_2 Self; + typedef ConicArc Conic_arc_2; + typedef Conic_x_monotone_arc_2 Self; - typedef typename Conic_arc_2::Alg_kernel Alg_kernel; - typedef typename Conic_arc_2::Algebraic Algebraic; + typedef typename Conic_arc_2::Alg_kernel Alg_kernel; + typedef typename Conic_arc_2::Algebraic Algebraic; - typedef typename Conic_arc_2::Point_2 Point_2; - typedef typename Conic_arc_2::Conic_point_2 Conic_point_2; + typedef typename Conic_arc_2::Alg_point_2 Alg_point_2; + typedef typename Conic_arc_2::Point_2 Point_2; // Type definition for the intersection points mapping. - typedef typename Conic_point_2::Conic_id Conic_id; + typedef typename Point_2::Conic_id Conic_id; using Conic_arc_2::sign_of_extra_data; @@ -62,8 +57,6 @@ private: typedef Conic_arc_2 Base; typedef typename Conic_arc_2::Integer Integer; - typedef typename Conic_arc_2::Nt_traits Nt_traits; - typedef typename Conic_arc_2::Rat_kernel Rat_kernel; Algebraic m_alg_r; // The coefficients of the supporting conic curve: Algebraic m_alg_s; // @@ -91,20 +84,237 @@ public: FACING_MASK = (0x1 << FACING_UP) | (0x1 << FACING_DOWN) }; + /// \name Deprecated Constructions. + //@{ + + // /*! Construct an x-monotone arc from a conic arc. + // * \param arc The given (base) arc. + // * \param id The ID of the base arc. + // */ + // CGAL_DEPRECATED Conic_x_monotone_arc_2(const Base& arc, const Conic_id& id) : + // Base(arc), + // m_id(id) + // { + // CGAL_precondition(arc.is_valid() && id.is_valid()); + // _set(); + // } + + /*! Construct an x-monotone sub-arc from a conic arc. + * \param arc The given (base) arc. + * \param source The source point. + * \param target The target point. + * \param id The ID of the base arc. + */ + CGAL_DEPRECATED Conic_x_monotone_arc_2(const Base& arc, + const Point_2& source, + const Point_2& target, + const Conic_id& id) : + Base(arc), + m_id(id) + { + CGAL_precondition(arc.is_valid() && id.is_valid()); + set_endpoints(source, target); + _set(); + } + + /*! Construct a special segment connecting to given endpoints (for the usage + * of the landmarks point-location strategy). + * \param source The source point. + * \param target The target point. + */ + CGAL_DEPRECATED + Conic_x_monotone_arc_2(const Point_2& source, const Point_2& target) : + Base(source, target) + { + set_flag(DEGREE_1); + + Alg_kernel ker; + auto cmp_xy = ker.compare_xy_2_object(); + Comparison_result dir_res = cmp_xy(this->m_source, this->m_target); + if (dir_res == SMALLER) set_flag(IS_DIRECTED_RIGHT); + + // Check if the segment is vertical. + if (CGAL::sign(this->extra_data->b) == ZERO) set_flag(IS_SPECIAL_SEGMENT); + + // Mark that this is a special segment. + set_flag(IS_SPECIAL_SEGMENT); + } + + /*! Construct a special segment of a given line connecting to given + * endpoints. + * \param a, b, c The coefficients of the supporting line (ax + by + c = 0). + * \param source The source point. + * \param target The target point. + */ + CGAL_DEPRECATED + Conic_x_monotone_arc_2(const Algebraic& a, const Algebraic& b, + const Algebraic& c, + const Point_2& source, const Point_2& target) : + Base() + { + // Make sure the two endpoints lie on the supporting line. + CGAL_precondition(CGAL::sign(a * source.x() + b * source.y() + c) == + CGAL::ZERO); + + CGAL_precondition(CGAL::sign(a * target.x() + b * target.y() + c) == + CGAL::ZERO); + + // Set the basic properties and clear the _info bits. + this->m_source = source; + this->m_target = target; + this->m_orient = COLLINEAR; + reset_flags(); // inavlid arc + + // Check if the arc is directed right (the target is lexicographically + // greater than the source point), or to the left. + Alg_kernel ker; + Comparison_result res = + ker.compare_x_2_object()(this->source(), this->target()); + + set_flag(Base::IS_VALID); + set_flag(DEGREE_1); + if (res == EQUAL) { + // Mark that the segment is vertical. + set_flag(IS_VERTICAL_SEGMENT); + + // Compare the endpoints lexicographically. + res = ker.compare_y_2_object()(this->source(), this->target()); + + CGAL_precondition(res != EQUAL); + if (res == EQUAL) { + reset_flags(); // inavlid arc + return; + } + } + + if (res == SMALLER) set_flag(IS_DIRECTED_RIGHT); + + // Store the coefficients of the line. + this->m_extra_data = new typename Base::Extra_data; + this->m_extra_data->a = a; + this->m_extra_data->b = b; + this->m_extra_data->c = c; + this->m_extra_data->side = ZERO; + + // Mark that this is a special segment. + set_flag(IS_SPECIAL_SEGMENT); + } + //@} + +private: + /*! Set the properties of the x-monotone conic arc (for the usage of the + * constructors). + */ + CGAL_DEPRECATED void _set() { + // Convert the coefficients of the supporting conic to algebraic numbers. + typename Base::Nt_traits nt_traits; + + m_alg_r = nt_traits.convert(this->r()); + m_alg_s = nt_traits.convert(this->s()); + m_alg_t = nt_traits.convert(this->t()); + m_alg_u = nt_traits.convert(this->u()); + m_alg_v = nt_traits.convert(this->v()); + m_alg_w = nt_traits.convert(this->w()); + + // Set the generating conic ID for the source and target points. + this->m_source.set_generating_conic(m_id); + this->m_target.set_generating_conic(m_id); + + // Clear the _info bits. + set_flag(Base::IS_VALID); + reset_flag(Base::IS_FULL_CONIC); + + // Check if the arc is directed right (the target is lexicographically + // greater than the source point), or to the left. + Alg_kernel ker; + Comparison_result dir_res = + ker.compare_xy_2_object()(this->source(), this->target()); + + CGAL_assertion(dir_res != EQUAL); + + if (dir_res == SMALLER) set_flag(IS_DIRECTED_RIGHT); + + // Compute the degree of the underlying conic. + if (CGAL::sign(this->r()) != ZERO || + CGAL::sign(this->s()) != ZERO || + CGAL::sign(this->t()) != ZERO) + { + set_flag(DEGREE_2); + + if (this->m_orient == COLLINEAR) { + set_flag(IS_SPECIAL_SEGMENT); + + // The arc is a vertical segment: + if (ker.compare_x_2_object()(this->source(), this->target()) == EQUAL) + set_flag(IS_VERTICAL_SEGMENT); + return; + } + } + else { + CGAL_assertion(CGAL::sign(this->m_u) != ZERO || + CGAL::sign(this->m_v) != ZERO); + // The supporting curve is of the form: _u*x + _w = 0 + if (CGAL::sign(this->m_v) == ZERO) set_flag(IS_VERTICAL_SEGMENT); + set_flag(DEGREE_1); + return; + } + + if (this->m_orient == COLLINEAR) return; + + // Compute a midpoint between the source and the target and get the y-value + // of the arc at its x-coordiante. + Point_2 p_mid = + ker.construct_midpoint_2_object()(this->source(), this->target()); + Algebraic ys[2]; + CGAL_assertion_code(int n_ys = ) + this->_conic_get_y_coordinates(p_mid.x(), ys); + + CGAL_assertion(n_ys != 0); + + // Check which solution lies on the x-monotone arc. + Point_2 p_arc_mid(p_mid.x(), ys[0]); + + if (this->_is_strictly_between_endpoints(p_arc_mid)) { + // Mark that we should use the -sqrt(disc) root for points on this + // x-monotone arc. + reset_flag(PLUS_SQRT_DISC_ROOT); + } + else { + CGAL_assertion(n_ys == 2); + p_arc_mid = Point_2(p_mid.x(), ys[1]); + + CGAL_assertion(this->_is_strictly_between_endpoints(p_arc_mid)); + + // Mark that we should use the +sqrt(disc) root for points on this + // x-monotone arc. + set_flag(PLUS_SQRT_DISC_ROOT); + } + + // Check whether the conic is facing up or facing down: + // Check whether the arc (which is x-monotone of degree 2) lies above or + // below the segement that contects its two end-points (x1,y1) and (x2,y2). + // To do that, we find the y coordinate of a point on the arc whose x + // coordinate is (x1+x2)/2 and compare it to (y1+y2)/2. + Comparison_result res = ker.compare_y_2_object()(p_arc_mid, p_mid); + + // The arc is above the connecting segment, so it is facing upwards. + if (res == LARGER) set_flag(FACING_UP); + // The arc is below the connecting segment, so it is facing downwards. + else if (res == SMALLER) set_flag(FACING_DOWN); + } + +public: /// \name Public constrcutors, assignment operators, and destructors. //@{ /*! Default constructor. */ - _Conic_x_monotone_arc_2() : - Base(), - m_id() - {} + Conic_x_monotone_arc_2() : Base(), m_id() {} /*! Copy constructor. * \param arc The copied arc. */ - _Conic_x_monotone_arc_2(const Self& arc) : + Conic_x_monotone_arc_2(const Self& arc) : Base(arc), m_alg_r(arc.m_alg_r), m_alg_s(arc.m_alg_s), @@ -150,59 +360,24 @@ private: * \param arc The given (base) arc. * \pre The given arc is x-monotone. */ - _Conic_x_monotone_arc_2(const Base& arc) : Base(arc), m_id() {} + Conic_x_monotone_arc_2(const Base& arc) : Base(arc), m_id() {} /*! Construct an x-monotone arc from a conic arc. * \param arc The given (base) arc. * \param id The ID of the base arc. */ - _Conic_x_monotone_arc_2(const Base& arc, const Conic_id& id) : + Conic_x_monotone_arc_2(const Base& arc, const Conic_id& id) : Base(arc), m_id(id) {} - /*! Construct an x-monotone sub-arc from a conic arc. - * \param arc The given (base) arc. - * \param source The source point. - * \param target The target point. - * \param id The ID of the base arc. + /*! Obtain the non const reference to the curve source point. */ - _Conic_x_monotone_arc_2(const Base& arc, - const Point_2& source, const Point_2& target, - const Conic_id& id) : - Base(arc), - m_id(id) - {} - - /*! Construct a special segment connecting to given endpoints (for the usage - * of the landmarks point-location strategy). - * \param source The source point. - * \param target The target point. - */ - _Conic_x_monotone_arc_2(const Point_2& source, const Point_2& target) : - Base(source, target) - {} - - /*! Construct a special segment of a given line connecting to given - * endpoints. - * \param a, b, c The coefficients of the supporting line (ax + by + c = 0). - * \param source The source point. - * \param target The target point. - */ - _Conic_x_monotone_arc_2(const Algebraic& a, - const Algebraic& b, - const Algebraic& c, - const Point_2& source, const Point_2& target) : - Base() - {} + Point_2& source() { return (this->m_source); } /*! Obtain the non const reference to the curve source point. */ - Conic_point_2& source() { return (this->m_source); } - - /*! Obtain the non const reference to the curve source point. - */ - Conic_point_2& target() { return this->m_target; } + Point_2& target() { return this->m_target; } //@} public: @@ -229,12 +404,12 @@ public: /*! Obtain the arc's source. * \return The source point. */ - const Conic_point_2& source() const { return (this->m_source); } + const Point_2& source() const { return (this->m_source); } /*! Obtain the arc's target. * \return The target point. */ - const Conic_point_2& target() const { return this->m_target; } + const Point_2& target() const { return this->m_target; } /*! Obtain the orientation of the arc. * \return The orientation. @@ -243,14 +418,14 @@ public: /*! Obtain the left endpoint of the arc. */ - const Conic_point_2& left() const { + const Point_2& left() const { if (test_flag(IS_DIRECTED_RIGHT)) return this->m_source; else return this->m_target; } /*! Obtain the right endpoint of the arc. */ - const Conic_point_2& right() const { + const Point_2& right() const { if (test_flag(IS_DIRECTED_RIGHT)) return this->m_target; else return this->m_source; } @@ -300,7 +475,7 @@ public: /*! Obtain a bounding box for the conic arc. * \return The bounding box. */ - Bbox_2 bbox() const { return Base::bbox(); } + CGAL_DEPRECATED Bbox_2 bbox() const { return Base::bbox(); } //@} // Setters @@ -432,20 +607,14 @@ private: * \return (true) if p lies on the supporting conic; (false) otherwise. */ bool is_on_supporting_conic(const Algebraic& px, const Algebraic& py) const { - CGAL::Sign _sign; - - if (! is_special_segment()) { + CGAL::Sign _sign = (! is_special_segment()) ? // Check whether p satisfies the conic equation. // The point must satisfy: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0. - _sign = CGAL::sign((m_alg_r*px + m_alg_t*py + m_alg_u) * px + - (m_alg_s*py + m_alg_v) * py + m_alg_w); - } - else { + CGAL::sign((m_alg_r*px + m_alg_t*py + m_alg_u) * px + + (m_alg_s*py + m_alg_v) * py + m_alg_w) : // Check whether p satisfies the equation of the line stored with the // extra data. - _sign = sign_of_extra_data(px, py); - } - + sign_of_extra_data(px, py); return (_sign == ZERO); } @@ -457,7 +626,7 @@ public: * \param slope_denom The denominator of the slope. * \todo Allow higher order derivatives. */ - void derive_by_x_at(const Point_2& p, const unsigned int& i, + void derive_by_x_at(const Alg_point_2& p, const unsigned int& i, Algebraic& slope_numer, Algebraic& slope_denom) const { if (is_special_segment()) { // Special treatment for special segments, given by (a*x + b*y + c = 0), @@ -566,7 +735,7 @@ public: * \param slope_denom The denominator of the slope. * \todo Allow higher order derivatives. */ - void derive_by_y_at(const Point_2& p, const int& i, + void derive_by_y_at(const Alg_point_2& p, const int& i, Algebraic& slope_numer, Algebraic& slope_denom) const { if (is_special_segment()) { // Special treatment for special segments, given by (a*x + b*y + c = 0), @@ -675,7 +844,7 @@ private: * \return The multiplicity of the intersection point. */ unsigned int multiplicity_of_intersection_point(const Self& xcv, - const Point_2& p) const { + const Alg_point_2& p) const { CGAL_assertion(! is_special_segment() || ! xcv.is_special_segment()); // Compare the slopes of the two arcs at p, using their first-order @@ -724,7 +893,7 @@ private: */ template std::ostream& operator<<(std::ostream& os, - const _Conic_x_monotone_arc_2& xcv) + const Conic_x_monotone_arc_2& xcv) { // Output the supporting conic curve. os << "{" << CGAL::to_double(xcv.r()) << "*x^2 + " diff --git a/Surface_sweep_2/include/CGAL/Surface_sweep_2_algorithms.h b/Surface_sweep_2/include/CGAL/Surface_sweep_2_algorithms.h index f18f1018db3..62d6d31aaec 100644 --- a/Surface_sweep_2/include/CGAL/Surface_sweep_2_algorithms.h +++ b/Surface_sweep_2/include/CGAL/Surface_sweep_2_algorithms.h @@ -62,8 +62,8 @@ struct Default_arr_traits -struct Default_arr_traits > +struct Default_arr_traits > { typedef CGAL::Arr_conic_traits_2 Traits; diff --git a/Surface_sweep_2/test/Surface_sweep_2/test_sweep_conic.cpp b/Surface_sweep_2/test/Surface_sweep_2/test_sweep_conic.cpp index 260dd8738cc..90866e1a98d 100644 --- a/Surface_sweep_2/test/Surface_sweep_2/test_sweep_conic.cpp +++ b/Surface_sweep_2/test/Surface_sweep_2/test_sweep_conic.cpp @@ -47,7 +47,8 @@ private: Traits_2 m_traits; public: - int read_data(const char* filename, CurveList& curves, CGAL::Bbox_2& bbox) { + int read_data(const char* filename, CurveList& curves, CGAL::Bbox_2& bbox, + const Traits& traits) { Curve_2 cv; char dummy[256]; @@ -62,7 +63,7 @@ public: for (int i = 0; i < count; ++i) { read_curve(inp, cv); curves.push_back(cv); - CGAL::Bbox_2 curve_bbox = cv.bbox(); + CGAL::Bbox_2 curve_bbox = traits.construct_bbox_2_object()(cv); if (i == 0) bbox = curve_bbox; else bbox = bbox + curve_bbox; } @@ -177,11 +178,12 @@ int main(int argc, char* argv[]) { exit(1); } + Traits_2 traits; CGAL::Bbox_2 bbox; CurveList curves; Conic_reader reader; - reader.read_data(argv[1], curves, bbox); + reader.read_data(argv[1], curves, bbox, traits); // run the sweep std::list mylist; From fefbe9abd2ffbfed4cfb378ffff7e2a1e9c08f7f Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Mon, 20 Jun 2022 13:44:23 +0300 Subject: [PATCH 033/105] More clean ups and small bug fixes --- .../include/CGAL/Arr_conic_traits_2.h | 88 +++++++++++-------- .../CGAL/Arr_geometry_traits/Conic_arc_2.h | 14 +++ .../Conic_x_monotone_arc_2.h | 85 ++++++------------ 3 files changed, 93 insertions(+), 94 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index a21ea135aac..19ec43e8543 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -2271,22 +2271,42 @@ public: * \pre p and q must not be the same. * \return A segment connecting p and q. */ - X_monotone_curve_2 operator()(const Point_2& source, - const Point_2& target) const { - X_monotone_curve_2 xcv; - xcv->set_endpoints(source, target); - xcv.set_flag(X_monotone_curve_2::DEGREE_1); + X_monotone_curve_2 operator()(const Point_2& source, const Point_2& target) + const + { auto cmp_xy = m_traits.m_alg_kernel->compare_xy_2_object(); - Comparison_result dir_res = cmp_xy(source, target); - if (dir_res == SMALLER) - xcv.set_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT); + Comparison_result res = cmp_xy(source, target); + CGAL_precondition(res != EQUAL); + + X_monotone_curve_2 xcv; + // Set the properties. + xcv.set_endpoints(source, target); + xcv.set_orientation(COLLINEAR); + xcv.set_flag(Curve_2::IS_VALID); + xcv.set_flag(X_monotone_curve_2::DEGREE_1); + xcv.set_flag(X_monotone_curve_2::IS_SPECIAL_SEGMENT); + + if (res == SMALLER) xcv.set_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT); + + const Algebraic x1 = source.x(); + const Algebraic y1 = source.y(); + const Algebraic x2 = target.x(); + const Algebraic y2 = target.y(); + + // The supporting line is A*x + B*y + C = 0, where: + // A = y2 - y1, B = x1 - x2, C = x2*y1 - x1*y2 + // We use the extra data field to store the equation of this line. + auto extra_data = new typename Curve_2::Extra_data; + extra_data->a = y2 - y1; + extra_data->b = x1 - x2; + extra_data->c = x2*y1 - x1*y2; + extra_data->side = ZERO; + xcv.set_extra_data(extra_data); // Check if the segment is vertical. if (CGAL::sign(xcv.extra_data()->b) == ZERO) xcv.set_flag(X_monotone_curve_2::IS_VERTICAL_SEGMENT); - // Mark that this is a special segment. - xcv.set_flag(X_monotone_curve_2::IS_SPECIAL_SEGMENT); return xcv; } @@ -2296,49 +2316,43 @@ public: * \param source The source point. * \param target The target point. */ - X_monotone_curve_2 operator()(const Algebraic& a, - const Algebraic& b, + X_monotone_curve_2 operator()(const Algebraic& a, const Algebraic& b, const Algebraic& c, - const Point_2& source, - const Point_2& target) const { - X_monotone_curve_2 xcv(); + const Point_2& source, const Point_2& target) + const + { + CGAL_precondition_code(auto cmp_xy = + m_traits.m_alg_kernel->compare_xy_2_object()); + CGAL_precondition(cmp_xy(source, target) != EQUAL); + + X_monotone_curve_2 xcv; // Make sure the two endpoints lie on the supporting line. - CGAL_precondition - (CGAL::sign(a*source.x() + b*source.y() + c) == CGAL::ZERO); + CGAL_precondition(CGAL::sign(a*source.x()+b*source.y()+c) == CGAL::ZERO); + CGAL_precondition(CGAL::sign(a*target.x()+b*target.y()+c) == CGAL::ZERO); - CGAL_precondition - (CGAL::sign(a*target.x() + b*target.y() + c) == CGAL::ZERO); - - // Set the basic properties and clear the m_info bits. - xcv.set_source(source); - xcv.set_target(target); + // Set the properties. + xcv.set_endpoints(source, target); xcv.set_orientation(COLLINEAR); - xcv.reset_flags(); // inavlid arc + xcv.set_flag(Curve_2::IS_VALID); + xcv.set_flag(X_monotone_curve_2::DEGREE_1); + xcv.set_flag(X_monotone_curve_2::IS_SPECIAL_SEGMENT); // Check if the arc is directed right (the target is lexicographically // greater than the source point), or to the left. auto cmp_x = m_traits.m_alg_kernel->compare_x_2_object(); Comparison_result res = cmp_x(source, target); + if (res == SMALLER) xcv.set_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT); - xcv.set_flag(Curve_2::IS_VALID); - xcv.set_flag(X_monotone_curve_2::DEGREE_1); - if (res == EQUAL) { - // Mark that the segment is vertical. + // Check whether the segment is vertical. + else if (res == EQUAL) { xcv.set_flag(X_monotone_curve_2::IS_VERTICAL_SEGMENT); // Compare the endpoints lexicographically. auto cmp_y = m_traits.m_alg_kernel->compare_y_2_object(); res = cmp_y(source, target); - - CGAL_precondition(res != EQUAL); - if (res == EQUAL) { - xcv.reset_flags(); // inavlid arc - return xcv; - } + if (res == SMALLER) xcv.set_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT); } - if (res == SMALLER) xcv.set_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT); - // Store the coefficients of the line. auto extra_data = new typename Curve_2::Extra_data; extra_data->a = a; @@ -2347,8 +2361,6 @@ public: extra_data->side = ZERO; xcv.set_extra_data(extra_data); - // Mark that this is a special segment. - xcv.set_flag(X_monotone_curve_2::IS_SPECIAL_SEGMENT); return xcv; } diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h index 457739c9fb5..3eaf851cdcd 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h @@ -1413,6 +1413,13 @@ public: return m_source; } + /*! Obtain the non const reference to the curve source point. + */ + Point_2& source() { + CGAL_precondition(! is_full_conic()); + return (this->m_source); + } + /*! Obtain the arc's target. * \return The target point. * \pre The arc does not represent a full conic curve. @@ -1422,6 +1429,13 @@ public: return m_target; } + /*! Obtain the non const reference to the curve source point. + */ + Point_2& target() { + CGAL_precondition(! is_full_conic()); + return this->m_target; + } + /*! Obtain the orientation of the arc. * \return The orientation. */ diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h index 53c2c62e440..fdc8d6c6ff6 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h @@ -130,11 +130,11 @@ public: Alg_kernel ker; auto cmp_xy = ker.compare_xy_2_object(); - Comparison_result dir_res = cmp_xy(this->m_source, this->m_target); + Comparison_result dir_res = cmp_xy(source, target); if (dir_res == SMALLER) set_flag(IS_DIRECTED_RIGHT); // Check if the segment is vertical. - if (CGAL::sign(this->extra_data->b) == ZERO) set_flag(IS_SPECIAL_SEGMENT); + if (CGAL::sign(this->extra_data->b) == ZERO) set_flag(IS_VERTICAL_SEGMENT); // Mark that this is a special segment. set_flag(IS_SPECIAL_SEGMENT); @@ -160,16 +160,14 @@ public: CGAL::ZERO); // Set the basic properties and clear the _info bits. - this->m_source = source; - this->m_target = target; - this->m_orient = COLLINEAR; - reset_flags(); // inavlid arc + this->set_endpoints(source, target); + this->set_orientation(COLLINEAR); + this->reset_flags(); // inavlid arc // Check if the arc is directed right (the target is lexicographically // greater than the source point), or to the left. Alg_kernel ker; - Comparison_result res = - ker.compare_x_2_object()(this->source(), this->target()); + Comparison_result res = ker.compare_x_2_object()(source, target); set_flag(Base::IS_VALID); set_flag(DEGREE_1); @@ -178,8 +176,7 @@ public: set_flag(IS_VERTICAL_SEGMENT); // Compare the endpoints lexicographically. - res = ker.compare_y_2_object()(this->source(), this->target()); - + res = ker.compare_y_2_object()(source, target); CGAL_precondition(res != EQUAL); if (res == EQUAL) { reset_flags(); // inavlid arc @@ -221,8 +218,8 @@ private: this->m_target.set_generating_conic(m_id); // Clear the _info bits. - set_flag(Base::IS_VALID); - reset_flag(Base::IS_FULL_CONIC); + this->set_flag(Base::IS_VALID); + this->reset_flag(Base::IS_FULL_CONIC); // Check if the arc is directed right (the target is lexicographically // greater than the source point), or to the left. @@ -254,8 +251,8 @@ private: CGAL_assertion(CGAL::sign(this->m_u) != ZERO || CGAL::sign(this->m_v) != ZERO); // The supporting curve is of the form: _u*x + _w = 0 - if (CGAL::sign(this->m_v) == ZERO) set_flag(IS_VERTICAL_SEGMENT); - set_flag(DEGREE_1); + if (CGAL::sign(this->m_v) == ZERO) this->set_flag(IS_VERTICAL_SEGMENT); + this->set_flag(DEGREE_1); return; } @@ -277,7 +274,7 @@ private: if (this->_is_strictly_between_endpoints(p_arc_mid)) { // Mark that we should use the -sqrt(disc) root for points on this // x-monotone arc. - reset_flag(PLUS_SQRT_DISC_ROOT); + this->reset_flag(PLUS_SQRT_DISC_ROOT); } else { CGAL_assertion(n_ys == 2); @@ -287,7 +284,7 @@ private: // Mark that we should use the +sqrt(disc) root for points on this // x-monotone arc. - set_flag(PLUS_SQRT_DISC_ROOT); + this->set_flag(PLUS_SQRT_DISC_ROOT); } // Check whether the conic is facing up or facing down: @@ -296,11 +293,10 @@ private: // To do that, we find the y coordinate of a point on the arc whose x // coordinate is (x1+x2)/2 and compare it to (y1+y2)/2. Comparison_result res = ker.compare_y_2_object()(p_arc_mid, p_mid); - // The arc is above the connecting segment, so it is facing upwards. - if (res == LARGER) set_flag(FACING_UP); + if (res == LARGER) this->set_flag(FACING_UP); // The arc is below the connecting segment, so it is facing downwards. - else if (res == SMALLER) set_flag(FACING_DOWN); + else if (res == SMALLER) this->set_flag(FACING_DOWN); } public: @@ -370,14 +366,6 @@ private: Base(arc), m_id(id) {} - - /*! Obtain the non const reference to the curve source point. - */ - Point_2& source() { return (this->m_source); } - - /*! Obtain the non const reference to the curve source point. - */ - Point_2& target() { return this->m_target; } //@} public: @@ -401,55 +389,40 @@ public: const Integer& v() const { return ( this->m_v); } const Integer& w() const { return ( this->m_w); } - /*! Obtain the arc's source. - * \return The source point. - */ - const Point_2& source() const { return (this->m_source); } - - /*! Obtain the arc's target. - * \return The target point. - */ - const Point_2& target() const { return this->m_target; } - - /*! Obtain the orientation of the arc. - * \return The orientation. - */ - Orientation orientation() const { return this->m_orient; } - /*! Obtain the left endpoint of the arc. */ const Point_2& left() const { - if (test_flag(IS_DIRECTED_RIGHT)) return this->m_source; - else return this->m_target; + if (this->test_flag(IS_DIRECTED_RIGHT)) return this->source(); + else return this->target(); } /*! Obtain the right endpoint of the arc. */ const Point_2& right() const { - if (test_flag(IS_DIRECTED_RIGHT)) return this->m_target; - else return this->m_source; + if (this->test_flag(IS_DIRECTED_RIGHT)) return this->target(); + else return this->source(); } /*! Determine whether the conic arc is directed iexicographically right. */ - bool is_directed_right() const { return test_flag(IS_DIRECTED_RIGHT); } + bool is_directed_right() const { return this->test_flag(IS_DIRECTED_RIGHT); } /*! Determine whether the conic arc is a vertical segment. */ - bool is_vertical() const { return test_flag(IS_VERTICAL_SEGMENT); } + bool is_vertical() const { return this->test_flag(IS_VERTICAL_SEGMENT); } /*! Determine whether the conic arc is a facing up. */ - bool is_upper() const { return test_flag(FACING_UP); } + bool is_upper() const { return this->test_flag(FACING_UP); } /*! Determine whether the conic arc is a facing down. */ - bool is_lower() const { return test_flag(FACING_DOWN); } + bool is_lower() const { return this->test_flag(FACING_DOWN); } /*! Check whether the arc is a special segment connecting two algebraic * endpoints (and has no undelying integer conic coefficients). */ - bool is_special_segment() const { return test_flag(IS_SPECIAL_SEGMENT); } + bool is_special_segment() const { return this->test_flag(IS_SPECIAL_SEGMENT); } /*! Obtain the mask of the DEGREE_1 flag. */ @@ -607,7 +580,7 @@ private: * \return (true) if p lies on the supporting conic; (false) otherwise. */ bool is_on_supporting_conic(const Algebraic& px, const Algebraic& py) const { - CGAL::Sign _sign = (! is_special_segment()) ? + CGAL::Sign my_sign = (! is_special_segment()) ? // Check whether p satisfies the conic equation. // The point must satisfy: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0. CGAL::sign((m_alg_r*px + m_alg_t*py + m_alg_u) * px + @@ -615,7 +588,7 @@ private: // Check whether p satisfies the equation of the line stored with the // extra data. sign_of_extra_data(px, py); - return (_sign == ZERO); + return (my_sign == ZERO); } public: @@ -633,7 +606,7 @@ public: // so their first-order derivative by x is simply -a/b. The higher-order // derivatives are all 0. if (i == 1) { - if (CGAL::sign (this->m_extra_data->b) != NEGATIVE) { + if (CGAL::sign(this->m_extra_data->b) != NEGATIVE) { slope_numer = - this->m_extra_data->a; slope_denom = this->m_extra_data->b; } @@ -843,8 +816,8 @@ private: * \param p The intersection point. * \return The multiplicity of the intersection point. */ - unsigned int multiplicity_of_intersection_point(const Self& xcv, - const Alg_point_2& p) const { + size_t multiplicity_of_intersection_point(const Self& xcv, + const Alg_point_2& p) const { CGAL_assertion(! is_special_segment() || ! xcv.is_special_segment()); // Compare the slopes of the two arcs at p, using their first-order From 27d2bd5f21631dddf15b7afe8ed3013058c1108e Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Mon, 20 Jun 2022 17:51:11 +0300 Subject: [PATCH 034/105] More clean ups --- .../include/CGAL/Arr_conic_traits_2.h | 382 +++++++----------- .../CGAL/Arr_geometry_traits/Conic_arc_2.h | 31 +- .../Conic_intersections_2.h | 9 +- 3 files changed, 191 insertions(+), 231 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index 19ec43e8543..725c1e18603 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -268,7 +268,7 @@ public: public: /*! Return the location of the given point with respect to the input curve. - * \param cv The curve. + * \param xcv The curve. * \param p The point. * \pre p is in the x-range of cv. * \return SMALLER if y(p) < cv(x(p)), i.e. the point is below the curve; @@ -380,7 +380,7 @@ public: // We take either the root involving -sqrt(disc) or +sqrt(disc) // based on the information flags. - auto nt_traits = m_traits.m_nt_traits; + const auto nt_traits = m_traits.m_nt_traits; y = (xcv.test_flag(X_monotone_curve_2::PLUS_SQRT_DISC_ROOT)) ? (nt_traits->sqrt(disc) - B) / (2*A) : -(B + nt_traits->sqrt(disc)) / (2*A); @@ -1192,9 +1192,11 @@ public: return; } - const int deg1 = (xcv1.degree_mask() == X_monotone_curve_2::degree_1_mask()) ? 1 : 2; - const int deg2 = (xcv2.degree_mask() == X_monotone_curve_2::degree_1_mask()) ? 1 : 2; - Nt_traits nt_traits; + const int deg1 = + (xcv1.degree_mask() == X_monotone_curve_2::degree_1_mask()) ? 1 : 2; + const int deg2 = + (xcv2.degree_mask() == X_monotone_curve_2::degree_1_mask()) ? 1 : 2; + const auto nt_traits = m_traits.m_nt_traits; Algebraic xs[4]; int n_xs = 0; Algebraic ys[4]; @@ -1223,7 +1225,7 @@ public: const auto* extra_data2 = xcv2.extra_data(); // Compute the x-coordinates of the intersection points. - n_xs = compute_resultant_roots(nt_traits, + n_xs = compute_resultant_roots(*nt_traits, xcv1.alg_r(), xcv1.alg_s(), xcv1.alg_t(), xcv1.alg_u(), xcv1.alg_v(), xcv1.alg_w(), @@ -1235,7 +1237,7 @@ public: CGAL_assertion(n_xs <= 2); // Compute the y-coordinates of the intersection points. - n_ys = compute_resultant_roots(nt_traits, + n_ys = compute_resultant_roots(*nt_traits, xcv1.alg_s(), xcv1.alg_r(), xcv1.alg_t(), xcv1.alg_v(), xcv1.alg_u(), xcv1.alg_w(), @@ -1249,7 +1251,7 @@ public: } else { // Compute the x-coordinates of the intersection points. - n_xs = compute_resultant_roots(nt_traits, + n_xs = compute_resultant_roots(*nt_traits, xcv1.r(), xcv1.s(), xcv1.t(), xcv1.u(), xcv1.v(), xcv1.w(), deg1, @@ -1260,7 +1262,7 @@ public: CGAL_assertion(n_xs <= 4); // Compute the y-coordinates of the intersection points. - n_ys = compute_resultant_roots(nt_traits, + n_ys = compute_resultant_roots(*nt_traits, xcv1.s(), xcv1.r(), xcv1.t(), xcv1.v(), xcv1.u(), xcv1.w(), deg1, @@ -1751,7 +1753,7 @@ public: auto numerator = -4*w_m*r_m*s_m + s_m*u_m*u_m + r_m*v_m*v_m; auto a_sqr = numerator / (4*r_m*r_m*s_m); auto b_sqr = numerator / (4*r_m*s_m*s_m); - if (a_sqr < 0) { + if (a_sqr < b_sqr) { // Shift phase: auto tmp(cost); cost = sint; @@ -1763,7 +1765,7 @@ public: cy_m = -v_m / (2*s_m); numerator = -4*w_m*r_m*s_m + s_m*u_m*u_m + r_m*v_m*v_m; a_sqr = numerator / (4*r_m*r_m*s_m); - b_sqr = -numerator / (4*r_m*s_m*s_m); + b_sqr = numerator / (4*r_m*s_m*s_m); } auto a = std::sqrt(a_sqr); @@ -2274,36 +2276,24 @@ public: X_monotone_curve_2 operator()(const Point_2& source, const Point_2& target) const { - auto cmp_xy = m_traits.m_alg_kernel->compare_xy_2_object(); - Comparison_result res = cmp_xy(source, target); - CGAL_precondition(res != EQUAL); - X_monotone_curve_2 xcv; - // Set the properties. + + // Set the basic properties. xcv.set_endpoints(source, target); xcv.set_orientation(COLLINEAR); xcv.set_flag(Curve_2::IS_VALID); + + // Set the other properties. xcv.set_flag(X_monotone_curve_2::DEGREE_1); xcv.set_flag(X_monotone_curve_2::IS_SPECIAL_SEGMENT); + xcv.update_extra_data(); + auto cmp_xy = m_traits.m_alg_kernel->compare_xy_2_object(); + Comparison_result res = cmp_xy(source, target); + CGAL_precondition(res != EQUAL); if (res == SMALLER) xcv.set_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT); - const Algebraic x1 = source.x(); - const Algebraic y1 = source.y(); - const Algebraic x2 = target.x(); - const Algebraic y2 = target.y(); - - // The supporting line is A*x + B*y + C = 0, where: - // A = y2 - y1, B = x1 - x2, C = x2*y1 - x1*y2 - // We use the extra data field to store the equation of this line. - auto extra_data = new typename Curve_2::Extra_data; - extra_data->a = y2 - y1; - extra_data->b = x1 - x2; - extra_data->c = x2*y1 - x1*y2; - extra_data->side = ZERO; - xcv.set_extra_data(extra_data); - - // Check if the segment is vertical. + // Check whether the segment is vertical. if (CGAL::sign(xcv.extra_data()->b) == ZERO) xcv.set_flag(X_monotone_curve_2::IS_VERTICAL_SEGMENT); @@ -2321,46 +2311,31 @@ public: const Point_2& source, const Point_2& target) const { - CGAL_precondition_code(auto cmp_xy = - m_traits.m_alg_kernel->compare_xy_2_object()); - CGAL_precondition(cmp_xy(source, target) != EQUAL); + auto cmp_xy = m_traits.m_alg_kernel->compare_xy_2_object(); + Comparison_result res = cmp_xy(source, target); + CGAL_precondition(res != EQUAL); X_monotone_curve_2 xcv; // Make sure the two endpoints lie on the supporting line. CGAL_precondition(CGAL::sign(a*source.x()+b*source.y()+c) == CGAL::ZERO); CGAL_precondition(CGAL::sign(a*target.x()+b*target.y()+c) == CGAL::ZERO); - // Set the properties. + // Set the basic properties. xcv.set_endpoints(source, target); xcv.set_orientation(COLLINEAR); xcv.set_flag(Curve_2::IS_VALID); - xcv.set_flag(X_monotone_curve_2::DEGREE_1); - xcv.set_flag(X_monotone_curve_2::IS_SPECIAL_SEGMENT); - // Check if the arc is directed right (the target is lexicographically - // greater than the source point), or to the left. - auto cmp_x = m_traits.m_alg_kernel->compare_x_2_object(); - Comparison_result res = cmp_x(source, target); + // Set the other properties. if (res == SMALLER) xcv.set_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT); + xcv.set_flag(X_monotone_curve_2::DEGREE_1); + xcv.set_flag(X_monotone_curve_2::IS_SPECIAL_SEGMENT); + xcv.set_extra_data(a, b, c, ZERO); + // Check whether the segment is vertical. - else if (res == EQUAL) { + if (CGAL::sign(xcv.extra_data()->b) == ZERO) xcv.set_flag(X_monotone_curve_2::IS_VERTICAL_SEGMENT); - // Compare the endpoints lexicographically. - auto cmp_y = m_traits.m_alg_kernel->compare_y_2_object(); - res = cmp_y(source, target); - if (res == SMALLER) xcv.set_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT); - } - - // Store the coefficients of the line. - auto extra_data = new typename Curve_2::Extra_data; - extra_data->a = a; - extra_data->b = b; - extra_data->c = c; - extra_data->side = ZERO; - xcv.set_extra_data(extra_data); - return xcv; } @@ -2478,18 +2453,18 @@ public: const auto nt_traits = m_traits.m_nt_traits; const auto alg_kernel = m_traits.m_alg_kernel; - auto source = Point_2(nt_traits->convert(x1), nt_traits->convert(y1)); - auto target = Point_2(nt_traits->convert(x3), nt_traits->convert(y3)); + Point_2 source(nt_traits->convert(x1), nt_traits->convert(y1)); + Point_2 target(nt_traits->convert(x3), nt_traits->convert(y3)); arc.set_endpoints(source, target); // Make sure that the source and the taget are not the same. - CGAL_precondition(alg_kernel->compare_xy_2_object()(source, target) != - EQUAL); + CGAL_precondition_code(auto cmp_xy = alg_kernel->compare_xy_2_object()); + CGAL_precondition(cmp_xy(source, target) != EQUAL); // Compute the lines: A1*x + B1*y + C1 = 0, // and: A2*x + B2*y + C2 = 0, // where: - const Rational two = 2; + const Rational two(2); const Rational A1 = two*(x1 - x2); const Rational B1 = two*(y1 - y2); @@ -2528,7 +2503,7 @@ public: // counterclockwise). // Otherwise, it is negative (going clockwise). auto orient_f = alg_kernel->orientation_2_object(); - Point_2 p_mid = Point_2(nt_traits->convert(x2), nt_traits->convert(y2)); + Point_2 p_mid(nt_traits->convert(x2), nt_traits->convert(y2)); auto orient = (orient_f(source, p_mid, target) == LEFT_TURN) ? COUNTERCLOCKWISE : CLOCKWISE; @@ -2577,8 +2552,8 @@ public: const Rational& y5 = p5.y(); const auto nt_traits = m_traits.m_nt_traits; - auto source = Point_2(nt_traits->convert(x1), nt_traits->convert(y1)); - auto target = Point_2(nt_traits->convert(x5), nt_traits->convert(y5)); + Point_2 source(nt_traits->convert(x1), nt_traits->convert(y1)); + Point_2 target(nt_traits->convert(x5), nt_traits->convert(y5)); arc.set_endpoints(source, target); // Set a conic curve that passes through the five given point. @@ -2616,12 +2591,9 @@ public: // Make sure that all midpoints are strictly between the // source and the target. - Point_2 mp2 = - Point_2(nt_traits->convert(p2.x()), nt_traits->convert(p2.y())); - Point_2 mp3 = - Point_2(nt_traits->convert(p3.x()), m_nt_traits->convert(p3.y())); - Point_2 mp4 = - Point_2(nt_traits->convert(p4.x()), nt_traits->convert(p4.y())); + Point_2 mp2(nt_traits->convert(p2.x()), nt_traits->convert(p2.y())); + Point_2 mp3(nt_traits->convert(p3.x()), m_nt_traits->convert(p3.y())); + Point_2 mp4(nt_traits->convert(p4.x()), nt_traits->convert(p4.y())); if (! m_traits.is_strictly_between_endpoints(arc, mp2) || ! m_traits.is_strictly_between_endpoints(arc, mp3) || @@ -2795,45 +2767,31 @@ public: } /*! Return a curve connecting the two given endpoints. - * \param p The first point. - * \param q The second point. + * \param source The source point. + * \param target The target point. * \pre p and q must not be the same. * \return A segment connecting p and q. */ - Curve_2 operator()(const Point_2& p, const Point_2& q) const { + Curve_2 operator()(const Point_2& source, const Point_2& target) const { const auto alg_kernel = m_traits.m_alg_kernel; - CGAL_precondition(alg_kernel->compare_xy_2_object()(p, q) != EQUAL); + CGAL_precondition_code(auto cmp_xy = alg_kernel->compare_xy_2_object()); + CGAL_precondition(cmp_xy(source, target) != EQUAL); - Curve_2 arc; - set_orientation(Curve_2::COLLINEAR); - arc.set_flag(Curve_2::IS_VALID); - arc.set_source(p); - arc.set_target(q); - - // Compose the equation of the underlying line. - const Algebraic& x1 = p.x(); - const Algebraic& y1 = p.y(); - const Algebraic& x2 = q.x(); - const Algebraic& y2 = q.y(); - - // The supporting line is A*x + B*y + C = 0, where: - // A = y2 - y1, B = x1 - x2, C = x2*y1 - x1*y2 - // We use the extra data field to store the equation of this line. - auto* extra_data = new typename Curve_2::Extra_data; - extra_data->a = y2 - y1; - extra_data->b = x1 - x2; - extra_data->c = x2*y1 - x1*y2; - extra_data->side = ZERO; - arc.set_extra_data(extra_data); - return arc; + Curve_2 cv; + cv.set_coefficients(0, 0, 0, 0, 0, 0); + cv.set_orientation(COLLINEAR); + cv.set_flag(Curve_2::IS_VALID); + cv.set_endpoints(source, target); + cv.update_extra_data(); + return cv; } /*! Construct a conic arc from a given line segment. * \param seg The line segment with rational endpoints. */ Curve_2 operator()(const Rat_segment_2& seg) const { - Curve_2 arc; - arc.set_orientation(COLLINEAR); + Curve_2 cv; + cv.set_orientation(COLLINEAR); // Set the source and target. const auto rat_kernel = m_traits.m_rat_kernel; @@ -2845,12 +2803,12 @@ public: const Rational& y2 = target.y(); const auto nt_traits = m_traits.m_nt_traits; - arc.set_source(Point_2(nt_traits->convert(x1), nt_traits->convert(y1))); - arc.set_target(Point_2(nt_traits->convert(x2), nt_traits->convert(y2))); + cv.set_source(Point_2(nt_traits->convert(x1), nt_traits->convert(y1))); + cv.set_target(Point_2(nt_traits->convert(x2), nt_traits->convert(y2))); // Make sure that the source and the taget are not the same. - CGAL_precondition(rat_kernel->compare_xy_2_object()(source, target) != - EQUAL); + CGAL_precondition_code(auto cmp_xy = rat_kernel->compare_xy_2_object()); + CGAL_precondition(cmp_xy(source, target) != EQUAL); // The supporting conic is r=s=t=0, and u*x + v*y + w = 0 should hold // for both the source (x1,y1) and the target (x2, y2). @@ -2879,16 +2837,16 @@ public: } // Set the arc properties (no need to compute the orientation). - m_traits.set(arc, rat_coeffs); - return arc; + m_traits.set(cv, rat_coeffs); + return cv; } /*! Construct a conic arc that is a full circle. * \param circ The circle with rational center and rational squared radius. */ Curve_2 operator()(const Rat_circle_2& circ) const { - Curve_2 arc; - arc.set_orientation(CLOCKWISE); + Curve_2 cv; + cv.set_orientation(CLOCKWISE); // Get the circle properties. const auto rat_kernel = m_traits.m_rat_kernel; @@ -2914,8 +2872,8 @@ public: rat_coeffs[5] = x0*x0 + y0*y0 - r_sqr; // Set the arc to be the full conic (no need to compute the orientation). - m_traits.set_full(arc, rat_coeffs, false); - return arc; + m_traits.set_full(cv, rat_coeffs, false); + return cv; } /*! Construct a conic arc that lies on a given circle: @@ -2928,14 +2886,16 @@ public: */ Curve_2 operator()(const Rat_circle_2& circ, const Orientation& orient, const Point_2& source, const Point_2& target) const { + // Make sure that the source and the taget are not the same. - CGAL_precondition_code(auto cmp_xy = m_traits.m_alg_kernel->compare_xy_2_object()); + CGAL_precondition_code(auto cmp_xy = + m_traits.m_alg_kernel->compare_xy_2_object()); CGAL_precondition(cmp_xy(source, target) != EQUAL); CGAL_precondition(orient != COLLINEAR); - Curve_2 arc; - arc.set_endpoints(source, target); - arc.set_orientation(orient); + Curve_2 cv; + cv.set_endpoints(source, target); + cv.set_orientation(orient); // Get the circle properties. const auto rat_kernel = m_traits.m_rat_kernel; @@ -2953,7 +2913,7 @@ public: const Rational zero(0); Rational rat_coeffs[6]; - if (arc.orientation() == COUNTERCLOCKWISE) { + if (cv.orientation() == COUNTERCLOCKWISE) { const Rational minus_one(-1); const Rational two(2); @@ -2977,8 +2937,8 @@ public: } // Set the arc properties (no need to compute the orientation). - m_traits.set(arc, rat_coeffs); - return arc; + m_traits.set(cv, rat_coeffs); + return cv; } }; @@ -2998,10 +2958,8 @@ public: * \return SMALLER if the curve is directed right; * LARGER if the curve is directed left. */ - Comparison_result operator()(const X_monotone_curve_2& cv) const { - if (cv.is_directed_right()) return SMALLER; - else return LARGER; - } + Comparison_result operator()(const X_monotone_curve_2& cv) const + { return (cv.is_directed_right()) ? SMALLER : LARGER; } }; /*! Obtain a Compare_endpoints_xy_2 functor object. */ @@ -3038,7 +2996,7 @@ public: public: /*!\brief - * Returns a trimmed version of an arc + * Returns a trimmed version of an cv * * \param xcv The arc * \param src the new first endpoint @@ -3063,10 +3021,9 @@ public: CGAL_precondition(! equal_2(src, tgt)); //check if the orientation conforms to the src and tgt. - if( (xcv.is_directed_right() && compare_x_2(src, tgt) == LARGER) || - (! xcv.is_directed_right() && compare_x_2(src, tgt) == SMALLER) ) - return trim(xcv, tgt, src); - else return trim(xcv, src, tgt); + return ((xcv.is_directed_right() && compare_x_2(src, tgt) == LARGER) || + (! xcv.is_directed_right() && compare_x_2(src, tgt) == SMALLER)) ? + trim(xcv, tgt, src) : trim(xcv, src, tgt); } private: @@ -3236,8 +3193,8 @@ public: * \param rat_coeffs A vector of size 6, storing the rational coefficients * of x^2, y^2, xy, x, y and the free coefficient resp. */ - void set(Curve_2& arc, const Rational* rat_coeffs) const { - arc.set_flag(Curve_2::IS_VALID); + void set(Curve_2& cv, const Rational* rat_coeffs) const { + cv.set_flag(Curve_2::IS_VALID); // Convert the coefficients vector to an equivalent vector of integer // coefficients. @@ -3252,7 +3209,7 @@ public: Integer r, s, t, u, v, w; - if (arc.orientation() == temp_conic.orientation()) { + if (cv.orientation() == temp_conic.orientation()) { r = int_coeffs[0]; s = int_coeffs[1]; t = int_coeffs[2]; @@ -3268,15 +3225,15 @@ public: v = -int_coeffs[4]; w = -int_coeffs[5]; } - arc.set_coefficients(r, s, t, u, v, w); + cv.set_coefficients(r, s, t, u, v, w); - const auto& source = arc.source(); - const auto& target = arc.target(); + const auto& source = cv.source(); + const auto& target = cv.target(); // Make sure both endpoint lie on the supporting conic. - if (! is_on_supporting_conic(arc, source) || - ! is_on_supporting_conic(arc, target)) + if (! is_on_supporting_conic(cv, source) || + ! is_on_supporting_conic(cv, target)) { - arc.reset_flags(); // inavlid arc + cv.reset_flags(); // inavlid arc return; } @@ -3284,7 +3241,7 @@ public: if ((CGAL::sign(r) != ZERO) || (CGAL::sign(s) != ZERO) || (CGAL::sign(t) != ZERO)) { - if (arc.orientation() == COLLINEAR) { + if (cv.orientation() == COLLINEAR) { // Make sure the midpoint is on the line pair (thus making sure that // the two points are not taken from different lines). auto ctr_mid_point = m_alg_kernel->construct_midpoint_2_object(); @@ -3297,29 +3254,14 @@ public: m_nt_traits->convert(v)) * p_mid.y() + m_nt_traits->convert(w)) != ZERO) { - arc.reset_flags(); // inavlid arc + cv.reset_flags(); // inavlid arc return; } // We have a segment of a line pair with rational coefficients. // Compose the equation of the underlying line // (with algebraic coefficients). - const Algebraic& x1 = source.x(); - const Algebraic& y1 = source.y(); - const Algebraic& x2 = target.x(); - const Algebraic& y2 = target.y(); - - // The supporting line is A*x + B*y + C = 0, where: - // - // A = y2 - y1, B = x1 - x2, C = x2*y1 - x1*y2 - // - // We use the extra dat field to store the equation of this line. - auto* extra_data = new typename Curve_2::Extra_data; - extra_data->a = y2 - y1; - extra_data->b = x1 - x2; - extra_data->c = x2*y1 - x1*y2; - extra_data->side = ZERO; - arc.set_extra_data(extra_data); + cv.update_extra_data(); } else { // The sign of (4rs - t^2) detetmines the conic type: @@ -3329,7 +3271,7 @@ public: CGAL::Sign sign_conic = CGAL::sign(4*r*s - t*t); // Build the extra hyperbolic data if necessary - if (sign_conic == NEGATIVE) build_hyperbolic_arc_data(arc); + if (sign_conic == NEGATIVE) build_hyperbolic_arc_data(cv); if (sign_conic != POSITIVE) { // In case of a non-degenerate parabola or a hyperbola, make sure @@ -3337,12 +3279,10 @@ public: Point_2 p_mid = m_alg_kernel->construct_midpoint_2_object()(source, target); Point_2 ps[2]; - - bool finite_at_x = (points_at_x(arc, p_mid, ps) > 0); - bool finite_at_y = (points_at_y(arc, p_mid, ps) > 0); - + bool finite_at_x = (points_at_x(cv, p_mid, ps) > 0); + bool finite_at_y = (points_at_y(cv, p_mid, ps) > 0); if (! finite_at_x && ! finite_at_y) { - arc.reset_flags(); // inavlid arc + cv.reset_flags(); // inavlid arc return; } } @@ -3350,8 +3290,8 @@ public: } - arc.set_flag(Curve_2::IS_VALID); // arc is valid - arc.reset_flag(Curve_2::IS_FULL_CONIC); // not a full conic + cv.set_flag(Curve_2::IS_VALID); // arc is valid + cv.reset_flag(Curve_2::IS_FULL_CONIC); // not a full conic } /*! Set the properties of a conic arc that is really a full curve @@ -3360,7 +3300,7 @@ public: * of x^2, y^2, xy, x, y and the free coefficient resp. * \param comp_orient Should we compute the orientation of the given curve. */ - void set_full(Curve_2& arc, const Rational* rat_coeffs, + void set_full(Curve_2& cv, const Rational* rat_coeffs, const bool& comp_orient) const { // Convert the coefficients vector to an equivalent vector of integer // coefficients. @@ -3374,10 +3314,10 @@ public: rat_coeffs[4], rat_coeffs[5]); const Orientation temp_orient = temp_conic.orientation(); - if (comp_orient) arc.set_orientation(temp_orient); + if (comp_orient) cv.set_orientation(temp_orient); Integer r, s, t, u, v, w; - if (arc.orientation() == temp_orient) { + if (cv.orientation() == temp_orient) { r = int_coeffs[0]; s = int_coeffs[1]; t = int_coeffs[2]; @@ -3393,7 +3333,7 @@ public: v = -int_coeffs[4]; w = -int_coeffs[5]; } - arc.set_coefficients(r, s, t, u, v, w); + cv.set_coefficients(r, s, t, u, v, w); // Make sure the conic is a non-degenerate ellipse: // The coefficients should satisfy (4rs - t^2) > 0. @@ -3404,24 +3344,24 @@ public: // Mark that this arc is a full conic curve. if (is_ellipse) { - arc.set_flag(Curve_2::IS_VALID); - arc.set_flag(Curve_2::IS_FULL_CONIC); + cv.set_flag(Curve_2::IS_VALID); + cv.set_flag(Curve_2::IS_FULL_CONIC); } - else arc.reset_flags(); // inavlid arc + else cv.reset_flags(); // inavlid arc } /*! Check whether the given point lies on the supporting conic of the arc. * \param p The query point. * \return true if p lies on the supporting conic; (false) otherwise. */ - bool is_on_supporting_conic(Curve_2& arc, const Point_2& p) const { + bool is_on_supporting_conic(Curve_2& cv, const Point_2& p) const { // Check whether p satisfies the conic equation. - const Algebraic r = m_nt_traits->convert(arc.r()); - const Algebraic t = m_nt_traits->convert(arc.t()); - const Algebraic u = m_nt_traits->convert(arc.u()); - const Algebraic s = m_nt_traits->convert(arc.s()); - const Algebraic v = m_nt_traits->convert(arc.v()); - const Algebraic w = m_nt_traits->convert(arc.w()); + const Algebraic r = m_nt_traits->convert(cv.r()); + const Algebraic t = m_nt_traits->convert(cv.t()); + const Algebraic u = m_nt_traits->convert(cv.u()); + const Algebraic s = m_nt_traits->convert(cv.s()); + const Algebraic v = m_nt_traits->convert(cv.v()); + const Algebraic w = m_nt_traits->convert(cv.w()); // The point must satisfy: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0. const Algebraic val = @@ -3594,22 +3534,18 @@ public: // // We store the equation of this line in the extra data structure and also // the sign (side of half-plane) our arc occupies with respect to the line. - auto* extra_data = new typename Curve_2::Extra_data; - - extra_data->a = cos_phi; - extra_data->b = sin_phi; - extra_data->c = - (cos_phi*x0 + sin_phi*y0); - - // Make sure that the two endpoints are located on the same branch - // of the hyperbola. + // We use it to make sure that the two endpoints are located on the same + // branch of the hyperbola. + auto a = cos_phi; + auto b = sin_phi; + auto c = - (cos_phi*x0 + sin_phi*y0); const auto& source = cv.source(); + auto val = a * source.x() + b * source.y() + c; + auto side = CGAL::sign(val); + CGAL_assertion(side != ZERO); + cv.set_extra_data(a, b, c, side); const auto& target = cv.target(); - cv.set_extra_data(extra_data); - extra_data->side = cv.sign_of_extra_data(source.x(), source.y()); - - CGAL_assertion(extra_data->side != ZERO); - CGAL_assertion(extra_data->side == - cv.sign_of_extra_data(target.x(), target.y())); + CGAL_assertion(side == cv.sign_of_extra_data(target.x(), target.y())); } /*! Find the x coordinates of the underlying conic at a given y coordinate. @@ -3623,8 +3559,7 @@ public: // Solve the quadratic equation for a given y and find the x values: // r*x^2 + (t*y + u)*x + (s*y^2 + v*y + w) = 0 Algebraic A = m_nt_traits->convert(cv.r()); - Algebraic B = - m_nt_traits->convert(cv.t())*y + m_nt_traits->convert(cv.u()); + Algebraic B = m_nt_traits->convert(cv.t())*y + m_nt_traits->convert(cv.u()); Algebraic C = (m_nt_traits->convert(cv.s())*y + m_nt_traits->convert(cv.v()))*y + m_nt_traits->convert(cv.w()); @@ -3643,8 +3578,7 @@ public: // Solve the quadratic equation for a given x and find the y values: // s*y^2 + (t*x + v)*y + (r*x^2 + u*x + w) = 0 Algebraic A = m_nt_traits->convert(cv.s()); - Algebraic B = - m_nt_traits->convert(cv.t())*x + m_nt_traits->convert(cv.v()); + Algebraic B = m_nt_traits->convert(cv.t())*x + m_nt_traits->convert(cv.v()); Algebraic C = (m_nt_traits->convert(cv.r())*x + m_nt_traits->convert(cv.u()))*x + m_nt_traits->convert(cv.w()); @@ -3682,7 +3616,6 @@ public: // Compute the two distinct solutions: Algebraic _2A = 2*A; - Nt_traits nt_traits; Algebraic sqrt_disc = m_nt_traits->sqrt(disc); x_minus = -(B + sqrt_disc) / _2A; @@ -3758,42 +3691,42 @@ public: xcv.set_flag(Curve_2::IS_VALID); xcv.reset_flag(Curve_2::IS_FULL_CONIC); - // Check if the arc is directed right (the target is lexicographically - // greater than the source point), or to the left. - Comparison_result dir_res = - m_alg_kernel->compare_xy_2_object()(xcv.source(), xcv.target()); - CGAL_assertion(dir_res != EQUAL); - if (dir_res == SMALLER) xcv.set_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT); + // Check (i) whether the arc is a vertical segment, and (ii) whether it is + // directed right. + auto cmp_x = m_alg_kernel->compare_x_2_object(); + Comparison_result resx = cmp_x(xcv.source(), xcv.target()); + if (resx == SMALLER) xcv.set_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT); + else if (resx == EQUAL) { + xcv.set_flag(X_monotone_curve_2::IS_VERTICAL_SEGMENT); - // Compute the degree of the underlying conic. - if ((CGAL::sign(xcv.r()) != ZERO) || - (CGAL::sign(xcv.s()) != ZERO) || - (CGAL::sign(xcv.t()) != ZERO)) - { - xcv.set_flag(X_monotone_curve_2::DEGREE_2); - - if (xcv.orientation() == COLLINEAR) { - xcv.set_flag(X_monotone_curve_2::IS_SPECIAL_SEGMENT); - - // Check whether the arc is a vertical segment: - auto cmp_x = m_alg_kernel->compare_x_2_object(); - if (cmp_x(xcv.source(), xcv.target()) == EQUAL) - xcv.set_flag(X_monotone_curve_2::IS_VERTICAL_SEGMENT); - return; - } + auto cmp_y = m_alg_kernel->compare_y_2_object(); + Comparison_result resy = cmp_y(xcv.source(), xcv.target()); + CGAL_assertion(resy != EQUAL); + if (resy == SMALLER) xcv.set_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT); } - else { - CGAL_assertion((CGAL::sign(xcv.u()) != ZERO) || - (CGAL::sign(xcv.v()) != ZERO)); - // The supporting curve is of the form: u*x + w = 0 - if (CGAL::sign(xcv.v()) == ZERO) - xcv.set_flag(X_monotone_curve_2::IS_VERTICAL_SEGMENT); - xcv.set_flag(X_monotone_curve_2::DEGREE_1); + if (xcv.orientation() == COLLINEAR) { + // Compute the degree of the underlying conic. + if ((CGAL::sign(xcv.r()) != ZERO) || + (CGAL::sign(xcv.s()) != ZERO) || + (CGAL::sign(xcv.t()) != ZERO)) + { + xcv.set_flag(X_monotone_curve_2::DEGREE_2); + xcv.set_flag(X_monotone_curve_2::IS_SPECIAL_SEGMENT); + } + else { + xcv.set_flag(X_monotone_curve_2::DEGREE_1); + + // Check whether this is a special segment + if ((CGAL::sign(xcv.u()) == ZERO) && (CGAL::sign(xcv.v()) == ZERO)) { + xcv.set_flag(X_monotone_curve_2::IS_SPECIAL_SEGMENT); + xcv.update_extra_data(); + } + } return; } - if (xcv.orientation() == COLLINEAR) return; + xcv.set_flag(X_monotone_curve_2::DEGREE_2); // Compute a midpoint between the source and the target and get the y-value // of the arc at its x-coordiante. @@ -3825,7 +3758,7 @@ public: // Check whether the conic is facing up or facing down: // Check whether the arc (which is x-monotone of degree 2) lies above or - // below the segement that contects its two end-points (x1,y1) and (x2,y2). + // below the segement that connects its two end-points (x1,y1) and (x2,y2). // To do that, we find the y coordinate of a point on the arc whose x // coordinate is (x1+x2)/2 and compare it to (y1+y2)/2. auto cmp_y = m_alg_kernel->compare_y_2_object(); @@ -3940,7 +3873,6 @@ public: const Integer two(2); const Integer four(4); Algebraic xs[2]; - Nt_traits nt_traits; auto r = cv.r(); auto s = cv.s(); diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h index 3eaf851cdcd..4c535b52d00 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h @@ -1489,7 +1489,6 @@ public: */ void set_coefficients(Integer r, Integer s, Integer t, Integer u, Integer v, Integer w) { - m_r = r; m_s = s; m_t = t; @@ -1512,6 +1511,36 @@ public: /*! Set the extra data field. */ void set_extra_data(Extra_data* extra_data) { m_extra_data = extra_data; } + + /*! Set the extra data field. + */ + void set_extra_data(const Algebraic& a, const Algebraic& b, + const Algebraic& c, Sign side) + { + m_extra_data = new Extra_data; + m_extra_data->a = a; + m_extra_data->b = b; + m_extra_data->c = c; + m_extra_data->side = side; + } + + /*! Update the extra data field. + */ + void update_extra_data() { + const Algebraic x1 = source().x(); + const Algebraic y1 = source().y(); + const Algebraic x2 = target().x(); + const Algebraic y2 = target().y(); + + // The supporting line is A*x + B*y + C = 0, where: + // A = y2 - y1, B = x1 - x2, C = x2*y1 - x1*y2 + // We use the extra data field to store the equation of this line. + m_extra_data = new Extra_data; + m_extra_data->a = y2 - y1; + m_extra_data->b = x1 - x2; + m_extra_data->c = x2*y1 - x1*y2; + m_extra_data->side = ZERO; + } //@} public: diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_intersections_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_intersections_2.h index 1ea27a61b22..223fcda24e9 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_intersections_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_intersections_2.h @@ -35,7 +35,7 @@ namespace CGAL { * \return The number of distinct roots found. */ template -int compute_resultant_roots(Nt_traits& nt_traits, +int compute_resultant_roots(const Nt_traits& nt_traits, const typename Nt_traits::Integer& r1, const typename Nt_traits::Integer& s1, const typename Nt_traits::Integer& t1, @@ -150,10 +150,9 @@ int compute_resultant_roots(Nt_traits& nt_traits, // Compute the roots of the resultant polynomial. typename Nt_traits::Polynomial poly = - nt_traits.construct_polynomial (c, degree); + nt_traits.construct_polynomial(c, degree); - xs_end = nt_traits.compute_polynomial_roots (poly, - xs); + xs_end = nt_traits.compute_polynomial_roots(poly, xs); return static_cast(xs_end - xs); } @@ -167,7 +166,7 @@ int compute_resultant_roots(Nt_traits& nt_traits, * \return The number of distinct roots found. */ template -int compute_resultant_roots(Nt_traits& nt_traits, +int compute_resultant_roots(const Nt_traits& nt_traits, const typename Nt_traits::Algebraic& r, const typename Nt_traits::Algebraic& s, const typename Nt_traits::Algebraic& t, From 2ba0fc38b5c2af568424674be3430744e7d9c3fd Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 22 Jun 2022 09:38:55 +0300 Subject: [PATCH 035/105] Fixed a couple of bugs --- .../include/CGAL/Arr_conic_traits_2.h | 43 ++++++++++++++----- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index 725c1e18603..ec0f0f51968 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -1411,6 +1412,16 @@ public: *oi++ = Intersection_result(ip); } + if (eq(xcv1.left(), xcv2.right())) { + Intersection_point ip(xcv1.left(), 0); + *oi++ = Intersection_result(ip); + } + + if (eq(xcv1.right(), xcv2.left())) { + Intersection_point ip(xcv1.right(), 0); + *oi++ = Intersection_result(ip); + } + return oi; } @@ -1866,6 +1877,9 @@ public: double r_m, t_m, s_m, u_m, v_m, w_m; double cost, sint; canonical_conic(arc, r_m, s_m, t_m, u_m, v_m, w_m, cost, sint); + // std::cout << r_m << "," << s_m << "," << t_m << "," + // << u_m << "," << v_m << "," << w_m << std::endl; + // std::cout << "sint, cost: " << sint << "," << cost << std::endl; /* If the axis of the parabola is the 𝑌-axis, shift * the parabola by 90, essentially, converting the @@ -1874,8 +1888,13 @@ public: * This is somehow inefficient, because we repeat the computation of * cost, sint, r_m,..., and w_m. An alternative, is to add code that * directly handles the case where the conjugate axis is the 𝑌-axis. + * + * We need to test whether s_m vanished; however, because of limited + * precision, s_m can become very small. Therefore, instead for comparing + * s_m with zero we compare its absolute value with the absolute value of + * r_m, which is expected to be larger. */ - if (s_m == 0) { + if (std::abs(s_m) < std::abs(r_m)) { // Shift phase: auto tmp(cost); cost = sint; @@ -2168,19 +2187,21 @@ public: // Compute the cos and sin of the rotation angle // This eliminates the t coefficinet (which multiplies x·y). - cost = 1.0; - sint = 0.0; - double cos_2t; if (r != s) { - auto tan_2t = t / (r - s); - cos_2t = std::sqrt(1 / (tan_2t*tan_2t + 1)); + auto theta = atan2(t, r-s) * 0.5; + cost = std::cos(theta); + sint = std::sin(theta); + } + else if (r != 0) { + double cos_2t = 1; + cost = 1.0; + sint = 0.0; + } else { + double cos_2t = 0; + cost = std::sqrt(1 / 2); + sint = cost; } - else if (r != 0) cos_2t = 1; - else cos_2t = 0; - - cost = std::sqrt((1 + cos_2t) / 2); - sint = std::sqrt((1 - cos_2t) / 2); inverse_conic(arc, cost, sint, r_m, s_m, t_m, u_m, v_m, w_m); } From ddf09bef01f17fc5f86d069588d129eab7e51d3e Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 22 Jun 2022 10:23:51 +0300 Subject: [PATCH 036/105] Updated --- .../Arrangement_on_surface_2/CMakeLists.txt | 5 +- .../Arrangement_on_surface_2/conics.cpp | 4 - .../Arrangement_on_surface_2/ellipses.cpp | 48 ++++++++++ .../Arrangement_on_surface_2/hyperbolas.cpp | 42 +++++++++ .../linear_conics.cpp | 72 +++++++++++++++ .../Arrangement_on_surface_2/parabolas.cpp | 92 +++++++++++++++++++ 6 files changed, 258 insertions(+), 5 deletions(-) create mode 100644 Arrangement_on_surface_2/examples/Arrangement_on_surface_2/ellipses.cpp create mode 100644 Arrangement_on_surface_2/examples/Arrangement_on_surface_2/hyperbolas.cpp create mode 100644 Arrangement_on_surface_2/examples/Arrangement_on_surface_2/linear_conics.cpp create mode 100644 Arrangement_on_surface_2/examples/Arrangement_on_surface_2/parabolas.cpp diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/CMakeLists.txt b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/CMakeLists.txt index d3536801663..afa7d09ca0b 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/CMakeLists.txt +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/CMakeLists.txt @@ -17,5 +17,8 @@ endforeach() if(CGAL_Qt5_FOUND) target_link_libraries(draw_arr PUBLIC CGAL::CGAL_Basic_viewer) - target_link_libraries(conics PUBLIC CGAL::CGAL_Basic_viewer) + target_link_libraries(linear_conics PUBLIC CGAL::CGAL_Basic_viewer) + target_link_libraries(parabolas PUBLIC CGAL::CGAL_Basic_viewer) + target_link_libraries(ellipses PUBLIC CGAL::CGAL_Basic_viewer) + target_link_libraries(old_conics PUBLIC CGAL::CGAL_Basic_viewer) endif() diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conics.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conics.cpp index 5221db2a415..7e0b235f5a1 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conics.cpp +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/conics.cpp @@ -5,8 +5,6 @@ #ifdef CGAL_USE_CORE -#include - #include "arr_conics.h" #include "arr_print.h" @@ -57,8 +55,6 @@ int main() { print_arrangement_size(arr); - CGAL::draw(arr); - return 0; } diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/ellipses.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/ellipses.cpp new file mode 100644 index 00000000000..a2a167e3f9b --- /dev/null +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/ellipses.cpp @@ -0,0 +1,48 @@ +//! \file examples/Arrangement_on_surface_2/conics.cpp +// Constructing an arrangement of various conic arcs. + +#include + +#ifdef CGAL_USE_CORE + +#include +#include + +#include "arr_conics.h" +#include "arr_print.h" + +int main() { + Traits traits; + Arrangement arr(&traits); + + auto ctr_cv = traits.construct_curve_2_object(); + Point p0(0, 0); + + // Insert a full x-major ellipse + insert(arr, ctr_cv(1, 4, 0, 0, 0, -8)); + + // Insert a full y-major ellipse + insert(arr, ctr_cv(4, 1, 0, 0, 0, -8)); + + // Insert a full ellipse (C2), which is (x/4)^2 + (y/2)^2 = 1 rotated by + // phi = 36.87 degrees (such that sin(phi) = 0.6, cos(phi) = 0.8), + // yielding: 58x^2 + 72y^2 - 48xy - 360 = 0. + insert(arr, ctr_cv(58, 72, -48, 0, 0, -360)); + + print_arrangement_size(arr); + + CGAL::draw(arr); + + return 0; +} + +#else + +#include + +int main() { + std::cout << "Sorry, this example needs GMP and CORE\n"; + return 0; +} + +#endif diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/hyperbolas.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/hyperbolas.cpp new file mode 100644 index 00000000000..9ce36d2cbd2 --- /dev/null +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/hyperbolas.cpp @@ -0,0 +1,42 @@ +//! \file examples/Arrangement_on_surface_2/conics.cpp +// Constructing an arrangement of various conic arcs. + +#include + +#ifdef CGAL_USE_CORE + +#include +#include + +#include "arr_conics.h" +#include "arr_print.h" + +int main() { + Traits traits; + Arrangement arr(&traits); + + auto ctr_cv = traits.construct_curve_2_object(); + + // Insert a hyperbolic arc (C1), supported by the hyperbola y = 1/x + // (or: xy - 1 = 0) with the endpoints (1/4, 4) and (2, 1/2). + // The arc is counterclockwise oriented. + insert(arr, ctr_cv(0, 0, 1, 0, 0, -1, CGAL::COUNTERCLOCKWISE, + Point(Rational(1,4), 4), Point(2, Rational(1,2)))); + + print_arrangement_size(arr); + + CGAL::draw(arr); + + return 0; +} + +#else + +#include + +int main() { + std::cout << "Sorry, this example needs GMP and CORE\n"; + return 0; +} + +#endif diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/linear_conics.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/linear_conics.cpp new file mode 100644 index 00000000000..5ffb0ef90be --- /dev/null +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/linear_conics.cpp @@ -0,0 +1,72 @@ +//! \file examples/Arrangement_on_surface_2/conics.cpp +// Constructing an arrangement of various conic arcs. + +#include + +#ifdef CGAL_USE_CORE + +#include +#include + +#include "arr_conics.h" +#include "arr_print.h" + +int main() { + Traits traits; + Arrangement arr(&traits); + + auto ctr_cv = traits.construct_curve_2_object(); + Point p0(0, 0); + Point p1(-1, 0); + Point p2(0, -1); + Point p3(0, 1); + Point p4(1, 0); + Rat_point rp0(0, 0); + Rat_point rp1(1, 0); + Rat_point rp2(0, 1); + Rat_point rp3(0, -1); + + // horizontal + // insert the segment (0, 0)--(1, 0). + insert(arr, ctr_cv(Rat_segment(rp0, rp1))); + // insert the segment (0, 0)--(-1, 0). + insert(arr, ctr_cv(0, 0, 0, 0, 1, 0, CGAL::COLLINEAR, p0, p1)); + + // vertical + // insert the segment (0, -1)--(0, 0). + insert(arr, ctr_cv(Rat_segment(rp3, rp0))); + + // translated + // insert the segment (0, -1)--(1, 0). + insert(arr, ctr_cv(Rat_segment(rp3, rp1))); + // insert the segment (0, -1)--(-1, 0). + insert(arr, ctr_cv(0, 0, 0, -1, -1, -1, CGAL::COLLINEAR, p2, p1)); + + // Special segments + // horizontal special segment + insert(arr, ctr_cv(Point(Rational(1,2),Rational(1,2)), Point(Rational(-1,2),Rational(1,2)))); + + // vertical special segment + insert(arr, ctr_cv(p0, p3)); + + // special translated + insert(arr, ctr_cv(p1, p3)); + insert(arr, ctr_cv(p3, p4)); + + print_arrangement_size(arr); + + CGAL::draw(arr); + + return 0; +} + +#else + +#include + +int main() { + std::cout << "Sorry, this example needs GMP and CORE\n"; + return 0; +} + +#endif diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/parabolas.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/parabolas.cpp new file mode 100644 index 00000000000..b58c7b4ec9d --- /dev/null +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/parabolas.cpp @@ -0,0 +1,92 @@ +//! \file examples/Arrangement_on_surface_2/conics.cpp +// Constructing an arrangement of various conic arcs. + +#include + +#ifdef CGAL_USE_CORE + +#include +#include + +#include "arr_conics.h" +#include "arr_print.h" + +int main() { + Traits traits; + Arrangement arr(&traits); + + auto ctr_cv = traits.construct_curve_2_object(); + Point p0(0, 0); + + // x-major + // insert the parabola y = x^2; (-1,1)--(1,1) + insert(arr, ctr_cv(1, 0, 0, 0, -1, 0, CGAL::COUNTERCLOCKWISE, + Point(-1, 1), Point(1, 1))); + + // translated + // Insert the parabola y = x^2 - 2x + 2; (1,1)--(2,2) + insert(arr, ctr_cv(1, 0, 0, -2, -1, 2, CGAL::COUNTERCLOCKWISE, + Point(1, 1), Point(2, 2))); + insert(arr, ctr_cv(1, 0, 0, 2, -1, 2, CGAL::COUNTERCLOCKWISE, + Point(-2, 2), Point(-1, 1))); + + // rotated + // Insert the parabola y = x^2 rotated clockwise about theta, such that + // sin(theta) = 0.6, cos(theta) = 0.8 + insert(arr, ctr_cv(16, 9, -24, -15, -20, 0, CGAL::COUNTERCLOCKWISE, + Point(Rational(-2,10), Rational(14,10)), + Point(Rational(14,10), Rational(2,10)))); + insert(arr, ctr_cv(16, 9, 24, 15, -20, 0, CGAL::CLOCKWISE, + Point(Rational(2,10), Rational(14,10)), + Point(Rational(-14,10), Rational(2,10)))); + insert(arr, ctr_cv(16, 9, 24, -15, 20, 0, CGAL::COUNTERCLOCKWISE, + Point(Rational(14,10), Rational(-2,10)), + Point(Rational(-2,10), Rational(-14,10)))); + insert(arr, ctr_cv(16, 9, -24, 15, 20, 0, CGAL::COUNTERCLOCKWISE, + Point(Rational(2,10), Rational(-14,10)), + Point(Rational(-14,10), Rational(-2,10)))); + + // 16*x*x+9*y*y-24*x*y-15*x-20*y + + insert(arr, ctr_cv(9, 16, -24, -20, -15, 0, CGAL::COUNTERCLOCKWISE, + Point(Rational(2,10), Rational(14,10)), + Point(Rational(14,10), Rational(-2,10)))); + insert(arr, ctr_cv(9, 16, 24, -20, 15, 0, CGAL::CLOCKWISE, + Point(Rational(2,10), Rational(-14,10)), + Point(Rational(14,10), Rational(2,10)))); + insert(arr, ctr_cv(9, 16, 24, 20, -15, 0, CGAL::COUNTERCLOCKWISE, + Point(Rational(-14,10), Rational(-2,10)), + Point(Rational(-2,10), Rational(14,10)))); + insert(arr, ctr_cv(9, 16, -24, 20, 15, 0, CGAL::COUNTERCLOCKWISE, + Point(Rational(-2,10), Rational(-14,10)), + Point(Rational(-14,10), Rational(2,10)))); + + // 9*x*x+16*y*y-24*x*y+20*x+15*y + + // rotated & translated + insert(arr, ctr_cv(16, 9, -24, -23, -14, 36, CGAL::COUNTERCLOCKWISE, + Point(Rational(8,10), Rational(24,10)), + Point(Rational(24,10), Rational(12,10)))); + insert(arr, ctr_cv(16, 9, 24, 23, -14, 36, CGAL::CLOCKWISE, + Point(Rational(-8,10), Rational(24,10)), + Point(Rational(-24,10), Rational(12,10)))); + + // 16*x*x+9*y*y-24*x*y-23*x-14*y+36 + + print_arrangement_size(arr); + + CGAL::draw(arr); + + return 0; +} + +#else + +#include + +int main() { + std::cout << "Sorry, this example needs GMP and CORE\n"; + return 0; +} + +#endif From 88113a7b82c8c3d2d317ca5cf13f34560ee88a0d Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 22 Jun 2022 18:21:39 +0300 Subject: [PATCH 037/105] Cleaned up --- .../Arrangement_on_surface_2/CMakeLists.txt | 1 + .../Arrangement_on_surface_2/arr_conics.h | 28 +- .../Arrangement_on_surface_2/ellipses.cpp | 21 +- .../include/CGAL/Arr_conic_traits_2.h | 777 +++++++++++------- 4 files changed, 497 insertions(+), 330 deletions(-) diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/CMakeLists.txt b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/CMakeLists.txt index afa7d09ca0b..b40ee522e16 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/CMakeLists.txt +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/CMakeLists.txt @@ -20,5 +20,6 @@ if(CGAL_Qt5_FOUND) target_link_libraries(linear_conics PUBLIC CGAL::CGAL_Basic_viewer) target_link_libraries(parabolas PUBLIC CGAL::CGAL_Basic_viewer) target_link_libraries(ellipses PUBLIC CGAL::CGAL_Basic_viewer) + target_link_libraries(hyperbolas PUBLIC CGAL::CGAL_Basic_viewer) target_link_libraries(old_conics PUBLIC CGAL::CGAL_Basic_viewer) endif() diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/arr_conics.h b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/arr_conics.h index d0a29ba9336..8e222124fd3 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/arr_conics.h +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/arr_conics.h @@ -6,20 +6,18 @@ #include #include -typedef CGAL::CORE_algebraic_number_traits Nt_traits; -typedef Nt_traits::Rational Rational; -typedef CGAL::Cartesian Rat_kernel; -typedef Rat_kernel::Point_2 Rat_point; -typedef Rat_kernel::Segment_2 Rat_segment; -typedef Rat_kernel::Circle_2 Rat_circle; -typedef Nt_traits::Algebraic Algebraic; -typedef CGAL::Cartesian Alg_kernel; - -typedef CGAL::Arr_conic_traits_2 - Traits; -typedef Traits::Point_2 Point; -typedef Traits::Curve_2 Conic_arc; -typedef Traits::X_monotone_curve_2 X_monotone_conic_arc; -typedef CGAL::Arrangement_2 Arrangement; +using Nt_traits = CGAL::CORE_algebraic_number_traits; +using Rational = Nt_traits::Rational; +using Rat_kernel = CGAL::Cartesian; +using Rat_point = Rat_kernel::Point_2; +using Rat_segment = Rat_kernel::Segment_2; +using Rat_circle = Rat_kernel::Circle_2; +using Algebraic = Nt_traits::Algebraic; +using Alg_kernel = CGAL::Cartesian; +using Traits = CGAL::Arr_conic_traits_2; +using Point = Traits::Point_2; +using Conic_arc = Traits::Curve_2; +using X_monotone_conic_arc = Traits::X_monotone_curve_2; +using Arrangement = CGAL::Arrangement_2; #endif diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/ellipses.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/ellipses.cpp index a2a167e3f9b..159b18cf9cf 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/ellipses.cpp +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/ellipses.cpp @@ -16,18 +16,27 @@ int main() { Arrangement arr(&traits); auto ctr_cv = traits.construct_curve_2_object(); - Point p0(0, 0); // Insert a full x-major ellipse - insert(arr, ctr_cv(1, 4, 0, 0, 0, -8)); + insert(arr, ctr_cv(1, 4, 0, 0, 0, -16, CGAL::COUNTERCLOCKWISE, + Point(4,0), Point(0,2))); + insert(arr, ctr_cv(1, 4, 0, 0, 0, -16, CGAL::COUNTERCLOCKWISE, + Point(0,2), Point(-4,0))); + insert(arr, ctr_cv(1, 4, 0, 0, 0, -16, CGAL::COUNTERCLOCKWISE, + Point(-4,0), Point(0,-2))); + insert(arr, ctr_cv(1, 4, 0, 0, 0, -16, CGAL::COUNTERCLOCKWISE, + Point(0,-2), Point(4,0))); // Insert a full y-major ellipse - insert(arr, ctr_cv(4, 1, 0, 0, 0, -8)); + insert(arr, ctr_cv(4, 1, 0, 0, 0, -16)); - // Insert a full ellipse (C2), which is (x/4)^2 + (y/2)^2 = 1 rotated by + // Insert the full ellipse (x/4)^2 + (y/2)^2 = 1 clockwise rotated by // phi = 36.87 degrees (such that sin(phi) = 0.6, cos(phi) = 0.8), - // yielding: 58x^2 + 72y^2 - 48xy - 360 = 0. - insert(arr, ctr_cv(58, 72, -48, 0, 0, -360)); + insert(arr, ctr_cv(52, 73, 72, 0, 0, -400)); + + // Insert the full ellipse (x/4)^2 + (y/2)^2 = 1 counter clockwise rotated by + // phi = 36.87 degrees (such that sin(phi) = 0.6, cos(phi) = 0.8), + insert(arr, ctr_cv(52, 73, -72, 0, 0, -400)); print_arrangement_size(arr); diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index ec0f0f51968..bcadc889f11 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -1590,6 +1590,98 @@ public: using Approximate_kernel = CGAL::Cartesian; using Approximate_point_2 = Approximate_kernel::Point_2; + class Approximate_curve_length_2 { + protected: + using Traits = Arr_conic_traits_2; + + /*! The traits (in case it has state) */ + const Traits& m_traits; + + /*! Constructor + * \param traits the traits. + */ + Approximate_curve_length_2(const Traits& traits) : m_traits(traits) {} + + friend class Arr_conic_traits_2; + + public: + /*! Obtain an approximation of the length of a curve. + * \param xcv The curve. + * \return An approximation of the length of `xcv`. + */ + Approximate_number_type operator()(const X_monotone_curve_2& xcv) const { + if (xcv.orientation() == COLLINEAR) return segment_length(xcv); + CGAL::Sign sign_conic = CGAL::sign(4*xcv.r()*xcv.s() - xcv.t()*xcv.t()); + if (sign_conic == POSITIVE) return ellipse_length(xcv); + if (sign_conic == NEGATIVE) return hyperbola_length(xcv); + return parabola_length(xcv); + } + + private: + /*! Obtain the segment length. + */ + double segment_length(const X_monotone_curve_2& xcv) { + auto min_vertex = m_traits.construct_min_vertex_2_object(); + auto max_vertex = m_traits.construct_max_vertex_2_object(); + const auto& minv = min_vertex(xcv); + const auto& maxv = max_vertex(xcv); + auto x1 = CGAL::to_double(minv.x()); + auto y1 = CGAL::to_double(minv.y()); + auto x2 = CGAL::to_double(maxv.x()); + auto y2 = CGAL::to_double(maxv.y()); + auto dx = x2 - x1; + auto dy = y2 - y1; + double l = std::sqrt(x2*x2 + y2*y2); + return l; + } + + /*! Obtain the parabolic arc length. + */ + double parabola_length(const X_monotone_curve_2& xcv) { + double r_m, t_m, s_m, u_m, v_m, w_m; + double cost, sint; + double xs_t, ys_t, xt_t, yt_t; + double a; + double ts, tt; + double cx, cy; + m_traits.approximate_parabola(r_m, t_m, s_m, u_m, v_m, w_m, cost, sint, + xs_t, ys_t, xt_t, yt_t, a, ts, tt, cx, cy, + xcv); + + auto ds = m_traits.parabolic_arc_length(xs_t, 2.0*std::abs(ys_t)); + auto dt = m_traits.parabolic_arc_length(xt_t, 2.0*std::abs(yt_t)); + auto d = (CGAL::sign(ys_t) == CGAL::sign(yt_t)) ? + std::abs(ds - dt)/2.0 : (ds + dt)/2.0; + // std::cout << "d, ds, dt = " << d << ", " << ds << "," << dt + // << std::endl; + return d; + } + + double ellipse_length(const X_monotone_curve_2& xcv) { + double r_m, t_m, s_m, u_m, v_m, w_m; + double cost, sint; + double a, b; + double cx, cy; + double ts, tt; + m_traits.approximate_ellipse(r_m, t_m, s_m, u_m, v_m, w_m, cost, sint, + ts, tt, a, b, cx, cy, xcv); + + namespace bm = boost::math; + auto ratio = b/a; + auto k = std::sqrt(1 - (ratio*ratio)); + auto ds = a*bm::ellint_2(k, ts); + auto dt = a*bm::ellint_2(k, tt); + auto d = std::abs(dt - ds); + // std::cout << "d,ds,dt: " << d << "," << ds << ", " << dt << std::endl; + return d; + } + + double hyperbola_length(const X_monotone_curve_2& xcv) { + double l; + return l; + } + }; + class Approximate_2 { protected: using Traits = Arr_conic_traits_2; @@ -1628,16 +1720,16 @@ public: */ template OutputIterator operator()(OutputIterator oi, double density, - const X_monotone_curve_2& arc, + const X_monotone_curve_2& xcv, bool l2r = true) const { - if (arc.orientation() == COLLINEAR) - return approximate_segment(oi, density, arc, l2r); - CGAL::Sign sign_conic = CGAL::sign(4*arc.r()*arc.s() - arc.t()*arc.t()); + if (xcv.orientation() == COLLINEAR) + return approximate_segment(oi, density, xcv, l2r); + CGAL::Sign sign_conic = CGAL::sign(4*xcv.r()*xcv.s() - xcv.t()*xcv.t()); if (sign_conic == POSITIVE) - return approximate_ellipse(oi, density, arc, l2r); + return approximate_ellipse(oi, density, xcv, l2r); if (sign_conic == NEGATIVE) - return approximate_hyperbola(oi, density, arc, l2r); - return approximate_parabola(oi, density, arc, l2r); + return approximate_hyperbola(oi, density, xcv, l2r); + return approximate_parabola(oi, density, xcv, l2r); } private: @@ -1645,15 +1737,13 @@ public: */ template OutputIterator approximate_segment(OutputIterator oi, double density, - const X_monotone_curve_2& arc, + const X_monotone_curve_2& xcv, bool l2r) const { // std::cout << "SEGMENT\n"; auto min_vertex = m_traits.construct_min_vertex_2_object(); auto max_vertex = m_traits.construct_max_vertex_2_object(); - const auto& src = (l2r) ? - min_vertex(arc) : max_vertex(arc); - const auto& trg = (l2r) ? - max_vertex(arc) : min_vertex(arc); + const auto& src = (l2r) ? min_vertex(xcv) : max_vertex(xcv); + const auto& trg = (l2r) ? max_vertex(xcv) : min_vertex(xcv); auto xs = CGAL::to_double(src.x()); auto ys = CGAL::to_double(src.y()); auto xt = CGAL::to_double(trg.x()); @@ -1732,15 +1822,13 @@ public: */ template OutputIterator approximate_ellipse(OutputIterator oi, double density, - const X_monotone_curve_2& arc, + const X_monotone_curve_2& xcv, bool l2r) const { // std::cout << "ELLIPSE\n"; auto min_vertex = m_traits.construct_min_vertex_2_object(); auto max_vertex = m_traits.construct_max_vertex_2_object(); - const auto& src = (l2r) ? - min_vertex(arc) : max_vertex(arc); - const auto& trg = (l2r) ? - max_vertex(arc) : min_vertex(arc); + const auto& src = (l2r) ? min_vertex(xcv) : max_vertex(xcv); + const auto& trg = (l2r) ? max_vertex(xcv) : min_vertex(xcv); auto xs = CGAL::to_double(src.x()); auto ys = CGAL::to_double(src.y()); auto xt = CGAL::to_double(trg.x()); @@ -1751,63 +1839,11 @@ public: double r_m, t_m, s_m, u_m, v_m, w_m; double cost, sint; - canonical_conic(arc, r_m, s_m, t_m, u_m, v_m, w_m, cost, sint); - // std::cout << r_m << "," << s_m << "," << t_m << "," - // << u_m << "," << v_m << "," << w_m << std::endl; - // std::cout << "sint, cost: " << sint << "," << cost << std::endl; - - // Compute the center of the inversly rotated ellipse: - auto cx_m = -u_m / (2*r_m); - auto cy_m = -v_m / (2*s_m); - - // Compute the radi of the ellipse: - auto numerator = -4*w_m*r_m*s_m + s_m*u_m*u_m + r_m*v_m*v_m; - auto a_sqr = numerator / (4*r_m*r_m*s_m); - auto b_sqr = numerator / (4*r_m*s_m*s_m); - if (a_sqr < b_sqr) { - // Shift phase: - auto tmp(cost); - cost = sint; - sint = -tmp; - - // Recompute: - inverse_conic(arc, cost, sint, r_m, s_m, t_m, u_m, v_m, w_m); - cx_m = -u_m / (2*r_m); - cy_m = -v_m / (2*s_m); - numerator = -4*w_m*r_m*s_m + s_m*u_m*u_m + r_m*v_m*v_m; - a_sqr = numerator / (4*r_m*r_m*s_m); - b_sqr = numerator / (4*r_m*s_m*s_m); - } - - auto a = std::sqrt(a_sqr); - auto b = std::sqrt(b_sqr); - // std::cout << "a, b: " << a << "," << b << std::endl; - - // Compute the center (cx,cy) of the ellipse, rotating back: - auto cx = cx_m*cost - cy_m*sint; - auto cy = cx_m*sint + cy_m*cost; - // std::cout << "center: " << cx << "," << cy << std::endl; - - // Compute the parameters ts and tt such that - // source == (x(ts),y(ts)), and - // target == (x(tt),y(tt)) - auto xds = xs - cx; - auto yds = ys - cy; - auto ts = std::atan2(a*(cost*yds - sint*xds),b*(sint*yds + cost*xds)); - if (ts < 0) ts += 2*M_PI; - auto xdt = xt - cx; - auto ydt = yt - cy; - auto tt = std::atan2(a*(cost*ydt - sint*xdt),b*(sint*ydt + cost*xdt)); - if (tt < 0) tt += 2*M_PI; - auto orient(arc.orientation()); - if (arc.source() != src) orient = CGAL::opposite(orient); - if (orient == COUNTERCLOCKWISE) { - if (tt < ts) tt += 2*M_PI; - } - else { - if (ts < tt) ts += 2*M_PI; - } - // std::cout << "ts,tt: " << ts << "," << tt << std::endl; + double a, b; + double cx, cy; + double ts, tt; + m_traits.approximate_ellipse(r_m, t_m, s_m, u_m, v_m, w_m, cost, sint, + ts, tt, a, b, cx, cy, xcv, l2r); namespace bm = boost::math; auto ratio = b/a; @@ -1815,7 +1851,8 @@ public: auto ds = a*bm::ellint_2(k, ts); auto dt = a*bm::ellint_2(k, tt); auto d = std::abs(dt - ds); - // std::cout << "d,ds,dt: " << d << "," << ds << ", " << dt << std::endl; + // std::cout << "d, ds, dt: " << d << "," << ds << ", " << dt + // << std::endl; auto size = static_cast(d*density); if (size == 0) size = 1; auto delta_t = (tt - ts) / size; @@ -1857,15 +1894,13 @@ public: */ template OutputIterator approximate_parabola(OutputIterator oi, double density, - const X_monotone_curve_2& arc, - bool l2r) const { + const X_monotone_curve_2& xcv, bool l2r) + const { // std::cout << "PARABOLA\n"; auto min_vertex = m_traits.construct_min_vertex_2_object(); auto max_vertex = m_traits.construct_max_vertex_2_object(); - const auto& src = (l2r) ? - min_vertex(arc) : max_vertex(arc); - const auto& trg = (l2r) ? - max_vertex(arc) : min_vertex(arc); + const auto& src = (l2r) ? min_vertex(xcv) : max_vertex(xcv); + const auto& trg = (l2r) ? max_vertex(xcv) : min_vertex(xcv); auto xs = CGAL::to_double(src.x()); auto ys = CGAL::to_double(src.y()); auto xt = CGAL::to_double(trg.x()); @@ -1876,67 +1911,20 @@ public: double r_m, t_m, s_m, u_m, v_m, w_m; double cost, sint; - canonical_conic(arc, r_m, s_m, t_m, u_m, v_m, w_m, cost, sint); - // std::cout << r_m << "," << s_m << "," << t_m << "," - // << u_m << "," << v_m << "," << w_m << std::endl; - // std::cout << "sint, cost: " << sint << "," << cost << std::endl; + double xs_t, ys_t, xt_t, yt_t; + double a; + double ts, tt; + double cx, cy; + m_traits.approximate_parabola(r_m, t_m, s_m, u_m, v_m, w_m, cost, sint, + xs_t, ys_t, xt_t, yt_t, a, ts, tt, cx, cy, + xcv, l2r); - /* If the axis of the parabola is the 𝑌-axis, shift - * the parabola by 90, essentially, converting the - * parabola to one the axis of which is the 𝑋-axis, as the - * remaining code assume that the 𝑋-axis is the parabola axis. - * This is somehow inefficient, because we repeat the computation of - * cost, sint, r_m,..., and w_m. An alternative, is to add code that - * directly handles the case where the conjugate axis is the 𝑌-axis. - * - * We need to test whether s_m vanished; however, because of limited - * precision, s_m can become very small. Therefore, instead for comparing - * s_m with zero we compare its absolute value with the absolute value of - * r_m, which is expected to be larger. - */ - if (std::abs(s_m) < std::abs(r_m)) { - // Shift phase: - auto tmp(cost); - cost = sint; - sint = -tmp; - - // Recompute: - inverse_conic(arc, cost, sint, r_m, s_m, t_m, u_m, v_m, w_m); - } - // std::cout << r_m << "," << s_m << "," << t_m << "," - // << u_m << "," << v_m << "," << w_m << std::endl; - // std::cout << "sint, cost: " << sint << "," << cost << std::endl; - - // Compute the center of the inversly rotated parabola: - // double cx_m = -u_m / (2*r_m); - // double cy_m = (u_m*u_m - 4*r_m*w_m) / (4*r_m*v_m); - double cx_m = (v_m*v_m - 4*s_m*w_m) / (4*s_m*u_m); - double cy_m = -v_m / (2*s_m); - // std::cout << "cx_m, cy_m: " << cx_m << "," << cy_m << std::endl; - - // Transform the source and target - auto xs_t = xs*cost + ys*sint - cx_m; - auto ys_t = -xs*sint + ys*cost - cy_m; - auto xt_t = xt*cost + yt*sint - cx_m; - auto yt_t = -xt*sint + yt*cost - cy_m; - - auto a = -u_m/(4.0*s_m); - auto ts = ys_t/(2.0*a); - auto tt = yt_t/(2.0*a); - // std::cout << "xs' = " << xs_t << "," << ys_t << std::endl; - // std::cout << "xt' = " << xt_t << "," << yt_t << std::endl; - // std::cout << "ts,tt = " << ts << "," << tt << std::endl; - - auto ds = parabolic_arc_length(xs_t, 2.0*std::abs(ys_t)); - auto dt = parabolic_arc_length(xt_t, 2.0*std::abs(yt_t)); + auto ds = m_traits.parabolic_arc_length(xs_t, 2.0*std::abs(ys_t)); + auto dt = m_traits.parabolic_arc_length(xt_t, 2.0*std::abs(yt_t)); auto d = (CGAL::sign(ys_t) == CGAL::sign(yt_t)) ? std::abs(ds - dt)/2.0 : (ds + dt)/2.0; - // std::cout << "d, ds, dt = " << d << ", " << ds << "," << dt << std::endl; - - // Compute the center (cx,cy) of the ellipse, rotating back: - auto cx = cx_m*cost - cy_m*sint; - auto cy = cx_m*sint + cy_m*cost; - // std::cout << "center: " << cx << "," << cy << std::endl; + // std::cout << "d, ds, dt = " << d << ", " << ds << "," << dt + // << std::endl; auto t(ts); auto size = static_cast(d*density); @@ -1983,7 +1971,7 @@ public: #else auto xt_prev = 2.0*a*t; auto yt_prev = a*t*t; - auto dt_prev = parabolic_arc_length(yt_prev, 2.0*std::abs(xt_prev)); + auto dt_prev = m_traits.parabolic_arc_length(yt_prev, 2.0*std::abs(xt_prev)); double d_t(delta_t); double d; @@ -1994,7 +1982,7 @@ public: auto xt = 2.0*a*t; auto yt = a*t*t; - auto dt = parabolic_arc_length(yt, 2.0*std::abs(xt)); + auto dt = m_traits.parabolic_arc_length(yt, 2.0*std::abs(xt)); d = (CGAL::sign(xt_prev) == CGAL::sign(xt)) ? std::abs(dt - dt_prev)/2.0 : (dt + dt_prev)/2.0; @@ -2006,120 +1994,29 @@ public: #endif } - /*! The formula for the arc length of a parabola is: - * L = 1/2 * √(b^2+16⋅a^2) + b^2/(8*a) * ln((4*a+√(b^2+16⋅a^2))/b) - * where: - * L is the length of the parabola arc. - * a is the length along the parabola axis. - * b is the length perpendicular to the axis making a chord. - * - * --- - * / | \ - * / |a \ - * / | \ - * /---------\ - * / b \ - * - */ - double parabolic_arc_length(double a, double b) const { - if (a == 0) return b; - if (b == 0) return a; - auto b_sqr = b*b; - auto tmp = std::sqrt(b_sqr+16.0*a*a); - return tmp/2.0 + b_sqr*std::log((4.0*a + tmp)/b)/(8.0*a); - } - /*! Handle hyperbolas. */ template OutputIterator approximate_hyperbola(OutputIterator oi, double density, - const X_monotone_curve_2& arc, + const X_monotone_curve_2& xcv, bool l2r) const { // std::cout << "HYPERBOLA\n"; auto min_vertex = m_traits.construct_min_vertex_2_object(); auto max_vertex = m_traits.construct_max_vertex_2_object(); - const auto& src = (l2r) ? - min_vertex(arc) : max_vertex(arc); - const auto& trg = (l2r) ? - max_vertex(arc) : min_vertex(arc); + const auto& src = (l2r) ? min_vertex(xcv) : max_vertex(xcv); + const auto& trg = (l2r) ? max_vertex(xcv) : min_vertex(xcv); auto xs = CGAL::to_double(src.x()); auto ys = CGAL::to_double(src.y()); auto xt = CGAL::to_double(trg.x()); auto yt = CGAL::to_double(trg.y()); - // std::cout << "curve: (" << xs << "," << ys - // << ") => (" << xt << "," << yt << ")" - // << std::endl; double r_m, t_m, s_m, u_m, v_m, w_m; double cost, sint; - // If the hyperbola conjugate axis is the Y-axis, add - canonical_conic(arc, r_m, s_m, t_m, u_m, v_m, w_m, cost, sint); - // std::cout << r_m << "," << s_m << "," << t_m << "," - // << u_m << "," << v_m << "," << w_m << std::endl; - - auto numerator = -4*w_m*r_m*s_m + s_m*u_m*u_m + r_m*v_m*v_m; - auto a_sqr = numerator / (4*r_m*r_m*s_m); - auto b_sqr = -numerator / (4*r_m*s_m*s_m); - - /* If the conjugate axis of the canonical hyperbula is the 𝑌-axis, shift - * the canonical hyperbula by 90, essentially, converting the canonical - * hyperbula to one the conjugate axis of which is the 𝑋-axis, as the - * remaining code assume that the conjugate axis is the 𝑋-axis. - * This is somehow inefficient, because we repeat the computation of - * cost, sint, r_m,...,w_m, a_sqr, and b_sqr. An alternative, is - * to add code that directly handles the case where the conjugate axis - * is the 𝑌-axis. Here, - * 1. a_sqr = -a_sqr, b_sqr = -b_sqr, and - * 2. x(t),y(t) = a*sinh(t), b*cosh(t) - */ - if (a_sqr < 0) { - // Shift phase: - auto tmp(cost); - cost = sint; - sint = -tmp; - - // Recompute: - inverse_conic(arc, cost, sint, r_m, s_m, t_m, u_m, v_m, w_m); - numerator = -4*w_m*r_m*s_m + s_m*u_m*u_m + r_m*v_m*v_m; - a_sqr = numerator / (4*r_m*r_m*s_m); - b_sqr = -numerator / (4*r_m*s_m*s_m); - } - // std::cout << "sint, cost: " << sint << "," << cost << std::endl; - - // Compute the center of the inversly rotated ellipse: - auto cx_m = -u_m / (2*r_m); - auto cy_m = -v_m / (2*s_m); - - // Transform the source and target - auto xs_t = xs*cost + ys*sint - cx_m; - auto ys_t = -xs*sint + ys*cost - cy_m; - auto xt_t = xt*cost + yt*sint - cx_m; - auto yt_t = -xt*sint + yt*cost - cy_m; - // std::cout << "xs_t,ys_t: " << xs_t << "," << ys_t << std::endl; - // std::cout << "xt_t,yt_t: " << xt_t << "," << yt_t << std::endl; - - // Compute the center (cx,cy) of the hyperbola, rotating back: - auto cx = cx_m*cost - cy_m*sint; - auto cy = cx_m*sint + cy_m*cost; - // std::cout << "center: " << cx << "," << cy << std::endl; - - auto a = std::sqrt(a_sqr); - auto b = std::sqrt(b_sqr); - - // We use the parametric representation x(t),y(t) = a*cosh(t), b*sinh(t) - // cosh(t) = (e^t + e^(-t))/2 - // sinh(t) = (e^t - e^(-t))/2 - // Compute the parameters ts and tt such that - // source == (x(ts),y(ts)), and - // target == (x(tt),y(tt)) - // Compute the radi of the hyperbola: - auto ts = std::asinh(ys_t/b); - auto tt = std::asinh(yt_t/b); - assert(std::signbit(xs_t) == std::signbit(xt_t)); - // std::cout << "a, b: " << a << "," << b << std::endl; - // std::cout << "ts, tt: " << ts << "," << tt << std::endl; - - if (std::signbit(xs_t)) a = -a; + double a, b; + double cx, cy; + double ts, tt; + m_traits.approximate_hyperbola(r_m, t_m, s_m, u_m, v_m, w_m, cost, sint, + ts, tt, a, b, cx, cy, xcv, l2r); auto t(ts); auto size = static_cast(density); @@ -2159,74 +2056,6 @@ public: *oi++ = Approximate_point_2(x, y); return oi; } - - /*! Obtain (i) the rotation that yields the given conic arc when applied - * to the canonical arc, and (ii) the canonical arc. - * \param[in] arc the given arc - * \param[out] r_m the coefficients of the canonical conic. - * \param[out] s_m - * \param[out] t_m - * \param[out] u_m - * \param[out] v_m - * \param[out] w_m - * \param[out] cost the cosine of the rotation angle. - * \param[out] sint the sine of the rotation angle. - */ - void canonical_conic(const X_monotone_curve_2& arc, - double& r_m, double& s_m, double& t_m, - double& u_m, double& v_m, double& w_m, - double& cost, double& sint) const { - auto r = CGAL::to_double(arc.r()); - auto s = CGAL::to_double(arc.s()); - auto t = CGAL::to_double(arc.t()); - auto u = CGAL::to_double(arc.u()); - auto v = CGAL::to_double(arc.v()); - auto w = CGAL::to_double(arc.w()); - // std::cout << r << "," << s << "," << t << "," - // << u << "," << v << "," << w << std::endl; - - // Compute the cos and sin of the rotation angle - // This eliminates the t coefficinet (which multiplies x·y). - - if (r != s) { - auto theta = atan2(t, r-s) * 0.5; - cost = std::cos(theta); - sint = std::sin(theta); - } - else if (r != 0) { - double cos_2t = 1; - cost = 1.0; - sint = 0.0; - } else { - double cos_2t = 0; - cost = std::sqrt(1 / 2); - sint = cost; - } - - inverse_conic(arc, cost, sint, r_m, s_m, t_m, u_m, v_m, w_m); - } - - /*! Apply the inverse of the rotation given by the sin and cosine of the - * rotation angle to the given conic arc. - */ - void inverse_conic(const X_monotone_curve_2& arc, - double cost, double sint, - double& r_m, double& s_m, double& t_m, - double& u_m, double& v_m, double& w_m) const { - auto r = CGAL::to_double(arc.r()); - auto s = CGAL::to_double(arc.s()); - auto t = CGAL::to_double(arc.t()); - auto u = CGAL::to_double(arc.u()); - auto v = CGAL::to_double(arc.v()); - auto w = CGAL::to_double(arc.w()); - - r_m = r * cost*cost + t*cost*sint + s*sint*sint; - t_m = 0; - s_m = r * sint*sint - t*cost*sint + s*cost*cost; - u_m = u*cost + v*sint; - v_m = - u*sint + v*cost; - w_m = w; - } }; /*! Obtain an Approximate_2 functor object. */ @@ -2270,7 +2099,7 @@ public: } /*! Construct an x-monotone sub-arc from a conic arc. - * \param arc The given (base) arc. + * \param cv The given (base) arc. * \param source The source point. * \param target The target point. * \param id The ID of the base arc. @@ -4046,6 +3875,336 @@ public: CGAL_assertion(m <= 2); return m; } + + /*! Apply the inverse of the rotation given by the sin and cosine of the + * rotation angle to the given conic arc. + */ + void inverse_conic(const X_monotone_curve_2& xcv, + double cost, double sint, + double& r_m, double& s_m, double& t_m, + double& u_m, double& v_m, double& w_m) const { + auto r = CGAL::to_double(xcv.r()); + auto s = CGAL::to_double(xcv.s()); + auto t = CGAL::to_double(xcv.t()); + auto u = CGAL::to_double(xcv.u()); + auto v = CGAL::to_double(xcv.v()); + auto w = CGAL::to_double(xcv.w()); + + r_m = r * cost*cost + t*cost*sint + s*sint*sint; + t_m = 0; + s_m = r * sint*sint - t*cost*sint + s*cost*cost; + u_m = u*cost + v*sint; + v_m = - u*sint + v*cost; + w_m = w; + } + + /*! Obtain (i) the rotation that yields the given conic arc when applied + * to the canonical arc, and (ii) the canonical arc. + * \param[in] arc the given arc + * \param[out] r_m the coefficients of the canonical conic. + * \param[out] s_m + * \param[out] t_m + * \param[out] u_m + * \param[out] v_m + * \param[out] w_m + * \param[out] cost the cosine of the rotation angle. + * \param[out] sint the sine of the rotation angle. + */ + void canonical_conic(const X_monotone_curve_2& xcv, + double& r_m, double& s_m, double& t_m, + double& u_m, double& v_m, double& w_m, + double& cost, double& sint) const { + auto r = CGAL::to_double(xcv.r()); + auto s = CGAL::to_double(xcv.s()); + auto t = CGAL::to_double(xcv.t()); + auto u = CGAL::to_double(xcv.u()); + auto v = CGAL::to_double(xcv.v()); + auto w = CGAL::to_double(xcv.w()); + // std::cout << r << "," << s << "," << t << "," + // << u << "," << v << "," << w << std::endl; + + // Compute the cos and sin of the rotation angle + // This eliminates the t coefficinet (which multiplies x·y). + + if (r != s) { + auto theta = atan2(t, r-s) * 0.5; + cost = std::cos(theta); + sint = std::sin(theta); + } + else if (r != 0) { + cost = 1.0; + sint = 0.0; + } + else { + cost = std::sqrt(0.5); + sint = cost; + } + + inverse_conic(xcv, cost, sint, r_m, s_m, t_m, u_m, v_m, w_m); + } + + /*! Handle parabolas. + * The arc-length closed form can be found here: + * https://www.vcalc.com/wiki/vCalc/Parabola+-+arc+length + */ + void approximate_parabola(double& r_m, double& t_m, double& s_m, + double& u_m, double& v_m, double& w_m, + double& cost, double& sint, + double& xs_t, double& ys_t, + double& xt_t, double& yt_t, + double& a, double& ts, double& tt, + double& cx, double& cy, + const X_monotone_curve_2& xcv, bool l2r = true) + const { + auto min_vertex = construct_min_vertex_2_object(); + auto max_vertex = construct_max_vertex_2_object(); + const auto& src = (l2r) ? min_vertex(xcv) : max_vertex(xcv); + const auto& trg = (l2r) ? max_vertex(xcv) : min_vertex(xcv); + auto xs = CGAL::to_double(src.x()); + auto ys = CGAL::to_double(src.y()); + auto xt = CGAL::to_double(trg.x()); + auto yt = CGAL::to_double(trg.y()); + + canonical_conic(xcv, r_m, s_m, t_m, u_m, v_m, w_m, cost, sint); + // std::cout << r_m << "," << s_m << "," << t_m << "," + // << u_m << "," << v_m << "," << w_m << std::endl; + // std::cout << "sint, cost: " << sint << "," << cost << std::endl; + + /* If the axis of the parabola is the 𝑌-axis, shift + * the parabola by 90, essentially, converting the + * parabola to one the axis of which is the 𝑋-axis, as the + * remaining code assume that the 𝑋-axis is the parabola axis. + * + * We need to test whether s_m vanished; however, because of limited + * precision, s_m can become very small. Therefore, instead for comparing + * s_m with zero we compare its absolute value with the absolute value of + * r_m, which is expected to be larger. + */ + if (std::abs(s_m) < std::abs(r_m)) { + // Shift phase: + auto tmp(cost); + cost = sint; + sint = -tmp; + + // Recompute: + inverse_conic(xcv, cost, sint, r_m, s_m, t_m, u_m, v_m, w_m); + } + // std::cout << r_m << "," << s_m << "," << t_m << "," + // << u_m << "," << v_m << "," << w_m << std::endl; + // std::cout << "sint, cost: " << sint << "," << cost << std::endl; + + // Compute the center of the inversly rotated parabola: + // double cx_m = -u_m / (2*r_m); + // double cy_m = (u_m*u_m - 4*r_m*w_m) / (4*r_m*v_m); + auto cx_m = (v_m*v_m - 4*s_m*w_m) / (4*s_m*u_m); + auto cy_m = -v_m / (2*s_m); + // std::cout << "cx_m, cy_m: " << cx_m << "," << cy_m << std::endl; + + // Transform the source and target + xs_t = xs*cost + ys*sint - cx_m; + ys_t = -xs*sint + ys*cost - cy_m; + xt_t = xt*cost + yt*sint - cx_m; + yt_t = -xt*sint + yt*cost - cy_m; + + a = -u_m / (4.0*s_m); + ts = ys_t / (2.0*a); + tt = yt_t / (2.0*a); + // std::cout << "xs' = " << xs_t << "," << ys_t << std::endl; + // std::cout << "xt' = " << xt_t << "," << yt_t << std::endl; + // std::cout << "ts,tt = " << ts << "," << tt << std::endl; + + // Compute the center (cx,cy) of the ellipse, rotating back: + cx = cx_m*cost - cy_m*sint; + cy = cx_m*sint + cy_m*cost; + // std::cout << "center: " << cx << "," << cy << std::endl; + } + + /*! The formula for the arc length of a parabola is: + * L = 1/2 * √(b^2+16⋅a^2) + b^2/(8*a) * ln((4*a+√(b^2+16⋅a^2))/b) + * where: + * L is the length of the parabola arc. + * a is the length along the parabola axis. + * b is the length of the chord perpendicular to the axis. + * + * --- + * / | \ + * / |a \ + * / | \ + * /---------\ + * / b \ + * + */ + double parabolic_arc_length(double a, double b) const { + if (a == 0) return b; + if (b == 0) return a; + auto b_sqr = b*b; + auto tmp = std::sqrt(b_sqr+16.0*a*a); + return tmp/2.0 + b_sqr*std::log((4.0*a + tmp)/b)/(8.0*a); + } + + /*! Handle ellipses. + */ + void approximate_ellipse(double& r_m, double& t_m, double& s_m, + double& u_m, double& v_m, double& w_m, + double& cost, double& sint, double& ts, double& tt, + double& a, double& b, double& cx, double& cy, + const X_monotone_curve_2& xcv, bool l2r = true) + const { + auto min_vertex = construct_min_vertex_2_object(); + auto max_vertex = construct_max_vertex_2_object(); + const auto& src = (l2r) ? min_vertex(xcv) : max_vertex(xcv); + const auto& trg = (l2r) ? max_vertex(xcv) : min_vertex(xcv); + auto xs = CGAL::to_double(src.x()); + auto ys = CGAL::to_double(src.y()); + auto xt = CGAL::to_double(trg.x()); + auto yt = CGAL::to_double(trg.y()); + + canonical_conic(xcv, r_m, s_m, t_m, u_m, v_m, w_m, cost, sint); + // std::cout << r_m << "," << s_m << "," << t_m << "," + // << u_m << "," << v_m << "," << w_m << std::endl; + // std::cout << "sint, cost: " << sint << "," << cost << std::endl; + + // Compute the radi of the ellipse: + auto numerator = -4*w_m*r_m*s_m + s_m*u_m*u_m + r_m*v_m*v_m; + auto a_sqr = numerator / (4*r_m*r_m*s_m); + auto b_sqr = numerator / (4*r_m*s_m*s_m); + if (a_sqr < b_sqr) { + // Shift phase: + auto tmp(cost); + cost = sint; + sint = -tmp; + + // Recompute: + inverse_conic(xcv, cost, sint, r_m, s_m, t_m, u_m, v_m, w_m); + numerator = -4*w_m*r_m*s_m + s_m*u_m*u_m + r_m*v_m*v_m; + a_sqr = numerator / (4*r_m*r_m*s_m); + b_sqr = numerator / (4*r_m*s_m*s_m); + } + + a = std::sqrt(a_sqr); + b = std::sqrt(b_sqr); + // std::cout << "a, b: " << a << "," << b << std::endl; + + // Compute the center of the inversly rotated ellipse: + auto cx_m = -u_m / (2*r_m); + auto cy_m = -v_m / (2*s_m); + + // Compute the center (cx,cy) of the ellipse, rotating back: + cx = cx_m*cost - cy_m*sint; + cy = cx_m*sint + cy_m*cost; + // std::cout << "center: " << cx << "," << cy << std::endl; + + // Compute the parameters ts and tt such that + // source == (x(ts),y(ts)), and + // target == (x(tt),y(tt)) + auto xds = xs - cx; + auto yds = ys - cy; + ts = std::atan2(a*(cost*yds - sint*xds),b*(sint*yds + cost*xds)); + if (ts < 0) ts += 2*M_PI; + auto xdt = xt - cx; + auto ydt = yt - cy; + tt = std::atan2(a*(cost*ydt - sint*xdt),b*(sint*ydt + cost*xdt)); + if (tt < 0) tt += 2*M_PI; + auto orient(xcv.orientation()); + if (xcv.source() != src) orient = CGAL::opposite(orient); + if (orient == COUNTERCLOCKWISE) { + if (tt < ts) tt += 2*M_PI; + } + else { + if (ts < tt) ts += 2*M_PI; + } + // std::cout << "ts,tt: " << ts << "," << tt << std::endl; + } + + /*! Handle hyperbolas. + */ + /*! Handle ellipses. + */ + void approximate_hyperbola(double& r_m, double& t_m, double& s_m, + double& u_m, double& v_m, double& w_m, + double& cost, double& sint, double& ts, double& tt, + double& a, double& b, double& cx, double& cy, + const X_monotone_curve_2& xcv, bool l2r = true) + const { + auto min_vertex = construct_min_vertex_2_object(); + auto max_vertex = construct_max_vertex_2_object(); + const auto& src = (l2r) ? min_vertex(xcv) : max_vertex(xcv); + const auto& trg = (l2r) ? max_vertex(xcv) : min_vertex(xcv); + auto xs = CGAL::to_double(src.x()); + auto ys = CGAL::to_double(src.y()); + auto xt = CGAL::to_double(trg.x()); + auto yt = CGAL::to_double(trg.y()); + // std::cout << "curve: (" << xs << "," << ys + // << ") => (" << xt << "," << yt << ")" + // << std::endl; + + // If the hyperbola conjugate axis is the Y-axis, add + canonical_conic(xcv, r_m, s_m, t_m, u_m, v_m, w_m, cost, sint); + // std::cout << r_m << "," << s_m << "," << t_m << "," + // << u_m << "," << v_m << "," << w_m << std::endl; + // std::cout << "sint, cost: " << sint << "," << cost << std::endl; + + auto numerator = -4*w_m*r_m*s_m + s_m*u_m*u_m + r_m*v_m*v_m; + auto a_sqr = numerator / (4*r_m*r_m*s_m); + auto b_sqr = -numerator / (4*r_m*s_m*s_m); + + /* If the conjugate axis of the canonical hyperbula is the 𝑌-axis, shift + * the canonical hyperbula by 90, essentially, converting the canonical + * hyperbula to one the conjugate axis of which is the 𝑋-axis, as the + * remaining code assume that the conjugate axis is the 𝑋-axis. + * Here, + * 1. a_sqr = -a_sqr, b_sqr = -b_sqr, and + * 2. x(t),y(t) = a*sinh(t), b*cosh(t) + */ + if (a_sqr < 0) { + // Shift phase: + auto tmp(cost); + cost = sint; + sint = -tmp; + + // Recompute: + inverse_conic(xcv, cost, sint, r_m, s_m, t_m, u_m, v_m, w_m); + numerator = -4*w_m*r_m*s_m + s_m*u_m*u_m + r_m*v_m*v_m; + a_sqr = numerator / (4*r_m*r_m*s_m); + b_sqr = -numerator / (4*r_m*s_m*s_m); + } + // std::cout << "sint, cost: " << sint << "," << cost << std::endl; + + // Compute the center of the inversly rotated ellipse: + auto cx_m = -u_m / (2*r_m); + auto cy_m = -v_m / (2*s_m); + + // Transform the source and target + auto xs_t = xs*cost + ys*sint - cx_m; + auto ys_t = -xs*sint + ys*cost - cy_m; + auto xt_t = xt*cost + yt*sint - cx_m; + auto yt_t = -xt*sint + yt*cost - cy_m; + // std::cout << "xs_t,ys_t: " << xs_t << "," << ys_t << std::endl; + // std::cout << "xt_t,yt_t: " << xt_t << "," << yt_t << std::endl; + + // Compute the center (cx,cy) of the hyperbola, rotating back: + cx = cx_m*cost - cy_m*sint; + cy = cx_m*sint + cy_m*cost; + // std::cout << "center: " << cx << "," << cy << std::endl; + + a = std::sqrt(a_sqr); + b = std::sqrt(b_sqr); + + // We use the parametric representation x(t),y(t) = a*cosh(t), b*sinh(t) + // cosh(t) = (e^t + e^(-t))/2 + // sinh(t) = (e^t - e^(-t))/2 + // Compute the parameters ts and tt such that + // source == (x(ts),y(ts)), and + // target == (x(tt),y(tt)) + // Compute the radi of the hyperbola: + ts = std::asinh(ys_t/b); + tt = std::asinh(yt_t/b); + assert(std::signbit(xs_t) == std::signbit(xt_t)); + // std::cout << "a, b: " << a << "," << b << std::endl; + // std::cout << "ts, tt: " << ts << "," << tt << std::endl; + + if (std::signbit(xs_t)) a = -a; + } }; #include From 8543ef5a25ea57bd997400807035f17d420bd951 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Thu, 23 Jun 2022 15:42:17 +0300 Subject: [PATCH 038/105] Cleaned up; replaced typedef with using (when possible). --- Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index bcadc889f11..0ea91bec920 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -74,8 +74,6 @@ public: typedef typename Nt_traits::Integer Integer; - typedef Arr_conic_traits_2 Self; - // Category tags: typedef Tag_true Has_left_category; typedef Tag_true Has_merge_category; @@ -95,8 +93,8 @@ public: private: // Type definition for the intersection points mapping. - typedef typename Point_2::Conic_id Conic_id; - typedef std::pair Conic_pair; + using Conic_id = typename Point_2::Conic_id; + using Conic_pair = std::pair; /*! \struct Less functor for Conic_pair. */ From 34a391b656d1efbc598975472981c1f7085a1161 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Thu, 23 Jun 2022 15:43:09 +0300 Subject: [PATCH 039/105] Changed the methods of constructing conic and x-monotone conic arcs; fixed some typos and small semantic errors. --- .../CGAL/Arr_conic_traits_2.h | 320 ++++++++++-------- 1 file changed, 188 insertions(+), 132 deletions(-) diff --git a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arr_conic_traits_2.h index f7024e766c2..0b610d566be 100644 --- a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arr_conic_traits_2.h @@ -34,21 +34,21 @@ namespace CGAL { * p_t\f$ (the source and target points, respectively). The orientation \f$ o\f$ * indicates whether we proceed from \f$ p_s\f$ to \f$ p_t\f$ in a clockwise or * in a counterclockwise direction. Note that \f$ C\f$ may also correspond to a - * line or to pair of lines - in this case \f$ o\f$ may specify a `COLLINEAR` + * line or to pair of lines---in this case \f$ o\f$ may specify a `COLLINEAR` * orientation. * * * * A very useful subset of the set of conic arcs are line segments and circular * arcs, as arrangements of circular arcs and line segments have some - * interesting applications (e.g. offsetting polygons, motion planning for a - * disc robot, etc.). Circular arcs and line segment are simpler objects and can - * be dealt with more efficiently than arbitrary arcs. For these reasons, it is - * possible to construct conic arcs from segments and from circles. Using these - * constructors is highly recommended: It is more straightforward and also - * speeds up the arrangement construction. However, in case the set of input - * curves contain only circular arcs and line segments, it is recommended to use - * the `Arr_circle_segment_2` class to achieve faster running times. + * interesting applications (e.g., offsetting polygons and motion planning for a + * disc robot). Circular arcs and line segment are simpler objects and can be + * dealt with more efficiently than arbitrary arcs. Indeed, it is possible to + * construct conic arcs from segments and from circles. Using these constructors + * is highly recommended: It is more straightforward and also expedites the + * arrangement construction. However, in case the set of input curves contain + * only circular arcs and line segments, it is recommended using the + * `Arr_circle_segment_2` class to achieve better running times. * * In our representation, all conic coefficients (namely \f$ r, s, t, u, v, * w\f$) must be rational numbers. This guarantees that the coordinates of all @@ -58,13 +58,13 @@ namespace CGAL { * integer coefficient of degree \f$ d\f$ such that \f$ p(\alpha) = * 0\f$). We therefore require separate representations of the curve * coefficients and the point coordinates. The `NtTraits` should be instantiated - * with a class that defines nested `Integer`, `Rational` and `Algebraic` number + * with a class that defines nested `Integer`, `Rational`, and `Algebraic` number * types and supports various operations on them, yielding certified computation * results (for example, it can convert rational numbers to algebraic numbers * and can compute roots of polynomials with integer coefficients). The other * template parameters, `RatKernel` and `AlgKernel` should be geometric kernels - * templated with the `NtTraits::Rational` and `NtTraits::Algebraic` number - * types, respectively. It is recommended to instantiate the + * instantiated with the `NtTraits::Rational` and `NtTraits::Algebraic` number + * types, respectively. It is recommended instantiating the * `CORE_algebraic_number_traits` class as the `NtTraits` parameter, with * `Cartesian` and `Cartesian` * instantiating the two kernel types, respectively. The number types in this @@ -115,110 +115,9 @@ public: /// \name Creation /// @{ - /*! constructs an arc corresponding to the line segment `seg`. + /*! constructs an empty (invalid) arc. */ - Curve_2(const typename RatKernel::Segment_2& seg); - - /*! constructs an arc corresponding to the full circle `circ` - * (note that this circle has a center point with rational coordinates - * and rational squared radius). - */ - Curve_2(const typename RatKernel::Circle_2& circ); - - /*! constructs a circular arc supported by the circle `circ`, going - * in the given orientation `o` from the source point `ps` to its target - * point `pt`. - * - * \pre `ps` and `pt` both lie on the circle `circ`. - * - * \pre `o` is not `COLLINEAR`. - */ - Curve_2(const typename RatKernel::Circle_2& circ, Orientation o, - const Point_2& ps, const Point_2& pt); - - /*! constructs a circular arc going from `p1` (its source point) - * through `p2` to `p3` (its target point). Note that all three points have - * rational coordinates. The orientation of the arc is determined - * automatically. - * - * \pre The three points are not collinear. - */ - Curve_2(const typename RatKernel::Point_2& p1, - const typename RatKernel::Point_2& p2, - const typename RatKernel::Point_2& p3); - - /*! constructs a conic arc that corresponds to the full conic curve - * \f$ r x^2 + s y^2 + t x y + u x + v y + w = 0\f$. - * - * \pre As a conic arc must be bounded, the given curve must be an ellipse, - * that is \f$ 4 r s - t^2 > 0\f$. - */ - Curve_2(const Rational& r, const Rational& s, - const Rational& t, const Rational& u, - const Rational& v, const Rational& w); - - /*! constructs a conic arc supported by the conic curve - * \f$ r x^2 + s y^2 + t x y + u x + v y + w = 0\f$, going in the given - * orientation `o` from the source point `ps` to its target point `pt`. * * - * - * \pre `ps` and `pt` both satisfy the equation of the supporting conic - * curve and define a bounded segment of this curve (e.g. in case of a - * hyperbolic arc, both point should be located on the same branch of the - * hyperbola). - * - * \pre `o` is not `COLLINEAR` if the supporting conic is curves, and must - * be `COLLINEAR` if it is not curved (a line or a line-pair). - */ - Curve_2(const Rational& r, const Rational& s, - const Rational& t, const Rational& u, - const Rational& v, const Rational& w, - Orientation o, - const Point_2& ps, const Point_2& pt); - - /*! constructs a conic arc going from `p1` (its source point) - * through `p2`, `p3` and `p4` (in this order) to `p5` (its target - * point). Note that all five points have rational coordinates. The - * orientation of the arc is determined automatically. - * - * \pre No three points of the five are not collinear. - * - * \pre The five points define a valid arc, in their given order. - */ - Curve_2(const typename RatKernel::Point_2& p1, - const typename RatKernel::Point_2& p2, - const typename RatKernel::Point_2& p3, - const typename RatKernel::Point_2& p4, - const typename RatKernel::Point_2& p5); - - /*! constructs a conic arc supported by the conic curve - * \f$ r x^2 + s y^2 + t x y + u x + v y + w = 0\f$, going in the given - * orientation `o` from its source point to its target Point. In this case - * only some approximations of the endpoints (`app_ps` and `app_pt`, - * respectively) is available, and their exact locations are given - * implicitly, specified by the intersections of the supporting conic curve - * with \f$ r_1 x^2 + s_1 y^2 + t_1 x y + u_1 x + v_1 y + w_1 = 0\f$ and \f$ - * r_2 x^2 + s_2 y^2 + t_2 x y + u_2 x + v_2 y + w_2 = 0\f$, respectively. - * - * \pre The two auxiliary curves specifying the endpoints really intersect - * with the supporting conic curve, such that the arc endpoints define a - * bounded segment of the supporting curve (e.g. in case of a hyperbolic - * arc, both point should be located on the same branch of the hyperbola). - * - * \pre `o` is not `COLLINEAR` if the supporting conic is curves, and must - * be `COLLINEAR` if it is not curved (a line or a line-pair). - */ - Curve_2(const Rational& r, const Rational& s, - const Rational& t, const Rational& u, - const Rational& v, const Rational& w, - Orientation o, - const Point_2& app_ps, - const Rational& r1, const Rational& s1, - const Rational& t1, const Rational& u1, - const Rational& v1, const Rational& w1, - const Point_2& app_pt, - const Rational& r2, const Rational& s2, - const Rational& t2, const Rational& u2, - const Rational& v2, const Rational& w2); + Curve_2(); /// @} @@ -299,10 +198,6 @@ public: */ Orientation orientation() const; - /*! return a bounding box of the arc `a`. - */ - Bbox_2 bbox() const; - /// @} /// \name Operations @@ -338,10 +233,9 @@ public: /// \name Creation /// @{ - /*! converts the given arc to an \f$ x\f$-monotone arc. - * \pre `arc` is \f$ x\f$-monotone. + /*! constructs an empty (invalid) arc. */ - X_monotone_curve_2(const Curve_2& arc); + X_monotone_curve_2(); /// @} @@ -387,21 +281,183 @@ public: /// @} }; + /*! \class + * A functor that constructs a conic arc. + */ + class Construct_curve_2 { + /*! constructs an arc corresponding to the line segment `seg`. + */ + Curve_2 operator()(const typename RatKernel::Segment_2& seg) const; + + /*! constructs an arc corresponding to the full circle `circ` + * (note that this circle has a center point with rational coordinates + * and rational squared radius). + */ + Curve_2 operator()(const typename RatKernel::Circle_2& circ) const; + + /*! constructs a circular arc supported by the circle `circ`, going + * in the given orientation `o` from the source point `ps` to its target + * point `pt`. + * + * \pre `ps` and `pt` both lie on the circle `circ`. + * + * \pre `o` is not `COLLINEAR`. + */ + Curve_2 operator()(const typename RatKernel::Circle_2& circ, Orientation o, + const Point_2& ps, const Point_2& pt) const; + + /*! constructs a circular arc going from `p1` (its source point) + * through `p2` to `p3` (its target point). Note that all three points have + * rational coordinates. The orientation of the arc is determined + * automatically. + * + * \pre The three points are not collinear. + */ + Curve_2 operator()(const typename RatKernel::Point_2& p1, + const typename RatKernel::Point_2& p2, + const typename RatKernel::Point_2& p3) const; + + /*! constructs a conic arc that corresponds to the full conic curve + * \f$ r x^2 + s y^2 + t x y + u x + v y + w = 0\f$. + * + * \pre As a conic arc must be bounded, the given curve must be an ellipse, + * that is \f$ 4 r s - t^2 > 0\f$. + */ + Curve_2 operator()(const Rational& r, const Rational& s, + const Rational& t, const Rational& u, + const Rational& v, const Rational& w) const; + + /*! constructs a conic arc supported by the conic curve + * \f$ r x^2 + s y^2 + t x y + u x + v y + w = 0\f$, going in the given + * orientation `o` from the source point `ps` to its target point `pt`. * * + * + * \pre `ps` and `pt` both satisfy the equation of the supporting conic + * curve and define a bounded segment of this curve (e.g. in case of a + * hyperbolic arc, both point should be located on the same branch of the + * hyperbola). + * + * \pre `o` is not `COLLINEAR` if the supporting conic is curves, and must + * be `COLLINEAR` if it is not curved (a line or a line-pair). + */ + Curve_2 operator()(const Rational& r, const Rational& s, + const Rational& t, const Rational& u, + const Rational& v, const Rational& w, + Orientation o, + const Point_2& ps, const Point_2& pt) const; + + /*! constructs a conic arc going from `p1` (its source point) + * through `p2`, `p3` and `p4` (in this order) to `p5` (its target + * point). Note that all five points have rational coordinates. The + * orientation of the arc is determined automatically. + * + * \pre No three points of the five are not collinear. + * + * \pre The five points define a valid arc, in their given order. + */ + Curve_2 operator()(const typename RatKernel::Point_2& p1, + const typename RatKernel::Point_2& p2, + const typename RatKernel::Point_2& p3, + const typename RatKernel::Point_2& p4, + const typename RatKernel::Point_2& p5) const; + + /*! constructs a conic arc supported by the conic curve + * \f$ r x^2 + s y^2 + t x y + u x + v y + w = 0\f$, going in the given + * orientation `o` from its source point to its target Point. In this case + * only some approximations of the endpoints (`app_ps` and `app_pt`, + * respectively) is available, and their exact locations are given + * implicitly, specified by the intersections of the supporting conic curve + * with \f$ r_1 x^2 + s_1 y^2 + t_1 x y + u_1 x + v_1 y + w_1 = 0\f$ and \f$ + * r_2 x^2 + s_2 y^2 + t_2 x y + u_2 x + v_2 y + w_2 = 0\f$, respectively. + * + * \pre The two auxiliary curves specifying the endpoints really intersect + * with the supporting conic curve, such that the arc endpoints define a + * bounded segment of the supporting curve (e.g. in case of a hyperbolic + * arc, both point should be located on the same branch of the hyperbola). + * + * \pre `o` is not `COLLINEAR` if the supporting conic is curves, and must + * be `COLLINEAR` if it is not curved (a line or a line-pair). + */ + Curve_2 operator()(const Rational& r, const Rational& s, + const Rational& t, const Rational& u, + const Rational& v, const Rational& w, + Orientation o, + const Point_2& app_ps, + const Rational& r1, const Rational& s1, + const Rational& t1, const Rational& u1, + const Rational& v1, const Rational& w1, + const Point_2& app_pt, + const Rational& r2, const Rational& s2, + const Rational& t2, const Rational& u2, + const Rational& v2, const Rational& w2) const; + }; + + /*! \class + * A functor that constructs an \f$X\f$-monotone conic arc. + */ + class Construct_x_monotone_curve_2 { + /*! converts the given arc to an \f$ x\f$-monotone arc. + * \pre `arc` is \f$ x\f$-monotone. + */ + X_monotone_curve_2 operator()(const Curve_2& arc) const; + + /*! Constructs an x-monotone curve connecting the two given endpoints. + * \param p The first point. + * \param q The second point. + * \pre p and q must not be the same. + * \return A segment connecting p and q. + */ + X_monotone_curve_2 operator()(const Point_2& source, const Point_2& target) const; + + /*! Constructs a special segment of a given line connecting to given + * endpoints. + * \param a, b, c The coefficients of the supporting line (ax + by + c = 0). + * \param source The source point. + * \param target The target point. + */ + X_monotone_curve_2 operator()(const Algebraic& a, const Algebraic& b, + const Algebraic& c, + const Point_2& source, const Point_2& target) const; + }; + + /*! \class + * A functor that constructs a bounding box of a conic arc. + */ + class Construct_bbox_2 { + /*! return a bounding box of the arc `a`. + */ + Bbox_2 operator()() const; + }; + + /*! \class + * A functor that trims a conic arc. + */ class Trim_2 { public: - /// \name Creation - /// @{ - - /*! Trims the given x-monotone curve to an from src to tgt. - * \ pre `src` and `tgt` lies on the curve + /*! Trims the given x-monotone curve to an from source to target. + * \ pre `source` and `target` lies on the curve */ - X_monotone_curve_2(const X_monotone_curve_2& xcv, - const Point_2& src, - const Point_2& tgt) const; + X_monotone_curve_2 operator()(const X_monotone_curve_2& xcv, + const Point_2& source, + const Point_2& target) const; - /// @} - }/* end Arr_conic_traits_2::Trim_2 */ + }; + /// \name Accessing Functor Objects + /// @{ + + /*! Obtain a `Construct_curve_2` functor. */ + Construct_curve_2 construct_curve_2_object() const; + + /*! Obtain a `Construct_x_monotone_curve_2` functor. */ + Construct_x_monotone_curve_2 construct_x_monotone_curve_2_object() const; + + /*! Obtain a `Bbox_2` functor. */ + Construct_bbox_2 construct_bbox_2_object() const; + + /*! Obtain a `Trim_2` functor. */ + Trim_2 trim_2_object() const; + + /// @} }; /* end Arr_conic_traits_2 */ } /* end namespace CGAL */ From c98dd649a9fd7f94499795cd4526e3ec41983b58 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Thu, 23 Jun 2022 15:44:26 +0300 Subject: [PATCH 040/105] Added the description of the changes applied to the conic traits of the 2D-Arrangement package. --- Installation/CHANGES.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 07d95edbe5d..a6f9737ddb0 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -66,6 +66,11 @@ Release date: June 2022 ### [2D Arrangements](https://doc.cgal.org/5.5/Manual/packages.html#PkgArrangementOnSurface2) - Fixed the intersect_2, compare_y_at_x_right, and compare_y_at_x_left function objects of the traits class template that handles geodesic arcs on sphere and applied a small syntactical fix to the tracing traits. +- Introduced a function template, namely, `draw_arrangement(arr)`, that renders arrangements based on the `Basic_viewer_qt` class template. At this point only 2D arrangements on the plane induced by (i) segments and (ii) conics are supported. +- Improved the traits class template that handles conics, namely `Arr_conic_traits_2`. This includes the following: + (i) Fixed a couple of bugs and slightly optimized some functions. + (ii) Introduced functionality that approximates conics with polylines. (This is used to draw conic curves.) + (iii) **Breaking change**: Changed the interface to generate conic curves. In the past, curves where generated directly using the constructors of the conic and x-monotone conic constructs. Now, they are constructed via function objects provided by the traits. This eliminates the constructions of temporary kernels. The old functionality is obsolete, but still supported for a limited number of versions. It depends on a static member function of the traits. In the next version this function will no longer be static, implying that the old functionality will no longer be supported. [Release 5.4](https://github.com/CGAL/cgal/releases/tag/v5.4) From 9d35d72ca0df1b6838235c39b02b49a43ed16c77 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Thu, 23 Jun 2022 15:45:16 +0300 Subject: [PATCH 041/105] Changed some 'typedef' to 'using' --- .../Arrangement_on_surface_2.txt | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Arrangement_on_surface_2.txt b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Arrangement_on_surface_2.txt index 903dcb16903..29a714186dc 100644 --- a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Arrangement_on_surface_2.txt +++ b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Arrangement_on_surface_2.txt @@ -4819,21 +4819,19 @@ defined in the header file `arr_conics.h`. #include #include -typedef CGAL::CORE_algebraic_number_traits Nt_traits; -typedef Nt_traits::Rational Rational; -typedef CGAL::Cartesian Rat_kernel; -typedef Rat_kernel::Point_2 Rat_point; -typedef Rat_kernel::Segment_2 Rat_segment; -typedef Rat_kernel::Circle_2 Rat_circle; -typedef Nt_traits::Algebraic Algebraic; -typedef CGAL::Cartesian Alg_kernel; - -typedef CGAL::Arr_conic_traits_2 - Traits; -typedef Traits::Point_2 Point; -typedef Traits::Curve_2 Conic_arc; -typedef Traits::X_monotone_curve_2 X_monotone_conic_arc; -typedef CGAL::Arrangement_2 Arrangement; +using Nt_traits = CGAL::CORE_algebraic_number_traits; +using Rational = Nt_traits::Rational; +using Rat_kernel = CGAL::Cartesian; +using Rat_point = Rat_kernel::Point_2; +using Rat_segment = Rat_kernel::Segment_2; +using Rat_circle = Rat_kernel::Circle_2; +using Algebraic = Nt_traits::Algebraic; +using Alg_kernel = CGAL::Cartesian; +using Traits = CGAL::Arr_conic_traits_2; +using Point = Traits::Point_2; +using Conic_arc = Traits::Curve_2; +using X_monotone_conic_arc = Traits::X_monotone_curve_2; +using Arrangement = CGAL::Arrangement_2; \endcode From ce39d74c0eff4d44009f1a80ff4bf874b30e377a Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Thu, 23 Jun 2022 15:45:42 +0300 Subject: [PATCH 042/105] Cleaned up; added CGAL namespace. --- .../Arrangement_on_surface_2/ellipses.cpp | 22 +++--- .../Arrangement_on_surface_2/hyperbolas.cpp | 4 +- .../linear_conics.cpp | 20 ++--- .../Arrangement_on_surface_2/parabolas.cpp | 74 ++++++++++--------- 4 files changed, 62 insertions(+), 58 deletions(-) diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/ellipses.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/ellipses.cpp index 159b18cf9cf..bc2403f2aeb 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/ellipses.cpp +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/ellipses.cpp @@ -18,25 +18,25 @@ int main() { auto ctr_cv = traits.construct_curve_2_object(); // Insert a full x-major ellipse - insert(arr, ctr_cv(1, 4, 0, 0, 0, -16, CGAL::COUNTERCLOCKWISE, - Point(4,0), Point(0,2))); - insert(arr, ctr_cv(1, 4, 0, 0, 0, -16, CGAL::COUNTERCLOCKWISE, - Point(0,2), Point(-4,0))); - insert(arr, ctr_cv(1, 4, 0, 0, 0, -16, CGAL::COUNTERCLOCKWISE, - Point(-4,0), Point(0,-2))); - insert(arr, ctr_cv(1, 4, 0, 0, 0, -16, CGAL::COUNTERCLOCKWISE, - Point(0,-2), Point(4,0))); + CGAL::insert(arr, ctr_cv(1, 4, 0, 0, 0, -16, CGAL::COUNTERCLOCKWISE, + Point(4,0), Point(0,2))); + CGAL::insert(arr, ctr_cv(1, 4, 0, 0, 0, -16, CGAL::COUNTERCLOCKWISE, + Point(0,2), Point(-4,0))); + CGAL::insert(arr, ctr_cv(1, 4, 0, 0, 0, -16, CGAL::COUNTERCLOCKWISE, + Point(-4,0), Point(0,-2))); + CGAL::insert(arr, ctr_cv(1, 4, 0, 0, 0, -16, CGAL::COUNTERCLOCKWISE, + Point(0,-2), Point(4,0))); // Insert a full y-major ellipse - insert(arr, ctr_cv(4, 1, 0, 0, 0, -16)); + CGAL::insert(arr, ctr_cv(4, 1, 0, 0, 0, -16)); // Insert the full ellipse (x/4)^2 + (y/2)^2 = 1 clockwise rotated by // phi = 36.87 degrees (such that sin(phi) = 0.6, cos(phi) = 0.8), - insert(arr, ctr_cv(52, 73, 72, 0, 0, -400)); + CGAL::insert(arr, ctr_cv(52, 73, 72, 0, 0, -400)); // Insert the full ellipse (x/4)^2 + (y/2)^2 = 1 counter clockwise rotated by // phi = 36.87 degrees (such that sin(phi) = 0.6, cos(phi) = 0.8), - insert(arr, ctr_cv(52, 73, -72, 0, 0, -400)); + CGAL::insert(arr, ctr_cv(52, 73, -72, 0, 0, -400)); print_arrangement_size(arr); diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/hyperbolas.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/hyperbolas.cpp index 9ce36d2cbd2..ebd35af492d 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/hyperbolas.cpp +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/hyperbolas.cpp @@ -20,8 +20,8 @@ int main() { // Insert a hyperbolic arc (C1), supported by the hyperbola y = 1/x // (or: xy - 1 = 0) with the endpoints (1/4, 4) and (2, 1/2). // The arc is counterclockwise oriented. - insert(arr, ctr_cv(0, 0, 1, 0, 0, -1, CGAL::COUNTERCLOCKWISE, - Point(Rational(1,4), 4), Point(2, Rational(1,2)))); + CGAL::insert(arr, ctr_cv(0, 0, 1, 0, 0, -1, CGAL::COUNTERCLOCKWISE, + Point(Rational(1,4), 4), Point(2, Rational(1,2)))); print_arrangement_size(arr); diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/linear_conics.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/linear_conics.cpp index 5ffb0ef90be..b0f990e0ee9 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/linear_conics.cpp +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/linear_conics.cpp @@ -21,6 +21,8 @@ int main() { Point p2(0, -1); Point p3(0, 1); Point p4(1, 0); + Point p5(Rational(1,2),Rational(1,2)); + Point p6(Rational(-1,2),Rational(1,2)); Rat_point rp0(0, 0); Rat_point rp1(1, 0); Rat_point rp2(0, 1); @@ -28,30 +30,30 @@ int main() { // horizontal // insert the segment (0, 0)--(1, 0). - insert(arr, ctr_cv(Rat_segment(rp0, rp1))); + CGAL::insert(arr, ctr_cv(Rat_segment(rp0, rp1))); // insert the segment (0, 0)--(-1, 0). - insert(arr, ctr_cv(0, 0, 0, 0, 1, 0, CGAL::COLLINEAR, p0, p1)); + CGAL::insert(arr, ctr_cv(0, 0, 0, 0, 1, 0, CGAL::COLLINEAR, p0, p1)); // vertical // insert the segment (0, -1)--(0, 0). - insert(arr, ctr_cv(Rat_segment(rp3, rp0))); + CGAL::insert(arr, ctr_cv(Rat_segment(rp3, rp0))); // translated // insert the segment (0, -1)--(1, 0). - insert(arr, ctr_cv(Rat_segment(rp3, rp1))); + CGAL::insert(arr, ctr_cv(Rat_segment(rp3, rp1))); // insert the segment (0, -1)--(-1, 0). - insert(arr, ctr_cv(0, 0, 0, -1, -1, -1, CGAL::COLLINEAR, p2, p1)); + CGAL::insert(arr, ctr_cv(0, 0, 0, -1, -1, -1, CGAL::COLLINEAR, p2, p1)); // Special segments // horizontal special segment - insert(arr, ctr_cv(Point(Rational(1,2),Rational(1,2)), Point(Rational(-1,2),Rational(1,2)))); + CGAL::insert(arr, ctr_cv(p5, p6)); // vertical special segment - insert(arr, ctr_cv(p0, p3)); + CGAL::insert(arr, ctr_cv(p0, p3)); // special translated - insert(arr, ctr_cv(p1, p3)); - insert(arr, ctr_cv(p3, p4)); + CGAL::insert(arr, ctr_cv(p1, p3)); + CGAL::insert(arr, ctr_cv(p3, p4)); print_arrangement_size(arr); diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/parabolas.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/parabolas.cpp index b58c7b4ec9d..720e3fe5752 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/parabolas.cpp +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/parabolas.cpp @@ -17,59 +17,61 @@ int main() { auto ctr_cv = traits.construct_curve_2_object(); Point p0(0, 0); + CGAL::insert(arr, ctr_cv(Point(-2.4,-1.4), Point(-2.4,2.4))); + CGAL::insert(arr, ctr_cv(Point(2.4,-1.4), Point(2.4,2.4))); // x-major // insert the parabola y = x^2; (-1,1)--(1,1) - insert(arr, ctr_cv(1, 0, 0, 0, -1, 0, CGAL::COUNTERCLOCKWISE, - Point(-1, 1), Point(1, 1))); + CGAL::insert(arr, ctr_cv(1, 0, 0, 0, -1, 0, CGAL::COUNTERCLOCKWISE, + Point(-1, 1), Point(1, 1))); // translated // Insert the parabola y = x^2 - 2x + 2; (1,1)--(2,2) - insert(arr, ctr_cv(1, 0, 0, -2, -1, 2, CGAL::COUNTERCLOCKWISE, - Point(1, 1), Point(2, 2))); - insert(arr, ctr_cv(1, 0, 0, 2, -1, 2, CGAL::COUNTERCLOCKWISE, - Point(-2, 2), Point(-1, 1))); + CGAL::insert(arr, ctr_cv(1, 0, 0, -2, -1, 2, CGAL::COUNTERCLOCKWISE, + Point(1, 1), Point(2, 2))); + CGAL::insert(arr, ctr_cv(1, 0, 0, 2, -1, 2, CGAL::COUNTERCLOCKWISE, + Point(-2, 2), Point(-1, 1))); // rotated // Insert the parabola y = x^2 rotated clockwise about theta, such that // sin(theta) = 0.6, cos(theta) = 0.8 - insert(arr, ctr_cv(16, 9, -24, -15, -20, 0, CGAL::COUNTERCLOCKWISE, - Point(Rational(-2,10), Rational(14,10)), - Point(Rational(14,10), Rational(2,10)))); - insert(arr, ctr_cv(16, 9, 24, 15, -20, 0, CGAL::CLOCKWISE, - Point(Rational(2,10), Rational(14,10)), - Point(Rational(-14,10), Rational(2,10)))); - insert(arr, ctr_cv(16, 9, 24, -15, 20, 0, CGAL::COUNTERCLOCKWISE, - Point(Rational(14,10), Rational(-2,10)), - Point(Rational(-2,10), Rational(-14,10)))); - insert(arr, ctr_cv(16, 9, -24, 15, 20, 0, CGAL::COUNTERCLOCKWISE, - Point(Rational(2,10), Rational(-14,10)), - Point(Rational(-14,10), Rational(-2,10)))); + CGAL::insert(arr, ctr_cv(16, 9, -24, -15, -20, 0, CGAL::COUNTERCLOCKWISE, + Point(Rational(-2,10), Rational(14,10)), + Point(Rational(14,10), Rational(2,10)))); + CGAL::insert(arr, ctr_cv(16, 9, 24, 15, -20, 0, CGAL::CLOCKWISE, + Point(Rational(2,10), Rational(14,10)), + Point(Rational(-14,10), Rational(2,10)))); + CGAL::insert(arr, ctr_cv(16, 9, 24, -15, 20, 0, CGAL::COUNTERCLOCKWISE, + Point(Rational(14,10), Rational(-2,10)), + Point(Rational(-2,10), Rational(-14,10)))); + CGAL::insert(arr, ctr_cv(16, 9, -24, 15, 20, 0, CGAL::COUNTERCLOCKWISE, + Point(Rational(2,10), Rational(-14,10)), + Point(Rational(-14,10), Rational(-2,10)))); // 16*x*x+9*y*y-24*x*y-15*x-20*y - insert(arr, ctr_cv(9, 16, -24, -20, -15, 0, CGAL::COUNTERCLOCKWISE, - Point(Rational(2,10), Rational(14,10)), - Point(Rational(14,10), Rational(-2,10)))); - insert(arr, ctr_cv(9, 16, 24, -20, 15, 0, CGAL::CLOCKWISE, - Point(Rational(2,10), Rational(-14,10)), - Point(Rational(14,10), Rational(2,10)))); - insert(arr, ctr_cv(9, 16, 24, 20, -15, 0, CGAL::COUNTERCLOCKWISE, - Point(Rational(-14,10), Rational(-2,10)), - Point(Rational(-2,10), Rational(14,10)))); - insert(arr, ctr_cv(9, 16, -24, 20, 15, 0, CGAL::COUNTERCLOCKWISE, - Point(Rational(-2,10), Rational(-14,10)), - Point(Rational(-14,10), Rational(2,10)))); + CGAL::insert(arr, ctr_cv(9, 16, -24, -20, -15, 0, CGAL::COUNTERCLOCKWISE, + Point(Rational(2,10), Rational(14,10)), + Point(Rational(14,10), Rational(-2,10)))); + CGAL::insert(arr, ctr_cv(9, 16, 24, -20, 15, 0, CGAL::CLOCKWISE, + Point(Rational(2,10), Rational(-14,10)), + Point(Rational(14,10), Rational(2,10)))); + CGAL::insert(arr, ctr_cv(9, 16, 24, 20, -15, 0, CGAL::COUNTERCLOCKWISE, + Point(Rational(-14,10), Rational(-2,10)), + Point(Rational(-2,10), Rational(14,10)))); + CGAL::insert(arr, ctr_cv(9, 16, -24, 20, 15, 0, CGAL::COUNTERCLOCKWISE, + Point(Rational(-2,10), Rational(-14,10)), + Point(Rational(-14,10), Rational(2,10)))); // 9*x*x+16*y*y-24*x*y+20*x+15*y // rotated & translated - insert(arr, ctr_cv(16, 9, -24, -23, -14, 36, CGAL::COUNTERCLOCKWISE, - Point(Rational(8,10), Rational(24,10)), - Point(Rational(24,10), Rational(12,10)))); - insert(arr, ctr_cv(16, 9, 24, 23, -14, 36, CGAL::CLOCKWISE, - Point(Rational(-8,10), Rational(24,10)), - Point(Rational(-24,10), Rational(12,10)))); + CGAL::insert(arr, ctr_cv(16, 9, -24, -23, -14, 36, CGAL::COUNTERCLOCKWISE, + Point(Rational(8,10), Rational(24,10)), + Point(Rational(24,10), Rational(12,10)))); + CGAL::insert(arr, ctr_cv(16, 9, 24, 23, -14, 36, CGAL::CLOCKWISE, + Point(Rational(-8,10), Rational(24,10)), + Point(Rational(-24,10), Rational(12,10)))); // 16*x*x+9*y*y-24*x*y-23*x-14*y+36 From 08c4ad33c5853a5ff846b72177726e896dfff3df Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Sun, 26 Jun 2022 16:03:39 +0300 Subject: [PATCH 043/105] Enhanced --- .../Arrangement_on_surface_2/hyperbolas.cpp | 36 +++++++++++++++++++ .../Arrangement_on_surface_2/parabolas.cpp | 3 -- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/hyperbolas.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/hyperbolas.cpp index ebd35af492d..d16b263fba3 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/hyperbolas.cpp +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/hyperbolas.cpp @@ -22,6 +22,42 @@ int main() { // The arc is counterclockwise oriented. CGAL::insert(arr, ctr_cv(0, 0, 1, 0, 0, -1, CGAL::COUNTERCLOCKWISE, Point(Rational(1,4), 4), Point(2, Rational(1,2)))); + CGAL::insert(arr, ctr_cv(0, 0, -1, 0, 0, -1, CGAL::CLOCKWISE, + Point(Rational(-1,4), 4), Point(-2, Rational(1,2)))); + + CGAL::insert(arr, ctr_cv(2, -1, 0, 0, 0, -2, CGAL::COUNTERCLOCKWISE, + Point(3, 4), Point(1, 0))); + CGAL::insert(arr, ctr_cv(2, -1, 0, 0, 0, -2, CGAL::COUNTERCLOCKWISE, + Point(1, 0), Point(3, -4))); + CGAL::insert(arr, ctr_cv(2, -1, 0, 0, 0, -2, CGAL::CLOCKWISE, + Point(-3, 4), Point(-1, 0))); + CGAL::insert(arr, ctr_cv(2, -1, 0, 0, 0, -2, CGAL::CLOCKWISE, + Point(-1, 0), Point(-3, -4))); + + CGAL::insert(arr, ctr_cv(-1, 2, 0, 0, 0, -2, CGAL::CLOCKWISE, + Point(4, 3), Point(0, 1))); + CGAL::insert(arr, ctr_cv(-1, 2, 0, 0, 0, -2, CGAL::CLOCKWISE, + Point(0, 1), Point(-4, 3))); + CGAL::insert(arr, ctr_cv(-1, 2, 0, 0, 0, -2, CGAL::COUNTERCLOCKWISE, + Point(4, -3), Point(0, -1))); + CGAL::insert(arr, ctr_cv(-1, 2, 0, 0, 0, -2, CGAL::COUNTERCLOCKWISE, + Point(0, -1), Point(-4, -3))); + + CGAL::insert(arr, ctr_cv(4, 46, -144, 0, 0, -100, CGAL::COUNTERCLOCKWISE, + Point(-5, 0), + Point(Rational(14, 10), Rational(48, 10)))); + CGAL::insert(arr, ctr_cv(4, 46, -144, 0, 0, -100, CGAL::COUNTERCLOCKWISE, + Point(5, 0), + Point(Rational(-14, 10), Rational(-48, 10)))); + // 4*x*x + 46*y*y - 144*x*y - 100 + + CGAL::insert(arr, ctr_cv(46, 4, -144, 0, 0, -100, CGAL::CLOCKWISE, + Point(0, -5), + Point(Rational(48, 10), Rational(14, 10)))); + CGAL::insert(arr, ctr_cv(46, 4, -144, 0, 0, -100, CGAL::CLOCKWISE, + Point(0, 5), + Point(Rational(-48, 10), Rational(-14, 10)))); + // 46*x*x + 4*y*y - 144*x*y - 100 print_arrangement_size(arr); diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/parabolas.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/parabolas.cpp index 720e3fe5752..2f3bf04bf61 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/parabolas.cpp +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/parabolas.cpp @@ -16,9 +16,6 @@ int main() { Arrangement arr(&traits); auto ctr_cv = traits.construct_curve_2_object(); - Point p0(0, 0); - CGAL::insert(arr, ctr_cv(Point(-2.4,-1.4), Point(-2.4,2.4))); - CGAL::insert(arr, ctr_cv(Point(2.4,-1.4), Point(2.4,2.4))); // x-major // insert the parabola y = x^2; (-1,1)--(1,1) From 87b6a35b2e1378adf4bba1067a72ee77ae117106 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Sun, 26 Jun 2022 16:03:48 +0300 Subject: [PATCH 044/105] Fixed approximating conics --- .../include/CGAL/Arr_conic_traits_2.h | 430 ++++++++++-------- 1 file changed, 237 insertions(+), 193 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index 0ea91bec920..ac8d4695504 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -1633,6 +1633,29 @@ public: return l; } + /*! The formula for the arc length of a parabola is: + * L = 1/2 * √(b^2+16⋅a^2) + b^2/(8*a) * ln((4*a+√(b^2+16⋅a^2))/b) + * where: + * L is the length of the parabola arc. + * a is the length along the parabola axis. + * b is the length of the chord perpendicular to the axis. + * + * --- + * / | \ + * / |a \ + * / | \ + * /---------\ + * / b \ + * + */ + double parabolic_arc_length(double a, double b) const { + if (a == 0) return b; + if (b == 0) return a; + auto b_sqr = b*b; + auto tmp = std::sqrt(b_sqr+16.0*a*a); + return tmp/2.0 + b_sqr*std::log((4.0*a + tmp)/b)/(8.0*a); + } + /*! Obtain the parabolic arc length. */ double parabola_length(const X_monotone_curve_2& xcv) { @@ -1646,8 +1669,8 @@ public: xs_t, ys_t, xt_t, yt_t, a, ts, tt, cx, cy, xcv); - auto ds = m_traits.parabolic_arc_length(xs_t, 2.0*std::abs(ys_t)); - auto dt = m_traits.parabolic_arc_length(xt_t, 2.0*std::abs(yt_t)); + auto ds = parabolic_arc_length(xs_t, 2.0*std::abs(ys_t)); + auto dt = parabolic_arc_length(xt_t, 2.0*std::abs(yt_t)); auto d = (CGAL::sign(ys_t) == CGAL::sign(yt_t)) ? std::abs(ds - dt)/2.0 : (ds + dt)/2.0; // std::cout << "d, ds, dt = " << d << ", " << ds << "," << dt @@ -1658,11 +1681,13 @@ public: double ellipse_length(const X_monotone_curve_2& xcv) { double r_m, t_m, s_m, u_m, v_m, w_m; double cost, sint; + double xs_t, ys_t, xt_t, yt_t; double a, b; double cx, cy; double ts, tt; m_traits.approximate_ellipse(r_m, t_m, s_m, u_m, v_m, w_m, cost, sint, - ts, tt, a, b, cx, cy, xcv); + xs_t, ys_t, ts, xt_t, yt_t, tt, + a, b, cx, cy, xcv); namespace bm = boost::math; auto ratio = b/a; @@ -1717,24 +1742,24 @@ public: /*! Obtain an approximation of an x-monotone curve. */ template - OutputIterator operator()(OutputIterator oi, double density, + OutputIterator operator()(OutputIterator oi, double error, const X_monotone_curve_2& xcv, bool l2r = true) const { if (xcv.orientation() == COLLINEAR) - return approximate_segment(oi, density, xcv, l2r); + return approximate_segment(oi, xcv, l2r); CGAL::Sign sign_conic = CGAL::sign(4*xcv.r()*xcv.s() - xcv.t()*xcv.t()); if (sign_conic == POSITIVE) - return approximate_ellipse(oi, density, xcv, l2r); + return approximate_ellipse(oi, error, xcv, l2r); if (sign_conic == NEGATIVE) - return approximate_hyperbola(oi, density, xcv, l2r); - return approximate_parabola(oi, density, xcv, l2r); + return approximate_hyperbola(oi, error, xcv, l2r); + return approximate_parabola(oi, error, xcv, l2r); } private: /*! Handle segments. */ template - OutputIterator approximate_segment(OutputIterator oi, double density, + OutputIterator approximate_segment(OutputIterator oi, const X_monotone_curve_2& xcv, bool l2r) const { // std::cout << "SEGMENT\n"; @@ -1751,6 +1776,18 @@ public: return oi; } + /*! Transform a point. In particular, rotate the canonical point + * (`xc`,`yc`) by an angle, the sine and cosine of which are `sint` and + * `cost`, respectively, and translate by (`cx`,`cy`). + */ + void transform_point(double xc, double yc, + double cost, double sint, + double cx, double cy, + double& x, double& y) const { + x = xc*cost - yc*sint + cx; + y = xc*sint + yc*cost + cy; + } + /*! Handle ellipses. * The general equation of an ellipse is: * r·𝑥^2 + s·𝑦^2 + t·𝑥·𝑦 + u·𝑥 + v·𝑦 + w = 0 @@ -1814,12 +1851,12 @@ public: * 𝑥(𝛼) = a·𝑐𝑜𝑠(𝛼)·𝑐𝑜𝑠(𝜃) − b·𝑠𝑖𝑛(𝛼)·𝑠𝑖𝑛(𝜃) + 𝐶𝑥 * 𝑦(𝛼) = a·𝑐𝑜𝑠(𝛼)·𝑠𝑖𝑛(𝜃) + b·𝑠𝑖𝑛(𝛼)·𝑐𝑜𝑠(𝜃) + 𝐶𝑦 * - * @param density the density of the generated approximation. By default - * this value is 1, which implies that approximately every segment - * spans a unit length. + * @param error the error bound of the generated approximation. This is + * the Hausdorff distance between the arc and the polyline, + * which approximates the src. */ template - OutputIterator approximate_ellipse(OutputIterator oi, double density, + OutputIterator approximate_ellipse(OutputIterator oi, double error, const X_monotone_curve_2& xcv, bool l2r) const { // std::cout << "ELLIPSE\n"; @@ -1837,61 +1874,93 @@ public: double r_m, t_m, s_m, u_m, v_m, w_m; double cost, sint; + double xs_t, ys_t, xt_t, yt_t; double a, b; double cx, cy; double ts, tt; m_traits.approximate_ellipse(r_m, t_m, s_m, u_m, v_m, w_m, cost, sint, - ts, tt, a, b, cx, cy, xcv, l2r); + xs_t, ys_t, ts, xt_t, yt_t, tt, + a, b, cx, cy, xcv, l2r); + // std::cout << "a, b: " << a << "," << b << std::endl; - namespace bm = boost::math; - auto ratio = b/a; - auto k = std::sqrt(1 - (ratio*ratio)); - auto ds = a*bm::ellint_2(k, ts); - auto dt = a*bm::ellint_2(k, tt); - auto d = std::abs(dt - ds); - // std::cout << "d, ds, dt: " << d << "," << ds << ", " << dt - // << std::endl; - auto size = static_cast(d*density); - if (size == 0) size = 1; - auto delta_t = (tt - ts) / size; - auto t(ts); *oi++ = Approximate_point_2(xs, ys); - t += delta_t; - if (ts < tt) { - while (t < tt) { - oi = add_elliptic_point(oi, t, a, b, cost, sint, cx, cy); - t += delta_t; - } - } - else { - while (t > tt) { - oi = add_elliptic_point(oi, t, a, b, cost, sint, cx, cy); - t += delta_t; - } - } + add_points(xs_t, ys_t, ts, xt_t, yt_t, tt, error, oi, + [&](double tm, double& xm, double& ym) { + elliptic_point(a, b, tm, xm, ym); + }, + [&](double xc, double& yc, double& x, double& y) { + transform_point(xc, yc, cost, sint, cx, cy, x, y); + }); *oi++ = Approximate_point_2(xt, yt); return oi; } - template - OutputIterator add_elliptic_point(OutputIterator oi, double t, - double a, double b, - double cost, double sint, - double cx, double cy) const { - auto x = a*std::cos(t)*cost - b*std::sin(t)*sint + cx; - auto y = a*std::cos(t)*sint + b*std::sin(t)*cost + cy; - // std::cout << "t,(x, y): " << t << ",(" << x << "," << y << ")" - // << std::endl; + /*! Add either an elliptic or a hyperbilc point. + * The arc endpoints are (`x1`, `y1`) and (`x2`, `y2`). + * In our parametric representations for ellipses and hyperbolas the + * following holds: + * p1 = (x1, y1); x1 = x(t1), y1 = y(t1), and + * p2 = (x2, y2); x2 = x(t2), y2 = y(t2) + * The Hausdorff distance between the arc and the segment (p1,p2) is + * at (xm,ym), where xm = x(tm), ym = y(tmp), and tm = (t1 + t2) / 2. + * \param[in] x1 the canonical-arc source-point \f$x\f$-coordinate. + * \param[in] y1 the canonical-arc source-point \f$y\f$-coordinate. + * \param[in] t1 the source-point parameter; \f$yx1 = x(t1) and y1 = y(t1)\f$y. + * \param[in] x2 the canonical-arc target-point \f$x\f$-coordinate. + * \param[in] y2 the canonical arc target-point \f$y\f$-coordinate. + * \param[in] t2 the target-point parameter; \f$yx2 = x(t2) and y2 = y(t2)\f$y. + * \param[in] error + * \param[out] oi + * \param[in] op a function that computes a point \f$(x(t),y(t))\f$ given \f$t\f$. + * \param[in] transform a function that transforms a canonical point to an + * actual point + * + * Observe that in our parametric representation for parabolas, the + * expression for tm is different. + */ + template + OutputIterator add_points(double x1, double y1, double t1, + double x2, double y2, double t2, + double error, OutputIterator oi, + Op op, Transform transform) const { + auto tm = (t1 + t2)*0.5; + + // Compute the canocal point where the error is maximal. + double xm, ym; + op(tm, xm, ym); + + auto dx = x2 - x1; + auto dy = y2 - y1; + + // Compute the error; abort if it is below the threshold + auto l = std::sqrt(dx*dx + dy*dy); + auto e = std::abs((xm*dy - ym*dx + x2*y1 - x1*y2) / l); + if (e < error) return oi; + + double x, y; + transform(xm, ym, x, y); + add_points(x1, y1, t1, xm, ym, tm, error, oi, op, transform); *oi++ = Approximate_point_2(x, y); + add_points(xm, ym, tm, x2, y2, t2, error, oi, op, transform); return oi; } + /*! Compute the hyperbolic point given the parameter t and the transform + * data, that is, the center (translation) and the sin and cos of the + * rotation angle. + */ + void elliptic_point(double a, double b, double t, + double& x, double& y) const { + x = a * std::cos(t); + y = b * std::sin(t); + } + /*! Handle parabolas. * The arc-length closed form can be found here: * https://www.vcalc.com/wiki/vCalc/Parabola+-+arc+length */ template - OutputIterator approximate_parabola(OutputIterator oi, double density, + OutputIterator approximate_parabola(OutputIterator oi, double error, const X_monotone_curve_2& xcv, bool l2r) const { // std::cout << "PARABOLA\n"; @@ -1916,86 +1985,87 @@ public: m_traits.approximate_parabola(r_m, t_m, s_m, u_m, v_m, w_m, cost, sint, xs_t, ys_t, xt_t, yt_t, a, ts, tt, cx, cy, xcv, l2r); + // std::cout << "sint, cost: " << sint << "," << cost << std::endl; + // std::cout << "a: " << a << std::endl; + // std::cout << "xs' = " << xs_t << "," << ys_t << std::endl; + // std::cout << "xt' = " << xt_t << "," << yt_t << std::endl; + // std::cout << "ts,tt = " << ts << "," << tt << std::endl; - auto ds = m_traits.parabolic_arc_length(xs_t, 2.0*std::abs(ys_t)); - auto dt = m_traits.parabolic_arc_length(xt_t, 2.0*std::abs(yt_t)); - auto d = (CGAL::sign(ys_t) == CGAL::sign(yt_t)) ? - std::abs(ds - dt)/2.0 : (ds + dt)/2.0; - // std::cout << "d, ds, dt = " << d << ", " << ds << "," << dt - // << std::endl; - - auto t(ts); - auto size = static_cast(d*density); - if (size == 0) size = 1; *oi++ = Approximate_point_2(xs, ys); - auto delta_t = (tt - ts) / size; - auto delta_d = d / size; - adjust(t, delta_t, delta_d, a, 1.0/(density*2.0)); - - if (ts < tt) { - while (t < tt) { - oi = add_parabolic_point(oi, t, a, cost, sint, cx, cy); - adjust(t, delta_t, delta_d, a, 1.0/(density*2.0)); - } - } - else { - while (t > tt) { - oi = add_parabolic_point(oi, t, a, cost, sint, cx, cy); - adjust(t, delta_t, delta_d, a, 1.0/(density*2.0)); - } - } + add_parabolic_points(xs_t, ys_t, ts, xt_t, yt_t, tt, error, oi, + [&](double tm, double& xm, double& ym) { + parabolic_point(a, tm, xm, ym); + }, + [&](double xc, double& yc, double& x, double& y) { + transform_point(xc, yc, cost, sint, cx, cy, x, y); + }); *oi++ = Approximate_point_2(xt, yt); return oi; } - template - OutputIterator add_parabolic_point(OutputIterator oi, double t, double a, - double cost, double sint, - double cx, double cy) const { - auto xt = a*t*t; - auto yt = 2.0*a*t; - auto x = xt*cost - yt*sint + cx; - auto y = xt*sint + yt*cost + cy; - // std::cout << "t,(x,y): " << t << ",(" << x << "," << y << ")" - // << std::endl; + /*! Add either an elliptic or a hyperbilc point. + * The arc endpoints are (`x1`, `y1`) and (`x2`, `y2`). + * In our parametric representations for ellipses and hyperbolas the + * following holds: + * \f$p1 = (x1, y1); x1 = x(t1), y1 = y(t1)\f$, and + * \f$p2 = (x2, y2); x2 = x(t2), y2 = y(t2)\f$ + * The Hausdorff distance between the arc and the segment (p1,p2) is + * at (xm,ym), where xm = x(tm), ym = y(tmp), and tm = (x2-x1) / (y2-y1). + * \param[in] x1 the canonical-arc source-point \f$x\f$-coordinate. + * \param[in] y1 the canonical-arc source-point \f$y\f$-coordinate. + * \param[in] t1 the source-point parameter; \f$yx1 = x(t1) and y1 = y(t1)\f$y. + * \param[in] x2 the canonical-arc target-point \f$x\f$-coordinate. + * \param[in] y2 the canonical arc target-point \f$y\f$-coordinate. + * \param[in] t2 the target-point parameter; \f$yx2 = x(t2) and y2 = y(t2)\f$y. + * \param[in] error + * \param[out] oi + * \param[in] op a function that computes a point \f$(x(t),y(t))\f$ given \f$t\f$. + * \param[in] transform a function that transforms a canonical point to an + * actual point + * + * Observe that in our parametric representation for ellipses and + * hyperbolas, the expression for tm is different. + */ + template + OutputIterator add_parabolic_points(double x1, double y1, double t1, + double x2, double y2, double t2, + double error, OutputIterator oi, + Op op, Transform transform) const { + auto dx = x2 - x1; + auto dy = y2 - y1; + auto tm = (dy == 0) ? 0 : dx / dy; + + // Compute the canocal point where the error is maximal. + double xm, ym; + op(tm, xm, ym); + + // Compute the error and abort if it is below the threshold + auto l = std::sqrt(dx*dx + dy*dy); + auto e = std::abs((xm*dy - ym*dx + x2*y1 - x1*y2) / l); + if (e < error) return oi; + + // Compute the actual (transformed) point + double x, y; + transform(xm, ym, x, y); + add_parabolic_points(x1, y1, t1, xm, ym, tm, error, oi, op, transform); *oi++ = Approximate_point_2(x, y); + add_parabolic_points(xm, ym, tm, x2, y2, t2, error, oi, op, transform); return oi; } - void adjust(double& t, double delta_t, double delta_d, double a, - double e) const { -#if 1 - t += delta_t; -#else - auto xt_prev = 2.0*a*t; - auto yt_prev = a*t*t; - auto dt_prev = m_traits.parabolic_arc_length(yt_prev, 2.0*std::abs(xt_prev)); - - double d_t(delta_t); - double d; - double s(1); - do { - std::cout << "t: " << t << std::endl; - t += d_t*s; - - auto xt = 2.0*a*t; - auto yt = a*t*t; - auto dt = m_traits.parabolic_arc_length(yt, 2.0*std::abs(xt)); - d = (CGAL::sign(xt_prev) == CGAL::sign(xt)) ? - std::abs(dt - dt_prev)/2.0 : (dt + dt_prev)/2.0; - - if (std::abs(d - delta_d) <= e) break; - d_t /= 2.0; - s = (d > delta_d) ? -1 : 1; - } while (true); - std::cout << "d: " << d << "," << e << std::endl; -#endif + /*! Compute the parabolic point given the parameter t and the transform + * data, that is, the center (translation) and the sin and cos of the + * rotation angle. + */ + void parabolic_point(double a, double t, double& x, double& y) const { + x = a*t*t; + y = 2.0*a*t; } /*! Handle hyperbolas. */ template - OutputIterator approximate_hyperbola(OutputIterator oi, double density, + OutputIterator approximate_hyperbola(OutputIterator oi, double error, const X_monotone_curve_2& xcv, bool l2r) const { // std::cout << "HYPERBOLA\n"; @@ -2010,49 +2080,37 @@ public: double r_m, t_m, s_m, u_m, v_m, w_m; double cost, sint; + double xs_t, ys_t, xt_t, yt_t; double a, b; double cx, cy; double ts, tt; m_traits.approximate_hyperbola(r_m, t_m, s_m, u_m, v_m, w_m, cost, sint, - ts, tt, a, b, cx, cy, xcv, l2r); + xs_t, ys_t, ts, xt_t, yt_t, tt, + a, b, cx, cy, xcv, l2r); + // std::cout << "a, b: " << a << "," << b << std::endl; + // std::cout << "ts, tt: " << ts << "," << tt << std::endl; - auto t(ts); - auto size = static_cast(density); - if (size == 0) size = 1; + // std::cout << "a, b: " << a << "," << b << std::endl; *oi++ = Approximate_point_2(xs, ys); - auto delta_t = (tt - ts) / size; - t += delta_t; - - if (ts < tt) { - while (t < tt) { - oi = add_hyperbolic_point(oi, t, a, b, cost, sint, cx, cy); - t += delta_t; - } - } - else { - while (t > tt) { - oi = add_hyperbolic_point(oi, t, a, b, cost, sint, cx, cy); - t += delta_t; - } - } + add_points(xs_t, ys_t, ts, xt_t, yt_t, tt, error, oi, + [&](double tm, double& xm, double& ym) { + hyperbolic_point(a, b, tm, xm, ym); + }, + [&](double xc, double& yc, double& x, double& y) { + transform_point(xc, yc, cost, sint, cx, cy, x, y); + }); *oi++ = Approximate_point_2(xt, yt); return oi; } - template - OutputIterator add_hyperbolic_point(OutputIterator oi, double t, - double a, double b, - double cost, double sint, - double cx, double cy) const { - auto xt = a * std::cosh(t); - auto yt = b * std::sinh(t); - - auto x = xt*cost - yt*sint + cx; - auto y = xt*sint + yt*cost + cy; - // std::cout << "t,(x,y): " << t << ",(" << x << "," << y << ")" - // << std::endl; - *oi++ = Approximate_point_2(x, y); - return oi; + /*! Compute the hyperbolic point given the parameter t and the transform + * data, that is, the center (translation) and the sin and cos of the + * rotation angle. + */ + void hyperbolic_point(double a, double b, double t, + double& x, double& y) const { + x = a * std::cosh(t); + y = b * std::sinh(t); } }; @@ -3941,6 +3999,18 @@ public: inverse_conic(xcv, cost, sint, r_m, s_m, t_m, u_m, v_m, w_m); } + /*! Inverse transform a point. In particular, inversly rotate the point + * (`x`,`y`) by an angle, the sine and cosine of which are `sint` and + * `cost`, respectively, and translate by (`-cx`,`-cy`). + */ + void inverse_transform_point(double x, double y, + double cost, double sint, + double cx, double cy, + double& xc, double& yc) const { + xc = x*cost + y*sint - cx; + yc = -x*sint + y*cost - cy; + } + /*! Handle parabolas. * The arc-length closed form can be found here: * https://www.vcalc.com/wiki/vCalc/Parabola+-+arc+length @@ -3989,7 +4059,6 @@ public: } // std::cout << r_m << "," << s_m << "," << t_m << "," // << u_m << "," << v_m << "," << w_m << std::endl; - // std::cout << "sint, cost: " << sint << "," << cost << std::endl; // Compute the center of the inversly rotated parabola: // double cx_m = -u_m / (2*r_m); @@ -3998,18 +4067,13 @@ public: auto cy_m = -v_m / (2*s_m); // std::cout << "cx_m, cy_m: " << cx_m << "," << cy_m << std::endl; - // Transform the source and target - xs_t = xs*cost + ys*sint - cx_m; - ys_t = -xs*sint + ys*cost - cy_m; - xt_t = xt*cost + yt*sint - cx_m; - yt_t = -xt*sint + yt*cost - cy_m; + // Inverse transform the source and target + inverse_transform_point(xs, ys, cost, sint, cx_m, cy_m, xs_t, ys_t); + inverse_transform_point(xt, yt, cost, sint, cx_m, cy_m, xt_t, yt_t); a = -u_m / (4.0*s_m); ts = ys_t / (2.0*a); tt = yt_t / (2.0*a); - // std::cout << "xs' = " << xs_t << "," << ys_t << std::endl; - // std::cout << "xt' = " << xt_t << "," << yt_t << std::endl; - // std::cout << "ts,tt = " << ts << "," << tt << std::endl; // Compute the center (cx,cy) of the ellipse, rotating back: cx = cx_m*cost - cy_m*sint; @@ -4017,34 +4081,13 @@ public: // std::cout << "center: " << cx << "," << cy << std::endl; } - /*! The formula for the arc length of a parabola is: - * L = 1/2 * √(b^2+16⋅a^2) + b^2/(8*a) * ln((4*a+√(b^2+16⋅a^2))/b) - * where: - * L is the length of the parabola arc. - * a is the length along the parabola axis. - * b is the length of the chord perpendicular to the axis. - * - * --- - * / | \ - * / |a \ - * / | \ - * /---------\ - * / b \ - * - */ - double parabolic_arc_length(double a, double b) const { - if (a == 0) return b; - if (b == 0) return a; - auto b_sqr = b*b; - auto tmp = std::sqrt(b_sqr+16.0*a*a); - return tmp/2.0 + b_sqr*std::log((4.0*a + tmp)/b)/(8.0*a); - } - /*! Handle ellipses. */ void approximate_ellipse(double& r_m, double& t_m, double& s_m, double& u_m, double& v_m, double& w_m, - double& cost, double& sint, double& ts, double& tt, + double& cost, double& sint, + double& xs_t, double& ys_t, double& ts, + double& xt_t, double& yt_t, double& tt, double& a, double& b, double& cx, double& cy, const X_monotone_curve_2& xcv, bool l2r = true) const { @@ -4081,7 +4124,6 @@ public: a = std::sqrt(a_sqr); b = std::sqrt(b_sqr); - // std::cout << "a, b: " << a << "," << b << std::endl; // Compute the center of the inversly rotated ellipse: auto cx_m = -u_m / (2*r_m); @@ -4092,16 +4134,22 @@ public: cy = cx_m*sint + cy_m*cost; // std::cout << "center: " << cx << "," << cy << std::endl; + // Inverse transform the source and target + inverse_transform_point(xs, ys, cost, sint, cx_m, cy_m, xs_t, ys_t); + inverse_transform_point(xt, yt, cost, sint, cx_m, cy_m, xt_t, yt_t); + // std::cout << "xs_t,ys_t: " << xs_t << "," << ys_t << std::endl; + // std::cout << "xt_t,yt_t: " << xt_t << "," << yt_t << std::endl; + // Compute the parameters ts and tt such that // source == (x(ts),y(ts)), and // target == (x(tt),y(tt)) auto xds = xs - cx; auto yds = ys - cy; - ts = std::atan2(a*(cost*yds - sint*xds),b*(sint*yds + cost*xds)); + ts = std::atan2(a*ys_t, b*xs_t); if (ts < 0) ts += 2*M_PI; auto xdt = xt - cx; auto ydt = yt - cy; - tt = std::atan2(a*(cost*ydt - sint*xdt),b*(sint*ydt + cost*xdt)); + tt = std::atan2(a*yt_t, b*xt_t); if (tt < 0) tt += 2*M_PI; auto orient(xcv.orientation()); if (xcv.source() != src) orient = CGAL::opposite(orient); @@ -4116,11 +4164,11 @@ public: /*! Handle hyperbolas. */ - /*! Handle ellipses. - */ void approximate_hyperbola(double& r_m, double& t_m, double& s_m, double& u_m, double& v_m, double& w_m, - double& cost, double& sint, double& ts, double& tt, + double& cost, double& sint, + double& xs_t, double& ys_t, double& ts, + double& xt_t, double& yt_t, double& tt, double& a, double& b, double& cx, double& cy, const X_monotone_curve_2& xcv, bool l2r = true) const { @@ -4172,11 +4220,9 @@ public: auto cx_m = -u_m / (2*r_m); auto cy_m = -v_m / (2*s_m); - // Transform the source and target - auto xs_t = xs*cost + ys*sint - cx_m; - auto ys_t = -xs*sint + ys*cost - cy_m; - auto xt_t = xt*cost + yt*sint - cx_m; - auto yt_t = -xt*sint + yt*cost - cy_m; + // Inverse transform the source and target + inverse_transform_point(xs, ys, cost, sint, cx_m, cy_m, xs_t, ys_t); + inverse_transform_point(xt, yt, cost, sint, cx_m, cy_m, xt_t, yt_t); // std::cout << "xs_t,ys_t: " << xs_t << "," << ys_t << std::endl; // std::cout << "xt_t,yt_t: " << xt_t << "," << yt_t << std::endl; @@ -4198,8 +4244,6 @@ public: ts = std::asinh(ys_t/b); tt = std::asinh(yt_t/b); assert(std::signbit(xs_t) == std::signbit(xt_t)); - // std::cout << "a, b: " << a << "," << b << std::endl; - // std::cout << "ts, tt: " << ts << "," << tt << std::endl; if (std::signbit(xs_t)) a = -a; } From 597c1a96a4e5efe5c14cdc1c9cb8f39ebc3a7bb3 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Sun, 26 Jun 2022 16:04:17 +0300 Subject: [PATCH 045/105] Fixed density; added callback to capture window size --- .../include/CGAL/draw_arrangement_2.h | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h index 33fd1b03d45..a5cae7516cc 100644 --- a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h +++ b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h @@ -38,6 +38,11 @@ public: m_uni(0, 255) {} + virtual void resizeGL(int width, int height) { + m_width = width; + m_height = height; + } + //! void add_elements() { clear(); @@ -60,6 +65,8 @@ public: draw_point(it->point()); m_visited.clear(); + + // auto bb = bounding_box(); } protected: @@ -177,6 +184,12 @@ protected: } protected: + //! The window width in pixels. + int m_width; + + //! The window height in pixels. + int m_height; + //! The arrangement to draw const Arr& m_arr; @@ -257,9 +270,9 @@ public: curr = curr->twin()->next(); std::vector polyline; - double density(10); + double error(0.01); bool l2r = curr->direction() == ARR_LEFT_TO_RIGHT; - approx(std::back_inserter(polyline), density, curr->curve(), l2r); + approx(std::back_inserter(polyline), error, curr->curve(), l2r); auto it = polyline.begin(); auto prev = it++; for (; it != polyline.end(); prev = it++) { @@ -277,8 +290,8 @@ public: const auto* traits = this->m_arr.geometry_traits(); auto approx = traits->approximate_2_object(); std::vector polyline; - double density(10); - approx(std::back_inserter(polyline), density, curve); + double error(0.01); + approx(std::back_inserter(polyline), error, curve); auto it = polyline.begin(); auto prev = it++; for (; it != polyline.end(); prev = it++) this->add_segment(*prev, *it); From f18f690c08fb609f99e41168c056456cca6d4886 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Mon, 27 Jun 2022 13:16:10 +0300 Subject: [PATCH 046/105] moved an obsolete example --- .../examples/Arrangement_on_surface_2/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/CMakeLists.txt b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/CMakeLists.txt index b40ee522e16..213a2566931 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/CMakeLists.txt +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/CMakeLists.txt @@ -21,5 +21,4 @@ if(CGAL_Qt5_FOUND) target_link_libraries(parabolas PUBLIC CGAL::CGAL_Basic_viewer) target_link_libraries(ellipses PUBLIC CGAL::CGAL_Basic_viewer) target_link_libraries(hyperbolas PUBLIC CGAL::CGAL_Basic_viewer) - target_link_libraries(old_conics PUBLIC CGAL::CGAL_Basic_viewer) endif() From 771146b70b170ece91e34c30afcd0b2879b4f6fd Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Mon, 27 Jun 2022 18:13:30 +0300 Subject: [PATCH 047/105] Enhanced --- .../Arrangement_on_surface_2/hyperbolas.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/hyperbolas.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/hyperbolas.cpp index d16b263fba3..aa68c6c247f 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/hyperbolas.cpp +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/hyperbolas.cpp @@ -59,6 +59,21 @@ int main() { Point(Rational(-48, 10), Rational(-14, 10)))); // 46*x*x + 4*y*y - 144*x*y - 100 + CGAL::insert(arr, ctr_cv(4, 46, 144, 0, 0, -100, CGAL::CLOCKWISE, + Point(-5, 0), + Point(Rational(14,10), Rational(-48,10)))); + CGAL::insert(arr, ctr_cv(4, 46, 144, 0, 0, -100, CGAL::CLOCKWISE, + Point(5, 0), + Point(Rational(-14,10), Rational(48,10)))); + // 4*x*x + 46*y*y + 144*x*y - 100 + + CGAL::insert(arr, ctr_cv(46, 4, 144, 0, 0, -100, CGAL::COUNTERCLOCKWISE, + Point(0, -5), + Point(Rational(-48,10), Rational(14,10)))); + CGAL::insert(arr, ctr_cv(46, 4, 144, 0, 0, -100, CGAL::COUNTERCLOCKWISE, + Point(0, 5), + Point(Rational(48,10), Rational(-14,10)))); + print_arrangement_size(arr); CGAL::draw(arr); From 6688e9b156765cb8e48128436deec1b1a8db601d Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Mon, 27 Jun 2022 18:21:49 +0300 Subject: [PATCH 048/105] Cleaned up --- .../include/CGAL/Arr_conic_traits_2.h | 348 +++++++++--------- .../include/CGAL/draw_arrangement_2.h | 25 +- 2 files changed, 200 insertions(+), 173 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index ac8d4695504..b1cf4d5fbb3 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -160,7 +160,7 @@ public: const Traits& m_traits; /*! Constructor - * \param traits the traits. + * \param traits The traits. */ Compare_x_2(const Traits& traits) : m_traits(traits) {} @@ -189,7 +189,7 @@ public: const Traits& m_traits; /*! Constructor - * \param traits the traits. + * \param traits The traits. */ Compare_xy_2(const Traits& traits) : m_traits(traits) {} @@ -199,9 +199,9 @@ public: /*! Compares two points lexigoraphically: by x, then by y. * \param p1 The first point. * \param p2 The second point. - * \return LARGER if x(p1) > x(p2), or if x(p1) = x(p2) and y(p1) > y(p2); - * SMALLER if x(p1) < x(p2), or if x(p1) = x(p2) and y(p1) < y(p2); - * EQUAL if the two points are equal. + * \return `LARGER` if `x(p1) > x(p2)`, or if `x(p1) = x(p2)` and `y(p1) > y(p2)`; + * `SMALLER` if `x(p1) < x(p2)`, or if `x(p1) = x(p2)` and `y(p1) < y(p2)`; + * `EQUAL` if the two points are equal. */ Comparison_result operator()(const Point_2& p1, const Point_2& p2) const { return m_traits.m_alg_kernel->compare_xy_2_object()(p1, p2); } @@ -212,8 +212,8 @@ public: class Construct_min_vertex_2 { public: - /*! Obtain the left endpoint of the x-monotone curve (segment). - * \param cv The curve. + /*! Obtain the left endpoint of an x-monotone arc. + * \param cv The arc. * \return The left endpoint. */ const Point_2& operator()(const X_monotone_curve_2& xcv) const @@ -226,8 +226,8 @@ public: class Construct_max_vertex_2 { public: - /*! Obtain the right endpoint of the x-monotone curve (segment). - * \param cv The curve. + /*! Obtain the right endpoint of the x-monotone arc. + * \param cv The arc. * \return The right endpoint. */ const Point_2& operator()(const X_monotone_curve_2& xcv) const @@ -240,9 +240,9 @@ public: class Is_vertical_2 { public: - /*! Check whether the given x-monotone curve is a vertical segment. - * \param cv The curve. - * \return (true) if the curve is a vertical segment; (false) otherwise. + /*! Check whether a given x-monotone arc is a vertical segment. + * \param cv The vertical segment. + * \return `true` if the arc is a vertical segment; `false` otherwise. */ bool operator()(const X_monotone_curve_2& cv) const { return cv.is_vertical(); } @@ -259,20 +259,20 @@ public: const Traits& m_traits; /*! Constructor - * \param traits the traits. + * \param traits The traits. */ Compare_y_at_x_2(const Traits& traits) : m_traits(traits) {} friend class Arr_conic_traits_2; public: - /*! Return the location of the given point with respect to the input curve. - * \param xcv The curve. + /*! Return the location of a given point with respect to an input arc. + * \param xcv The arc. * \param p The point. - * \pre p is in the x-range of cv. - * \return SMALLER if y(p) < cv(x(p)), i.e. the point is below the curve; - * LARGER if y(p) > cv(x(p)), i.e. the point is above the curve; - * EQUAL if p lies on the curve. + * \pre `p` is in the \f$x\f$-range of `xcv`. + * \return `SMALLER` if `y(p) < xcv(x(p))`, i.e. the point is below the arc; + * `LARGER` if `y(p) > xcv(x(p))`, i.e. the point is above the arc; + * `EQUAL` if `p` lies on the curve. */ Comparison_result operator()(const Point_2& p, const X_monotone_curve_2& xcv) const { @@ -311,11 +311,11 @@ public: } private: - /*! Compute a point on the arc with the same x-coordiante as the given + /*! Compute a point on an arc with the same \f$x\f$-coordiante as the given * point. * \param p The given point. - * \pre The arc is not vertical and p is in the x-range of the arc. - * \return A point on the arc with the same x-coordiante as p. + * \pre The arc is not vertical and `p` is in the \f$x\f$-range of the arc. + * \return A point on the arc with the same \f$x\f$-coordiante as `p`. */ Point_2 point_at_x(const X_monotone_curve_2& xcv, const Point_2& p) const { // Make sure that p is in the x-range of the arc. @@ -404,22 +404,22 @@ public: const Traits& m_traits; /*! Constructor - * \param traits the traits. + * \param traits The traits. */ Compare_y_at_x_left_2(const Traits& traits) : m_traits(traits) {} friend class Arr_conic_traits_2; public: - /*! Compares the y value of two x-monotone curves immediately to the left - * of their intersection point. - * \param xcv1 The first curve. - * \param xcv2 The second curve. + /*! Compares the \f$y\f$ value of two \f$x\f$-monotone arcs immediately + * to the left of their intersection point. + * \param xcv1 The first arc. + * \param xcv2 The second arc. * \param p The intersection point. - * \pre The point p lies on both curves, and both of them must be also be + * \pre The point `p` lies on both curves, and both of them must be also be * defined (lexicographically) to its left. - * \return The relative position of xcv1 with respect to xcv2 immdiately to - * the left of p: SMALLER, LARGER or EQUAL. + * \return The relative position of `xcv1` with respect to `xcv2` immdiately + * to the left of `p`: `SMALLER`, `LARGER`, or `EQUAL`. */ Comparison_result operator()(const X_monotone_curve_2& xcv1, const X_monotone_curve_2& xcv2, @@ -443,10 +443,11 @@ public: } private: - /*! Compare to arcs immediately to the leftt of their intersection point. - * \param arc The compared arc. + /*! Compare two arcs immediately to the leftt of their intersection point. + * \param xcv1 The first compared arc. + * \param xcv2 The second compared arc. * \param p The reference intersection point. - * \return The relative position of the arcs to the left of p. + * \return The relative position of the arcs to the left of `p`. * \pre Both arcs we compare are not vertical segments. */ Comparison_result compare_to_left(const X_monotone_curve_2& xcv1, @@ -588,15 +589,15 @@ public: friend class Arr_conic_traits_2; public: - /*! Compares the y value of two x-monotone curves immediately to the right - * of their intersection point. - * \param xcv1 The first curve. - * \param xcv2 The second curve. + /*! Compares the `y` value of two \f$x\f$-monotone arcs immediately + * to the right of their intersection point. + * \param xcv1 The first arc. + * \param xcv2 The second arc. * \param p The intersection point. - * \pre The point p lies on both curves, and both of them must be also be + * \pre The point `p` lies on both curves, and both of them must be also be * defined (lexicographically) to its right. - * \return The relative position of xcv1 with respect to xcv2 immdiately to - * the right of p: SMALLER, LARGER or EQUAL. + * \return The relative position of `xcv1` with respect to `xcv2` immdiately + * to the right of `p`: `SMALLER`, `LARGER`, or `EQUAL`. */ Comparison_result operator()(const X_monotone_curve_2& xcv1, const X_monotone_curve_2& xcv2, @@ -620,10 +621,11 @@ public: } private: - /*! Compare to arcs immediately to the right of their intersection point. - * \param arc The compared arc. + /*! Compare two arcs immediately to the right of their intersection point. + * \param xcv1 The first compared arc. + * \param xcv2 The second compared arc. * \param p The reference intersection point. - * \return The relative position of the arcs to the right of p. + * \return The relative position of the arcs to the right of `p`. * \pre Both arcs we compare are not vertical segments. */ Comparison_result compare_to_right(const X_monotone_curve_2& xcv1, @@ -750,18 +752,18 @@ public: const Traits& m_traits; /*! Constructor - * \param traits the traits. + * \param traits The traits. */ Equal_2(const Traits& traits) : m_traits(traits) {} friend class Arr_conic_traits_2; public: - /*! Check whether the two x-monotone curves are the same (have the same + /*! Check whether two \f$x\f$-monotone curves are the same (have the same * graph). * \param xcv1 The first curve. * \param xcv2 The second curve. - * \return (true) if the two curves are the same; (false) otherwise. + * \return `true` if the two curves are the same; `false` otherwise. */ bool operator()(const X_monotone_curve_2& xcv1, const X_monotone_curve_2& xcv2) const @@ -770,10 +772,10 @@ public: return equals(xcv1, xcv2); } - /*! Check whether the two points are the same. + /*! Check whether two points are the same. * \param p1 The first point. * \param p2 The second point. - * \return (true) if the two point are the same; (false) otherwise. + * \return `true` if the two point are the same; `false` otherwise. */ bool operator()(const Point_2& p1, const Point_2& p2) const { if (&p1 == &p2) return (true); @@ -781,9 +783,10 @@ public: } private: - /*! Check whether the two arcs are equal (have the same graph). - * \param arc The compared arc. - * \return (true) if the two arcs have the same graph; (false) otherwise. + /*! Check whether two arcs are equal (have the same graph). + * \param xcv1 The first compared arc. + * \param xcv2 The second compared arc. + * \return `true` if the two arcs have the same graph; `false` otherwise. */ bool equals(const X_monotone_curve_2& xcv1, const X_monotone_curve_2& xcv2) const { @@ -821,21 +824,21 @@ public: //@{ /*! A function object that obtains the parameter space of a geometric - * entity along the x-axis + * entity along the \f$x-\f$xaxis. */ class Parameter_space_in_x_2 { public: - /*! Obtains the parameter space at the end of a line along the x-axis. - * \param xcv the line - * \param ce the line end indicator: - * ARR_MIN_END - the minimal end of xc or - * ARR_MAX_END - the maximal end of xc - * \return the parameter space at the ce end of the line xcv. - * ARR_LEFT_BOUNDARY - the line approaches the identification arc from - * the right at the line left end. - * ARR_INTERIOR - the line does not approache the identification arc. - * ARR_RIGHT_BOUNDARY - the line approaches the identification arc from - * the left at the line right end. + /*! Obtains the parameter space at the end of an arc along the \f$x\f$-axis. + * \param xcv The arc. + * \param ce The arc end indicator: + * `ARR_MIN_END`—the minimal end of `xcv` or + * `ARR_MAX_END`—the maximal end of `xcv`. + * \return the parameter space at the `ce` end of the arc `xcv`. + * `ARR_LEFT_BOUNDARY` —the arc approaches the identification curve from + * the right at the arc left end. + * `ARR_INTERIOR` —the arc does not approache the identification curve. + * `ARR_RIGHT_BOUNDARY`—the arc approaches the identification curve from + * the left at the arc right end. */ Arr_parameter_space operator()(const X_monotone_curve_2 & xcv, Arr_curve_end ce) const { @@ -843,9 +846,9 @@ public: return ARR_INTERIOR; } - /*! Obtains the parameter space at a point along the x-axis. - * \param p the point. - * \return the parameter space at p. + /*! Obtains the parameter space at a point along the \f$x\f$-axis. + * \param p The point. + * \return the parameter space at `p`. */ Arr_parameter_space operator()(const Point_2 ) const { return ARR_INTERIOR; } @@ -860,22 +863,22 @@ public: */ class Parameter_space_in_y_2 { public: - /*! Obtains the parameter space at the end of a line along the y-axis . - * Note that if the line end coincides with a pole, then unless the line - * coincides with the identification arc, the line end is considered to + /*! Obtains the parameter space at the end of an arc along the \f$y\f$-axis . + * Note that if the arc end coincides with a pole, then unless the arc + * coincides with the identification curve, the arc end is considered to * be approaching the boundary, but not on the boundary. - * If the line coincides with the identification arc, it is assumed to + * If the arc coincides with the identification curve, it is assumed to * be smaller than any other object. - * \param xcv the line - * \param ce the line end indicator: - * ARR_MIN_END - the minimal end of xc or - * ARR_MAX_END - the maximal end of xc - * \return the parameter space at the ce end of the line xcv. - * ARR_BOTTOM_BOUNDARY - the line approaches the south pole at the line - * left end. - * ARR_INTERIOR - the line does not approache a contraction point. - * ARR_TOP_BOUNDARY - the line approaches the north pole at the line - * right end. + * \param xcv The arc. + * \param ce The arc end indicator: + * `ARR_MIN_END`—the minimal end of `xcv` or + * `ARR_MAX_END`—the maximal end of `xcv`. + * \return the parameter space at the `ce` end of the arc `xcv`. + * `ARR_BOTTOM_BOUNDARY`—the arc approaches the south pole at the arc + * left end. + * `ARR_INTERIOR` —the arc does not approache a contraction point. + * `ARR_TOP_BOUNDARY` —the arc approaches the north pole at the arc + * right end. */ Arr_parameter_space operator()(const X_monotone_curve_2& xcv, Arr_curve_end ce) const { @@ -883,9 +886,9 @@ public: return ARR_INTERIOR; } - /*! Obtains the parameter space at a point along the y-axis. - * \param p the point. - * \return the parameter space at p. + /*! Obtains the parameter space at a point along the \f$y\f$-axis. + * \param p The point. + * \return The parameter space at `p`. */ Arr_parameter_space operator()(const Point_2 /* p */) const { return ARR_INTERIOR; } @@ -911,16 +914,16 @@ public: const Traits& m_traits; /*! Constructor - * \param traits the traits. + * \param traits The traits. */ Make_x_monotone_2(const Traits& traits) : m_traits(traits) {} friend class Arr_conic_traits_2; public: - /*! Subdivide a given conic curve (or conic arc) into x-monotone subcurves + /*! Subdivide a given conic arc into \f$x\f$-monotone sub arcs * and insert them to a given output iterator. - * \param cv the curve. + * \param cv The arc. * \param oi the output iterator for the result. Its dereference type is a * variant that wraps a \c Point_2 or an \c X_monotone_curve_2 * objects. @@ -1026,19 +1029,19 @@ public: const Traits& m_traits; /*! Constructor - * \param traits the traits. + * \param traits The traits. */ Split_2(const Traits& traits) : m_traits(traits) {} friend class Arr_conic_traits_2; public: - /*! Split a given x-monotone curve at a given point into two sub-curves. - * \param cv The curve to split + /*! Split a given \f$x\f$-monotone arc at a given point into two sub-arcs. + * \param xcv The arc to split * \param p The split point. - * \param c1 Output: The left resulting subcurve (p is its right endpoint). - * \param c2 Output: The right resulting subcurve (p is its left endpoint). - * \pre p lies on cv but is not one of its end-points. + * \param xcv1 Output: The left resulting sub-arc (`p` is its right endpoint). + * \param xcv2 Output: The right resulting sub-arc (`p` is its left endpoint). + * \pre `p` lies on `xcv` but is not one of its end-points. */ void operator()(const X_monotone_curve_2& xcv, const Point_2 & p, X_monotone_curve_2& xcv1, X_monotone_curve_2& xcv2) const @@ -1047,9 +1050,9 @@ public: private: /*! Split the arc into two at a given split point. * \param p The split point. - * \param xcv1 Output: The first resulting arc, lying to the left of p. - * \param xcv2 Output: The first resulting arc, lying to the right of p. - * \pre p lies in the interior of the arc (not one of its endpoints). + * \param xcv1 Output: The first resulting arc, lying to the left of `p`. + * \param xcv2 Output: The first resulting arc, lying to the right of `p`. + * \pre `p` lies in the interior of the arc (not one of its endpoints). */ void split(const X_monotone_curve_2& xcv, const Point_2& p, X_monotone_curve_2& xcv1, X_monotone_curve_2& xcv2) const { @@ -1100,7 +1103,7 @@ public: const Traits& m_traits; /*! Constructor. - * \param traits the traits. + * \param traits The traits. */ Intersect_2(const Traits& traits) : m_traits(traits) {} @@ -1110,8 +1113,8 @@ public: /*! Find the intersections of the two given curves and insert them to the * given output iterator. As two segments may itersect only once, only a * single will be contained in the iterator. - * \param cv1 The first curve. - * \param cv2 The second curve. + * \param cv1 The first arc. + * \param cv2 The second arc. * \param oi The output iterator. * \return The past-the-end iterator. */ @@ -1124,7 +1127,8 @@ public: private: /*! Compute the overlap with a given arc, which is supposed to have the same * supporting conic curve as this arc. - * \param arc The given arc. + * \param xcv1 The first arc. + * \param xcv2 The second arc. * \param overlap Output: The overlapping arc (if any). * \return Whether we found an overlap. */ @@ -1479,7 +1483,7 @@ public: const Traits& m_traits; /*! Constructor - * \param traits the traits (in case it has state) + * \param traits The traits (in case it has state) */ Are_mergeable_2(const Traits& traits) : m_traits(traits) {} @@ -1487,10 +1491,11 @@ public: public: /*! Check whether it is possible to merge two given x-monotone curves. - * \param cv1 The first curve. - * \param cv2 The second curve. - * \return (true) if the two curves are mergeable - if they are supported - * by the same line and share a common endpoint; (false) otherwise. + * \param xcv1 The first arc. + * \param xcv2 The second arc. + * \return `true` if the two curves are mergeable; that is, they are + * supported by the same curve and share a common endpoint); + * `false` otherwise. */ bool operator()(const X_monotone_curve_2& xcv1, const X_monotone_curve_2& xcv2) const @@ -1498,9 +1503,10 @@ public: private: /*! Check whether it is possible to merge the arc with the given arc. - * \param arc The query arc. - * \return (true) if it is possible to merge the two arcs; - * (false) otherwise. + * \param xcv1 The first arc. + * \param xcv2 The second arc. + * \return `true` if it is possible to merge the two arcs; + * `false` otherwise. */ bool can_merge_with(const X_monotone_curve_2& xcv1, const X_monotone_curve_2& xcv2) const { @@ -1530,7 +1536,7 @@ public: const Traits& m_traits; /*! Constructor - * \param traits the traits (in case it has state) + * \param traits The traits (in case it has state) */ Merge_2(const Traits& traits) : m_traits(traits) {} @@ -1538,10 +1544,10 @@ public: public: /*! Merge two given x-monotone curves into a single curve (segment). - * \param cv1 The first curve. - * \param cv2 The second curve. - * \param c Output: The merged curve. - * \pre The two curves are mergeable. + * \param xcv1 The first arc. + * \param xcv2 The second arc. + * \param xcv The merged arc. + * \pre The two arcs are mergeable. */ void operator()(const X_monotone_curve_2& xcv1, const X_monotone_curve_2& xcv2, @@ -1554,7 +1560,8 @@ public: private: /*! Merge the current arc with the given arc. - * \param arc The arc to merge with. + * \param xcv1 The first arc to merge with. + * \param xcv2 The second arc to merge with. * \pre The two arcs are mergeable. */ void merge(X_monotone_curve_2& xcv1, const X_monotone_curve_2& xcv2) const { @@ -1582,11 +1589,13 @@ public: //@} - /// \name Functor definitions for the landmarks point-location strategy. + /*! \name Auxiliary Functor definitions, used gor, e.g., the landmarks + * point-location strategy and the drawing function. + */ //@{ - using Approximate_number_type = double; - using Approximate_kernel = CGAL::Cartesian; - using Approximate_point_2 = Approximate_kernel::Point_2; + typedef double Approximate_number_type; + typedef CGAL::Cartesian Approximate_kernel; + typedef Approximate_kernel::Point_2 Approximate_point_2; class Approximate_curve_length_2 { protected: @@ -1739,7 +1748,7 @@ public: Approximate_point_2 operator()(const Point_2& p) const { return std::make_pair(operator()(p, 0), operator()(p, 1)); } - /*! Obtain an approximation of an x-monotone curve. + /*! Obtain an approximation of an \f$x\f$-monotone curve. */ template OutputIterator operator()(OutputIterator oi, double error, @@ -1853,7 +1862,7 @@ public: * * @param error the error bound of the generated approximation. This is * the Hausdorff distance between the arc and the polyline, - * which approximates the src. + * which approximates the arc. */ template OutputIterator approximate_ellipse(OutputIterator oi, double error, @@ -2125,16 +2134,16 @@ public: const Traits& m_traits; /*! Constructor - * \param traits the traits. + * \param traits The traits. */ Construct_x_monotone_curve_2(const Traits& traits) : m_traits(traits) {} friend class Arr_conic_traits_2; public: - /*! Construct an x-monotone arc from a conic arc. - * \param cv The given (Curve_2) curve. - * \pre cv is x-monotone. + /*! Construct an \f$x\f$-monotone arc from a conic arc. + * \param cv The given curve. + * \pre cv is \f$x\f$-monotone. */ X_monotone_curve_2 operator()(const Curve_2& cv) const { CGAL_precondition(cv.is_valid() && is_x_monotone(cv)); @@ -2143,8 +2152,8 @@ public: return xcv; } - /*! Construct an x-monotone arc from a conic arc. - * \param xcv The given (Curve_2) curve. + /*! Construct an \f$x\f$-monotone arc from a conic arc. + * \param xcv The given curve. * \param id The ID of the base curve. */ X_monotone_curve_2 operator()(const Curve_2& cv, const Conic_id& id) const { @@ -2154,11 +2163,11 @@ public: return xcv; } - /*! Construct an x-monotone sub-arc from a conic arc. + /*! Construct an \f$x\f$-monotone sub-arc from a conic arc. * \param cv The given (base) arc. * \param source The source point. * \param target The target point. - * \param id The ID of the base arc. + * \param id The id of the base arc. */ X_monotone_curve_2 operator()(const Curve_2& cv, const Point_2& source, const Point_2& target, @@ -2173,11 +2182,11 @@ public: return xcv; } - /*! Return an x-monotone curve connecting the two given endpoints. - * \param p The first point. - * \param q The second point. - * \pre p and q must not be the same. - * \return A segment connecting p and q. + /*! Return an \f$x\f$-monotone curve connecting the two given endpoints. + * \param source The first point. + * \param target The second point. + * \pre `source` and `target` must not be the same. + * \return A segment connecting `source` and `target`. */ X_monotone_curve_2 operator()(const Point_2& source, const Point_2& target) const @@ -2208,7 +2217,7 @@ public: /*! Construct a special segment of a given line connecting to given * endpoints. - * \param a, b, c The coefficients of the supporting line (ax + by + c = 0). + * \param a, b, c The coefficients of the supporting line (`ax + by + c = 0`). * \param source The source point. * \param target The target point. */ @@ -2246,7 +2255,7 @@ public: } private: - /*! Determine whether the arc is x-monotone. + /*! Determine whether the arc is \f$x\f$-monotone. */ bool is_x_monotone(const Curve_2& cv) const { // Collect vertical tangency points. @@ -2255,7 +2264,7 @@ public: return (res == 0); } - /*! Determine whether the arc is y-monotone. + /*! Determine whether the arc is \f$y\f$-monotone. */ bool is_y_monotone(const Curve_2& cv) const { // Collect horizontal tangency points. @@ -2279,7 +2288,7 @@ public: const Traits& m_traits; /*! Constructor - * \param traits the traits. + * \param traits The traits. */ Construct_curve_2(const Traits& traits) : m_traits(traits) {} @@ -2291,8 +2300,8 @@ public: Curve_2 operator()() const { return Curve_2(); } /*! Construct a conic arc which is the full conic: - * C: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0 - * \pre The conic C must be an ellipse (so 4rs - t^2 > 0). + * `C: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0` + * \pre The conic C must be an ellipse (so `4rs - t^2 > 0`). */ Curve_2 operator()(const Rational& r, const Rational& s, const Rational& t, const Rational& u, const Rational& v, const Rational& w) @@ -2315,7 +2324,7 @@ public: } /*! Construct a conic arc that lies on the conic: - * C: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0 + * `C: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0` * \param orient The orientation of the arc (clockwise or counterclockwise). * \param source The source point. * \param target The target point. @@ -2512,11 +2521,11 @@ public: } /*! Construct a conic arc that lies on a conic given by its coefficients: - * C: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0 + * `C: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0` * The source and the target are specified by the intersection of the * conic with: - * C_1: r_1*x^2 + s_1*y^2 + t_1*xy + u_1*x + v_1*y + w_1 = 0 - * C_2: r_2*x^2 + s_2*y^2 + t_2*xy + u_2*x + v_2*y + w_2 = 0 + * `C_1: r_1*x^2 + s_1*y^2 + t_1*xy + u_1*x + v_1*y + w_1 = 0` + * `C_2: r_2*x^2 + s_2*y^2 + t_2*xy + u_2*x + v_2*y + w_2 = 0` * The user must also specify the source and the target with approximated * coordinates. The actual intersection points that best fits the source * (or the target) will be selected. @@ -2672,11 +2681,11 @@ public: return arc; } - /*! Return a curve connecting the two given endpoints. + /*! Return a segment connecting the two given endpoints. * \param source The source point. * \param target The target point. - * \pre p and q must not be the same. - * \return A segment connecting p and q. + * \pre `source` and `target` must not be the same. + * \return A segment connecting `source` and `target`. */ Curve_2 operator()(const Point_2& source, const Point_2& target) const { const auto alg_kernel = m_traits.m_alg_kernel; @@ -2783,7 +2792,7 @@ public: } /*! Construct a conic arc that lies on a given circle: - * C: (x - x0)^2 + (y - y0)^2 = R^2 + * `C: (x - x0)^2 + (y - y0)^2 = R^2` * \param orient The orientation of the circle. * \param source The source point. * \param target The target point. @@ -2995,7 +3004,7 @@ public: const Traits& m_traits; /*! Constructor - * \param traits the traits. + * \param traits The traits. */ Construct_bbox_2(const Traits& traits) : m_traits(traits) {} @@ -3097,7 +3106,8 @@ public: /*! Set the properties of a conic arc (for the usage of the constructors). * \param rat_coeffs A vector of size 6, storing the rational coefficients - * of x^2, y^2, xy, x, y and the free coefficient resp. + * of \f$x^2\f$, \f$y^2\f$, \f$x \cdot y\f$, \f$x\f$, \f$y\f$ + * and the free coefficient resp. */ void set(Curve_2& cv, const Rational* rat_coeffs) const { cv.set_flag(Curve_2::IS_VALID); @@ -3203,7 +3213,8 @@ public: /*! Set the properties of a conic arc that is really a full curve * (that is, an ellipse). * \param rat_coeffs A vector of size 6, storing the rational coefficients - * of x^2, y^2, xy, x, y and the free coefficient resp. + * of \f$x^2\f$, \f$y^2\f$, \f$x \cdot y\f$, \f$x\f$, \f$y\f$ + * and the free coefficient resp. * \param comp_orient Should we compute the orientation of the given curve. */ void set_full(Curve_2& cv, const Rational* rat_coeffs, @@ -3278,8 +3289,8 @@ public: /*! Check whether the given point is between the source and the target. * The point is assumed to be on the conic's boundary. * \param p The query point. - * \return true if the point is between the two endpoints, - * (false) if it is not. + * \return `true` if the point is between the two endpoints; + * `false` if it is not. */ bool is_between_endpoints(const Curve_2& cv, const Point_2& p) const { CGAL_precondition(! cv.is_full_conic()); @@ -3294,8 +3305,8 @@ public: * target (but not any of them). * The point is assumed to be on the conic's boundary. * \param p The query point. - * \return true if the point is strictly between the two endpoints, - * (false) if it is not. + * \return `true` if the point is strictly between the two endpoints; + * `false` if it is not. */ bool is_strictly_between_endpoints(const Curve_2& cv, const Point_2& p) const { @@ -3529,10 +3540,10 @@ public: return 2; } - /*! Find all points on the arc with a given x-coordinate. - * \param p A placeholder for the x-coordinate. - * \param ps The point on the arc at x(p). - * \pre The vector ps should be allocated at the size of 2. + /*! Find all points on the arc with a given \f$x\f$-coordinate. + * \param p A placeholder for the \f$x\f$-coordinate. + * \param ps The point on the arc at `x(p)`. + * \pre The vector `ps` should be allocated at the size of 2. * \return The number of points found. */ int points_at_x(const Curve_2& cv, const Point_2& p, Point_2* ps) const { @@ -3553,10 +3564,10 @@ public: return m; } - /*! Find all points on the arc with a given y-coordinate. - * \param p A placeholder for the y-coordinate. - * \param ps The point on the arc at x(p). - * \pre The vector ps should be allocated at the size of 2. + /*! Find all points on the arc with a given \f$y\f$-coordinate. + * \param p A placeholder for the \f$y\f$-coordinate. + * \param ps The point on the arc at `x(p)`. + * \pre The vector `ps` should be allocated at the size of 2. * \return The number of points found. */ int points_at_y(const Curve_2& cv, const Point_2& p, Point_2* ps) const { @@ -3677,8 +3688,9 @@ public: } /*! Check whether the two arcs have the same supporting conic. - * \param arc The compared arc. - * \return (true) if the two supporting conics are the same. + * \param xcv1 The first comparedb arc. + * \param xcv2 The secind compared arc. + * \return `true` if the two supporting conics are the same. */ bool has_same_supporting_conic(const X_monotone_curve_2& xcv1, const X_monotone_curve_2& xcv2) const { @@ -3973,9 +3985,9 @@ public: auto r = CGAL::to_double(xcv.r()); auto s = CGAL::to_double(xcv.s()); auto t = CGAL::to_double(xcv.t()); - auto u = CGAL::to_double(xcv.u()); - auto v = CGAL::to_double(xcv.v()); - auto w = CGAL::to_double(xcv.w()); + // auto u = CGAL::to_double(xcv.u()); + // auto v = CGAL::to_double(xcv.v()); + // auto w = CGAL::to_double(xcv.w()); // std::cout << r << "," << s << "," << t << "," // << u << "," << v << "," << w << std::endl; @@ -4143,12 +4155,8 @@ public: // Compute the parameters ts and tt such that // source == (x(ts),y(ts)), and // target == (x(tt),y(tt)) - auto xds = xs - cx; - auto yds = ys - cy; ts = std::atan2(a*ys_t, b*xs_t); if (ts < 0) ts += 2*M_PI; - auto xdt = xt - cx; - auto ydt = yt - cy; tt = std::atan2(a*yt_t, b*xt_t); if (tt < 0) tt += 2*M_PI; auto orient(xcv.orientation()); diff --git a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h index a5cae7516cc..ed72186a417 100644 --- a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h +++ b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h @@ -1,3 +1,19 @@ +// Copyright (c) 2012 +// Utrecht University (The Netherlands), +// ETH Zurich (Switzerland), +// INRIA Sophia-Antipolis (France), +// Max-Planck-Institute Saarbruecken (Germany), +// and Tel-Aviv University (Israel). All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s): Efi Fogel + #ifndef CGAL_DRAW_ARRANGEMENT_2_H #define CGAL_DRAW_ARRANGEMENT_2_H @@ -6,6 +22,9 @@ #include #include + +#ifdef CGAL_USE_BASIC_VIEWER + #include #include #include @@ -41,6 +60,7 @@ public: virtual void resizeGL(int width, int height) { m_width = width; m_height = height; + // std::cout << width << "," << height << std::endl; } //! @@ -145,7 +165,6 @@ protected: //! void add_ccb(Ccb_halfedge_const_circulator circ) { - auto face = circ->face(); auto curr = circ; do { auto new_face = curr->twin()->face(); @@ -300,10 +319,9 @@ public: //! template -void draw(const CGAL::Arrangement_2& arr, +void draw(const Arrangement_2& arr, const char* title = "2D Arrangement Basic Viewer") { typedef GeometryTraits_2 Gt; - typedef CGAL::Arrangement_2 Arr; CGAL::Qt::init_ogl_context(4,3); @@ -319,3 +337,4 @@ void draw(const CGAL::Arrangement_2& arr, } #endif +#endif From f9c4e29d9ff97d4621c31391d9f3af0c06db8ea1 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Mon, 27 Jun 2022 18:22:04 +0300 Subject: [PATCH 049/105] Added documentation for draw_arrangement_2 and cleaned up --- .../CGAL/Arr_conic_traits_2.h | 178 ++++++++++++------ .../CGAL/Arrangement_on_surface_2.h | 4 + .../Concepts/ArrTraits--Intersect_2.h | 4 +- .../PackageDescription.txt | 11 ++ .../doc/Arrangement_on_surface_2/examples.txt | 5 + 5 files changed, 145 insertions(+), 57 deletions(-) diff --git a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arr_conic_traits_2.h index 0b610d566be..0ae33377ba6 100644 --- a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arr_conic_traits_2.h @@ -4,22 +4,22 @@ namespace CGAL { * * The class `Arr_conic_traits_2` is a model of the `ArrangementTraits_2` * concept and can be used to construct and maintain arrangements of bounded - * segments of algebraic curves of degree \f$ 2\f$ at most, also known as + * segments of algebraic curves of degree \f$2\f$ at most, also known as * conic curves. * - * A general conic curve \f$ C\f$ is the locus of all points \f$ (x,y)\f$ - * satisfying the equation: \f$ r x^2 + s y^2 + t x y + u x + v y + w = 0\f$, + * A general conic curve \f$C\f$ is the locus of all points \f$(x,y)\f$ + * satisfying the equation: \f$r x^2 + s y^2 + t x y + u x + v y + w = 0\f$, * where: * *
    - *
  • If \f$ 4 r s - t^2 > 0\f$, \f$ C\f$ is an ellipse. A special case occurs - * when \f$ r = s\f$ and \f$ t = 0\f$, when \f$ C\f$ becomes a circle. + *
  • If \f$4 r s - t^2 > 0\f$, \f$ C\f$ is an ellipse. A special case occurs + * when \f$r = s\f$ and \f$ t = 0\f$, when \f$ C\f$ becomes a circle. * - *
  • If \f$ 4 r s - t^2 < 0\f$, \f$ C\f$ is a hyperbola. + *
  • If \f$4 r s - t^2 < 0\f$, \f$ C\f$ is a hyperbola. * - *
  • If \f$ 4 r s - t^2 = 0\f$, \f$ C\f$ is a parabola. A degenerate case - * occurs when \f$ r = s = t = 0\f$, when \f$ C\f$ is a line. + *
  • If \f$4 r s - t^2 = 0\f$, \f$ C\f$ is a parabola. A degenerate case + * occurs when \f$r = s = t = 0\f$, when \f$ C\f$ is a line. * *
* @@ -50,13 +50,13 @@ namespace CGAL { * only circular arcs and line segments, it is recommended using the * `Arr_circle_segment_2` class to achieve better running times. * - * In our representation, all conic coefficients (namely \f$ r, s, t, u, v, - * w\f$) must be rational numbers. This guarantees that the coordinates of all + * In our representation, all conic coefficients (namely \f$r, s, t, u, v, w\f$) + * must be rational numbers. This guarantees that the coordinates of all * arrangement vertices (in particular, those representing intersection points) - * are algebraic numbers of degree \f$ 4\f$ (a real number \f$ \alpha\f$ is an - * algebraic number of degree \f$ d\f$ if there exist a polynomial \f$ p\f$ with - * integer coefficient of degree \f$ d\f$ such that \f$ p(\alpha) = - * 0\f$). We therefore require separate representations of the curve + * are algebraic numbers of degree \f$4\f$ (a real number \f$\alpha\f$ is an + * algebraic number of degree \f$d\f$ if there exist a polynomial \f$ p\f$ with + * integer coefficient of degree \f$d\f$ such that \f$p(\alpha) = 0\f$). + * We therefore require separate representations of the curve * coefficients and the point coordinates. The `NtTraits` should be instantiated * with a class that defines nested `Integer`, `Rational`, and `Algebraic` number * types and supports various operations on them, yielding certified computation @@ -72,7 +72,7 @@ namespace CGAL { * simple algebraic numbers. * * The traits class inherits its point type from `AlgKernel::Point_2`, - * and defines a curve and \f$ x\f$-monotone curve types, as detailed below. + * and defines a curve and \f$x\f$-monotone curve types, as detailed below. * * While the `Arr_conic_traits_2` models the concept * `ArrangementDirectionalXMonotoneTraits_2`, the implementation of @@ -129,20 +129,19 @@ public: * violation does not cause the program to abort. Instead, the constructed * arc is invalid (a defaultly constructed arc is also invalid). It is * however recommended to check that a constructed arc is valid before - * inserting it to an arrangement, as this operation will cause the - * program to abort. + * inserting it to an arrangement. */ bool is_valid() const; - /*! determines whether the arc is \f$ x\f$-monotone, namely each vertical + /*! determines whether the arc is \f$x\f$-monotone, namely each vertical * line intersects it at most once. A vertical line segment is also - * considered (weakly) \f$ x\f$-monotone. + * considered (weakly) \f$x\f$-monotone. */ bool is_x_monotone() const; - /*! determines whether the arc is \f$ y\f$-monotone, namely each horizontal + /*! determines whether the arc is \f$y\f$-monotone, namely each horizontal * line intersects it at most once. A horizontal line segment is also - * considered (weakly) \f$ x\f$-monotone. + * considered (weakly) \f$x\f$-monotone. */ bool is_y_monotone() const; @@ -160,23 +159,23 @@ public: */ /// @{ - /*! returns the coefficient of \f$ x^2\f$. + /*! returns the coefficient of \f$x^2\f$. */ const typename NtTraits::Integer& r() const; - /*! returns the coefficient of \f$ t^2\f$. + /*! returns the coefficient of \f$t^2\f$. */ const typename NtTraits::Integer& s() const; - /*! returns the coefficient of \f$ x y\f$. + /*! returns the coefficient of \f$x y\f$. */ const typename NtTraits::Integer& t() const; - /*! returns the coefficient of \f$ x\f$. + /*! returns the coefficient of \f$x\f$. */ const typename NtTraits::Integer& u() const; - /*! returns the coefficient of \f$ y\f$. + /*! returns the coefficient of \f$y\f$. */ const typename NtTraits::Integer& v() const; @@ -217,15 +216,16 @@ public: }; /* end Arr_conic_traits_2::Curve_2 */ - /*! The `X_monotone_curve_2` class nested within the conic-arc traits is + /*! \class X_monotone_curve_2 + * The `X_monotone_curve_2` class nested within the conic-arc traits is * used to represent \f$x\f$-monotone conic arcs. It inherits from the * `Curve_2` type, therefore supports the access methods and the operations * listed above. * - * For efficiency reasons, we recommend users not to construct \f$ - * x\f$-monotone conic arc directly, but rather use the `Make_x_monotone_2` + * For efficiency reasons, we recommend users not to construct + * \f$x\f$-monotone conic arc directly, but rather use the `Make_x_monotone_2` * functor supplied by the conic-arc traits class to convert conic curves to - * \f$ x\f$-monotone curves. + * \f$x\f$-monotone curves. */ class X_monotone_curve_2 { public: @@ -281,10 +281,11 @@ public: /// @} }; - /*! \class + /*! \class Construct_curve_2 * A functor that constructs a conic arc. */ class Construct_curve_2 { + public: /*! constructs an arc corresponding to the line segment `seg`. */ Curve_2 operator()(const typename RatKernel::Segment_2& seg) const; @@ -318,18 +319,18 @@ public: const typename RatKernel::Point_2& p3) const; /*! constructs a conic arc that corresponds to the full conic curve - * \f$ r x^2 + s y^2 + t x y + u x + v y + w = 0\f$. + * \f$r x^2 + s y^2 + t x y + u x + v y + w = 0\f$. * * \pre As a conic arc must be bounded, the given curve must be an ellipse, - * that is \f$ 4 r s - t^2 > 0\f$. + * that is \f$4 r s - t^2 > 0\f$. */ Curve_2 operator()(const Rational& r, const Rational& s, const Rational& t, const Rational& u, const Rational& v, const Rational& w) const; /*! constructs a conic arc supported by the conic curve - * \f$ r x^2 + s y^2 + t x y + u x + v y + w = 0\f$, going in the given - * orientation `o` from the source point `ps` to its target point `pt`. * * + * \f$r x^2 + s y^2 + t x y + u x + v y + w = 0\f$, going in the given + * orientation `o` from the source point `ps` to its target point `pt`. * * \pre `ps` and `pt` both satisfy the equation of the supporting conic * curve and define a bounded segment of this curve (e.g. in case of a @@ -361,13 +362,13 @@ public: const typename RatKernel::Point_2& p5) const; /*! constructs a conic arc supported by the conic curve - * \f$ r x^2 + s y^2 + t x y + u x + v y + w = 0\f$, going in the given + * \f$r x^2 + s y^2 + t x y + u x + v y + w = 0\f$, going in the given * orientation `o` from its source point to its target Point. In this case * only some approximations of the endpoints (`app_ps` and `app_pt`, * respectively) is available, and their exact locations are given * implicitly, specified by the intersections of the supporting conic curve - * with \f$ r_1 x^2 + s_1 y^2 + t_1 x y + u_1 x + v_1 y + w_1 = 0\f$ and \f$ - * r_2 x^2 + s_2 y^2 + t_2 x y + u_2 x + v_2 y + w_2 = 0\f$, respectively. + * with \f$r_1 x^2 + s_1 y^2 + t_1 x y + u_1 x + v_1 y + w_1 = 0\f$ and + * \f$r_2 x^2 + s_2 y^2 + t_2 x y + u_2 x + v_2 y + w_2 = 0\f$, respectively. * * \pre The two auxiliary curves specifying the endpoints really intersect * with the supporting conic curve, such that the arc endpoints define a @@ -391,50 +392,114 @@ public: const Rational& v2, const Rational& w2) const; }; - /*! \class - * A functor that constructs an \f$X\f$-monotone conic arc. + /*! \class Construct_x_monotone_curve_2 + * A functor that constructs an \f$x\f$-monotone conic arc. */ class Construct_x_monotone_curve_2 { - /*! converts the given arc to an \f$ x\f$-monotone arc. - * \pre `arc` is \f$ x\f$-monotone. + public: + /*! converts a given arc to an \f$x\f$-monotone arc. + * \param cv The input arc. + * \pre `cv` is \f$x\f$-monotone. */ - X_monotone_curve_2 operator()(const Curve_2& arc) const; + X_monotone_curve_2 operator()(const Curve_2& cv) const; - /*! Constructs an x-monotone curve connecting the two given endpoints. - * \param p The first point. - * \param q The second point. - * \pre p and q must not be the same. - * \return A segment connecting p and q. + /*! Constructs an \f$x\f$-monotone curve connecting the two given endpoints. + * \param source The first point. + * \param target The second point. + * \pre `source` and `target` must not be the same. + * \return A segment connecting `source` and `target`. */ X_monotone_curve_2 operator()(const Point_2& source, const Point_2& target) const; /*! Constructs a special segment of a given line connecting to given * endpoints. - * \param a, b, c The coefficients of the supporting line (ax + by + c = 0). + * \param a, b, c The coefficients of the supporting line (\f$ax + by + c = 0\f$). * \param source The source point. * \param target The target point. + * \pre `source` and `target` must not be the same. + * \return A segment connecting `source` and `target`. */ X_monotone_curve_2 operator()(const Algebraic& a, const Algebraic& b, const Algebraic& c, const Point_2& source, const Point_2& target) const; }; - /*! \class + /*! \class Construct_bbox_2 * A functor that constructs a bounding box of a conic arc. */ class Construct_bbox_2 { - /*! return a bounding box of the arc `a`. + public: + /*! Obtain a bounding box for a conic arc. + * \param cv The conic arc. + * \return The bounding box. */ - Bbox_2 operator()() const; + Bbox_2 operator()(const Curve_2& cv) const { return bbox(cv); } + + /*! Obtain a bounding box for an \f$x\f$-monotone conic arc. + * \param xcv The \f$x\f$-monotone conic arc. + * \return The bounding box. + */ + Bbox_2 operator()(const X_monotone_curve_2& xcv) const { return bbox(xcv); } }; - /*! \class + /*! \name Auxiliary Functor definitions, used gor, e.g., the landmarks + * point-location strategy and the drawing function. + */ + //@{ + typedef double Approximate_number_type; + typedef CGAL::Cartesian Approximate_kernel; + typedef Approximate_kernel::Point_2 Approximate_point_2; + + /*! \class Approximate_2 + * A functor that approximates a point and an \f$x\f$-monotone curve. + */ + class Approximate_2 { + public: + /*! Obtain an approximation of a point coordinate. + * \param p The exact point. + * \param i The coordinate index (either 0 or 1). + * \pre `i` is either 0 or 1. + * \return An approximation of p's \f$x\f$-coordinate (if `i` == 0), or an + * approximation of p's \f$y\f$-coordinate (if `i` == 1). + */ + Approximate_number_type operator()(const Point_2& p, int i) const; + + /*! Obtain an approximation of a point. + * \param p The exact point. + */ + Approximate_point_2 operator()(const Point_2& p) const; + + /*! Obtain a polyline that approximates an \f$x\f$-monotone curve. The + * polyline is defined by a range of approximate points beginning at + * `oi`. The type `OutputIterator` must dereference the type + * `Approximate_point_2`. The first and last points in the range are always + * the endpoints of the given arc `xcv`. The operator returns a + * past-the-end iterator of the destination range. + * \param oi An output iterator for the resulting polyline. + * \param error The error bound of the polyline approximation. This is + * the Hausdorff distance between the arc and the polyline + * that approximates the arc. + * \param xcv The exact \f$x\f$-monotone arc. + * \param l2r A Boolean flag that indicates whether the arc direction is + * left to right. + * \return The past-the-end iterator of the output iterator. + */ + template + OutputIterator operator()(OutputIterator oi, double error, + const X_monotone_curve_2& xcv, + bool l2r = true) const; + }; + + /*! \class Trim_2 * A functor that trims a conic arc. */ class Trim_2 { public: - /*! Trims the given x-monotone curve to an from source to target. - * \ pre `source` and `target` lies on the curve + /*! Trims the given \f$x\f$-monotone arc to new endpoints. + * \param xcv The \f$x\f$-monotone arc + * \param source The new source point. + * \param target The new target point. + * \pre `source` and `target` lies on the arc. */ X_monotone_curve_2 operator()(const X_monotone_curve_2& xcv, const Point_2& source, @@ -457,6 +522,9 @@ public: /*! Obtain a `Trim_2` functor. */ Trim_2 trim_2_object() const; + /*! Obtain an `Approximate_2` functor. */ + Trim_2 approximate_2_object() const; + /// @} }; /* end Arr_conic_traits_2 */ diff --git a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arrangement_on_surface_2.h b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arrangement_on_surface_2.h index d58316e3e70..07ac2dff536 100644 --- a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arrangement_on_surface_2.h +++ b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arrangement_on_surface_2.h @@ -52,6 +52,10 @@ namespace CGAL { * \sa `PkgArrangementOnSurface2Read` * \sa `PkgArrangementOnSurface2Write` + * + * Drawing function + * + * \sa `PkgArrangementOnSurface2Draw` */ template class Arrangement_on_surface_2 { diff --git a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/ArrTraits--Intersect_2.h b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/ArrTraits--Intersect_2.h index 036e21226bc..22c343f21af 100644 --- a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/ArrTraits--Intersect_2.h +++ b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/ArrTraits--Intersect_2.h @@ -37,8 +37,8 @@ public: */ template OutputIterator operator()(ArrTraits::X_monotone_curve_2 xc1, - ArrTraits::X_monotone_curve_2 xc2, - OutputIterator& oi); + ArrTraits::X_monotone_curve_2 xc2, + OutputIterator& oi); /// @} diff --git a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/PackageDescription.txt b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/PackageDescription.txt index 8d6daf70bd6..04ce3c47c28 100644 --- a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/PackageDescription.txt +++ b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/PackageDescription.txt @@ -46,6 +46,14 @@ namespace ArrTraits {} /// \defgroup PkgArrangementOnSurface2Funcs Free Functions /// \ingroup PkgArrangementOnSurface2Ref +/*! + \code + #include + \endcode +*/ +/// \defgroup PkgArrangementOnSurface2Draw Drawing +/// \ingroup PkgArrangementOnSurface2Ref + /// \defgroup PkgArrangementOnSurface2Insert CGAL::insert() /// \ingroup PkgArrangementOnSurface2Funcs @@ -252,4 +260,7 @@ implemented as peripheral classes or as free (global) functions. - \link PkgArrangementOnSurface2op_left_shift `CGAL::operator<<` \endlink - \link PkgArrangementOnSurface2op_right_shift `CGAL::operator<<` \endlink +\cgalCRPSection{Draw an `Arrangemen_2` object} +- \link PkgArrangementOnSurface2Draw CGAL::draw<>() \endlink + */ diff --git a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/examples.txt b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/examples.txt index 0cac1f68db1..5e8b1f376be 100644 --- a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/examples.txt +++ b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/examples.txt @@ -43,4 +43,9 @@ \example Arrangement_on_surface_2/unbounded_non_intersecting.cpp \example Arrangement_on_surface_2/unbounded_rational_functions.cpp \example Arrangement_on_surface_2/vertical_ray_shooting.cpp +\example Arrangement_on_surface_2/draw_arr +\example Arrangement_on_surface_2/linear_conics.cpp +\example Arrangement_on_surface_2/parabolas.cpp +\example Arrangement_on_surface_2/ellipses.cpp +\example Arrangement_on_surface_2/hyperbolas.cpp */ From 9656187609ff01ba19125af49b8560eb1cc324cb Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Mon, 27 Jun 2022 18:29:06 +0300 Subject: [PATCH 050/105] Introduced a function that draws an arrangement --- .../CGAL/draw_arrangement_2.h | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/draw_arrangement_2.h diff --git a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/draw_arrangement_2.h b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/draw_arrangement_2.h new file mode 100644 index 00000000000..f415f5c9e7e --- /dev/null +++ b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/draw_arrangement_2.h @@ -0,0 +1,55 @@ +// Copyright (c) 2012 +// Utrecht University (The Netherlands), +// ETH Zurich (Switzerland), +// INRIA Sophia-Antipolis (France), +// Max-Planck-Institute Saarbruecken (Germany), +// and Tel-Aviv University (Israel). All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Efi Fogel + +#ifndef CGAL_DRAW_ARRANGEMENT_2_H +#define CGAL_DRAW_ARRANGEMENT_2_H + +#include + +#ifdef DOXYGEN_RUNNING + +namespace CGAL { + +/*! \ingroup PkgArrangementOnSurface2Draw + * + * opens a new window and draws `arr`, an instance of the `CGAL::Arrangement_2` + * class template. A call to this function is blocking; that is, the program + * continues only after the user closes the window. This function requires + * `CGAL_Qt5`, and is only available if the macro `CGAL_USE_BASIC_VIEWER` is + * defined. Linking with the cmake target `CGAL::CGAL_Basic_viewer` will link + * with `CGAL_Qt5` and add the definition `CGAL_USE_BASIC_VIEWER`. + * + * \tparam GeometryTraits_2 a geometry traits type, a model of a 2D arrangement + * traits concept. At this point it must be an instance of either + * `CGAL::Arr_segment_traits_2` or `CGAL::Arr_conic_traits_2`. + * + * \tparam Dcel the \dcel type, a model of the `ArrangementDcel` concept. + * + * \param arr the 2D arrangement to draw. + * \param title the window title. + * + * \sa `ArrangementDcel` + * \sa `ArrangementTraits_2` + */ +template +void draw(const Arrangement_2& arr, + const char* title = "2D Arrangement Basic Viewer"); + +} /* namespace CGAL */ + +#endif + +#endif From 88d747093f3ad13cf56bdabaf9ccfc26609adff3 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Tue, 28 Jun 2022 10:09:45 +0300 Subject: [PATCH 051/105] 1st revision; an example of the window generated by draw_arr.cpp --- .../Arrangement_on_surface_2/fig/draw_arr.png | Bin 0 -> 16301 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Arrangement_on_surface_2/doc/Arrangement_on_surface_2/fig/draw_arr.png diff --git a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/fig/draw_arr.png b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/fig/draw_arr.png new file mode 100644 index 0000000000000000000000000000000000000000..ea7cf9f9809e84c5cf935999e51c448ec6d479fe GIT binary patch literal 16301 zcmeIZc{r5s`#(IPC|l|sm25@c5wbIky=31hYf4#%Fk={ol%=wjH9Il(Az?5Kl~4&| z9otaZW(+f7nC#Ep=kpxL^ZVm_9N#~le}9f+j=ASvuKT*q<#oQ!^Sr#UG&kfvb@3Dk z1mZTjZD0)o9b*8WUmPcZGs1VZxPULVU_B#S4&X0>!{a&d`vUCd9hgnPBN)Ox=po3{ zKLGkrCip?n!-xLCUI8#VYo`_nBnmPz(6tTCTO)&$G_lK-U9r_2~-mX~*) z>*#q{eLP+%=;NF5(utHco>?U`_7;0C%Lj_#k8-TGcA_T#`!9>$9X4G9{%6-Gjr@a% zlY{h>?3tNdjlS%LLdClBlrR0?)#o-Lo=XMHh>qp(t38xK%`qi2o3d-%yaGy^cPy`_ zWpe2Qb8$8uvBfx!jKZu&MkI{NxVkK>_-2PwW4pdBHyD?t8edJ*WeR{mjrVe_@vb&1 zx%OIFV`TChpDmm<+WMw+rku6AXt{?%r4PEyxb^B+F5Dmp^y6M!`i(Qd)87Q%R}teI z!v`y@pRtB52Hm}&U@MjRjCK_SB7aWzsj9TEzLsx(EvxU}!a-?e%P&&drWMY$CrCFz zAi}et)+$?YrL%0cEjZsAW1r=%@R*~2u}3@F;awdrzqSNtSj!d;>4?d7{W_q!LpecDD&!wZ zjs3CCrbTNhyA1!CC>_x7X&unoI4#t4@3#JAX^)9AL=#+FsD;xfLT77#zCN}XJXs4( zN;325xAJX7j=gq#cki`AcH+0i_qPn0WM+z1Re$Gn4PW6j3rO^(=}3CuQ0$=m*%t=A z$0e_pDT~`gHMnE!1*{dMAAYS-^@-?ul^BxPt}HKKDd_*Fm1_*;%}F*a^RBY41jKhj`{l!&DQs}zN)s+q zM$jId@p3x^Br-;YUywt(FY6S_W-3`?R%`~r=Fgf^ZK;pLofOdP2Dj*cCZFY)muK`n zTxznbHX4i^XjP!X$9$T$%_Pzk&cxLo3~d>gb6HG3MRni58{S)HTWOnd`@C^^n&Sde-H);W`mY^x%V_kq{M-M)A|7L}9cvsN{OPU4)(ynP;vmfz%z*PJOiw5rRU zY6>@%cDU})s)>#%PA)!ND3H(Svm5h)8(Cj=|2NIt`<`f>-s~ix%A6@ha3ycYkzC{B zpDZXc{m5$UTjQ{|ulwEt4V9B4E1hrd-7Utstm#l`+XU^c5ci%O<})+Tga)v4R3q`T zVP8l}W@d>ND=!s^6*uq>TRg?Bb2+7%KsrdmzCoR-nC;e`1AzjX%O+zy3B^e1$0V9J^kqw!$7ifPRN6l>J=O3aLs|Ep6 zUy&q|isYiUd>u_IG_31XSs2m|DDxKvdI6|qx2i{(8RkugQ_H0Ao~<~d+uNpIk?N1p z$0X8DCZ$+-ZPG=?;KU>6PW(}1QXrXj{P5vPvSWjBY9n$>io~RbXZVa1P8Q54 zmNg$t3c{x<%f0%>p-5(7r<-(^T&lR8w4H=?7;2O1V3aC*^jq7fH#r}RWsS-94rz@8 z{9v?a@frBCl`Rw}Zj@7-jr6OknvWY+?1S8J9pZ~k-}u_|BFye;bpy{ea&rCKjo2Ae zr+A@|H}5BFzCHAvyX{atmOi)$n<$o6#(5%ov9+Ct<XEyiA1Q?oS9+`0Pir(wLXHs!EO zQduF-;qnl8v{$kW{&8o}s#g8Teg3W|nR;{}V^^&#k;Z;2v!|y_$wjK#5o()K>7mz` znd}u2f!mrtJCc(pRq0x75|`dzs;r=J>Y*1KVXv>46=Ir{WZ~;mHS?!-(N<6YS=hM^_NCy}NsVG-G>O_rb))GDIHV{nsKUO{JUncK~el#hoK0{ zbnb9~7f!6B4b{>2F!r@~YAsyCV)?J1ANm1UX3?8t;yAtu8he-w7qi5kCg9pZ#9Y^}y zysG9a59V!ly9Dr-lKHTwnb+@@I;&J;oSLbqr~?FYtXs~1=TDy-^0i6m!rL?xskdk zRAF5F#zm4wG0|<;Q3(GigI~t6)I*^-UU;@9H>%!95b&F^>g3VS3#AJF)tiOp!&GD_vpN#jrifN;D7y=-A z@zN#2t|E~#J-1UEH^Q3pM#|^l0#)2dbv861sI{@@YT2@%Cu~sG%rtXKc+eRAmf5if z1@CxEQo^-c>>Z*uqm>`Wy;D7z-H?LfvH+E&|PjP2~?%&S~;?D0yN2XWTBKX&Kg-OuKC zJ9~Toe&bdX=V9M1eI8{a1Ffrv?d*J;)S>52?L3mOZrCrkt^}grT$7B^MIoVlrlEB& z_RoW(!B59ocgGPO)oasOFG}k1D%|Oj?=FQ~)hKmf z>Tz6IxwOo5VUEt?P5W*zx;Z1qyYJLb{(tgHArrGiGFFWu|;vL|8?5P zy8h1a%X58OJtl4?=lUF~Y-_#dIQhj^$&n zbm@Ov7A!eoL7Od!aj$Tthxqv-=fdY|OOhQikdhLBFjPq-2>AN>MY!(S*xZCHw>NAJ zGsTlCjIn5wHvBkge28DDI>?I9mw_;2xs~UXx=YfP#uW)esx5by^HLhrb%f;(2PC_FWtneGZ zvO*$IQ+Us3hxtnujYp*yJ1f^}i%nv`rLQbfSa~xOz_pg+)fSqzh4{Td7vyj;*d1Bz zV-p-D#{Rtrjyr(n_Pc%X+4}HeVcaRex7Ec6xuj^3yQ7|Oj)0mBn@U8!n@kaz;m^Au z{2gG-z7g+Bd7ZaaF2og6YmZvXu1Y!z-|u>LDmIbUMsEf)R~s5bhdwP4!d$>!FK0g6 zS`DHGCR0nPQ6Xu<$j}BXbh`GObfzz+=TK|19ErGnpdi zqEK2Fu_d^hB8Rf$6iD>C_gLrX&rn~}%9ktYgUbLBRd1M`i((ib_-{Ts=--2LzH^NB&A~Krmz}RsLuJ!Zm09=&J^VgeK$)nN@zrAsxM%}lZTR7@XH)Ot zxdp+qlgKV~)Z1mZ-+l)p8AqDsDGm{!@3fx?4C~!F#wB4*zx1 zcZ+>c?Jh5b@k(LR**X#=eY~6S<_(lPnv_%#-v>j z<5NrJP&>Z6v%Ix-m)*VA-@0>ic`P#mMGHsZ#JM8Qg78`(B-G3&LvH1&28?sMg~o|f zKE_9uuT3MoCWn89?KK=V`5`o;Hgosj%PvfEDzUvPY>fnX(Iq(}$Ck&@nKDjQ4^q^P zQ(;6B)5pu}T{+QnJ3QFq&1?OMvBirx_wyI)#+Bb6@i&!)BWPm|*hFfQq)2fci5Zi8 z=kACN`%+Csy^qU_&(Q(Jid_2L_l@ELf7AyLsFy>DJw4m~H4d0e99F`+%vyWmu-B>S zxTjAO&iEWYr2KRl+&2$D}oWCn<}pSa{Ix zQ88anY7NdRn0Rj&FNCu$JYZ;(1)68d0#JKDXO`qA%R#|}S( zIQI(w90esNLM=m~@nN4mgz@{4P%z^nbmnoKaOiJ$jP`tXYN^P|*<>chp7r!C`se`$1?zuf7#4MBwpF5geXlH9PZRk^G{0-ug z-@p@5jih?)rEr}dX_W{r>hTFnw zFa`?`p5BTJN=@8RF1R*Ul_a)dV;)&0?!7!9=}EJGbC6?dma+9opg_Xt+w$h_l!KOb zdF9!Hpmu&4*SE$GeOx;)u6-}`@XWEUw;i*w02|3gQ4*9O5R9DbR$)$F&Umitk>f)J z3RaOOozdfEDV5=q%p=s&4%8J6itx(Z{nu^kh+CL|qk99JX*M=e3yL{!uJ?z{+~CT{ zoi-LvOARZ^_joT~`Q5y2ld0>I_;Piw)?=J|jJsh`{tX^6w?k9L(RKyJjU=_##DNGu zTj^P_&Az+g&{1qxolFk(V?XhJ_rqMI0brG3;N?7S?^C*x0 zboEVLf*((9)9#kgzYBl43FS=*k({V#J`x}jdb_Jj|DuQp5g=~Gu~&97JDK*$o_JYO zWUmXD@#!3xo|oi^^?T8=opdy0;ucYC9=Y-Y`E6<*NM_)GZx7f~@$FiBa}9Y}_p-dJ zf@2HJ%V8t4RRxjHuPN)V|1Q>b>7YHv6wJI`S$LBya(;Y~YVW%<+xsw6@}hJZ7pZa3 z5}cpotpTLJd&&8ZHfrzZA@l4eSJS5IAC#l9G#r(d3H`1mCOpHxI^7mvOpln(1!%Px zZhoK*z9^|J+4U+U#Xfy-pwnJm{;uuSTw=9sOH zQdKQkID^@!@$EM>RjK#8oxrWXiZ)HrhQXN%>3S z(!7ncTsL~Zc?@rkd)KNN>ct61-LD2pOj?D+zt0Oa&z1ph-+%qV`M846`+eVur&E%W zDD1?2gVe@*9tLH19mERrMcUarWq6T=xJmz3YpY6I0HlXr8(yk4YbF%~zIeQg)G5{K zukti%^1Vdx?)cioI5mz-e|NC%pt)ncKY;R*7w=Y`tf^O?x32`*p2$?64sCBO+;KKv z&Tq5QZl#?7LT4;zT)Od_%_T1ng=?fBst~eYq*D)2@9v1n;q6q$Jk{S44F8cye0Ep8 z0DzWeKb*dR%OB1BgPN_>(rN!rlU@--&3OJc7eFXUfy<;S`#!8IKqc>fsCpDTt3_zY zPWQi{%6RInU!7X!F`jYF%xi4c&^Fhf%VfOgR#TO=J>E9`Zk^FBy%bXkSf7WrzCOG8 z=%lG}xS^qPJ**zcr_nmfT>3UPBNv58r(2Mp}m>U486)ajjEZa<~b#^SX& z=5B*=;o)b)M+I%`Jx+|dqrJ84&dy)I1gO8VTuMi40v7-3f9pWRwfg7B?|H-$+p3lH za&0?(ef=t1DJ0V^;@;936TJUQirbC?p8SckF|dn*+s!>vt#jL3zSD@*%rIRkURvGz zTZ>4ETGa=fW$rsP(Ed%FlDvGaVB{eu#CJX$*_Z29-rT+e-^|R-%Oj*j?%TNho(YD3 z^>sx%xbB~^tG46j;UUwtk!az`_STzJc4&3?1OKL6qjE-dcqC@T9CDM6?9FXL(6xY? z6n+zu<-PvtBbItNB<)ru;KqpH=HmHx?vj1y^6Z=!lSXn$S$qG`Wb0?&k)s9zQc0n_ zO;+2#VKh7ronD4|-jC2D9x-nH4N!Q>R^6Dd+rg*uZ+|N`hW0UQTAA7V;+xh_b&D$w zRIE&)-@caHcUxikpYyGLw>tMoSHQb(O44tD-Q;|nrK_ok&hS$8^~zwUHUu3@;$OXs z^`m?rOyD2DM}<7D;N#E;Ssi`9geNN-g)?a*ONPQ@+^VxR)AT>+IQHOv;;#>!*4OP| z<8eLgjc%mi!m5n-{BnM#!xiHzIEp~?%1r^+A_)_I-?jB#a>tzJW6QxQe7PCg#s~sr z#k(`hb;Gf8YHrf@m)`30x)h`KdKiDsI@wizKT3|VhjQ~SG3ahB#+^|N`Fz+fN3`{| z#mz9G@b6YR1qJqcad7~^4j$ngr?G2<Ug#CVi+5TkT zCbR8+Pqg}|Wu@Bq>RB-5^I0X!f4yL^#xNrv+6GXual-nIrFL^F->@Wn(9s3xOv?VD zJis#K02@BM&B^}{PI%hZ=XMI@Fb2r`#U8wFMD3X${J|Ac96E8Hu17(W=^c!WI&XRh zYU0L zo`yjPpuN^C<8#~&<&5O+dB?P>RkytlEd4)Q`^OTsn!+s~P}<*TkGmbeD`jU}O@vRl z$4lk*55N|5Y;Fa&zAp&sfN^$}9y6O3`}rCby)55gK3mK=a z->-j5u?|}rZw7J}TZQ6}(KTmYd~V+=EAPw6lf4EMUPJ$_Lt<+E+${m-Y~SQ)2hJa7 zmkm!Tc)zWNI#>yyuxszXKDE>HMZeN^3|6VRnNdmcu#Syhjh3rd_i}nLKO*H&CH2pH zDW%SPkG8QAlRnLM8h?wSX%ZRIb^z9TTrNI-B{+o{Ie#`OaxF?muum{a?$cLK52a-p z7#Q1xQ&LyQ_+Vs#D);U4-#ir+5z^nI@TO*Fs{UQoL_z37Ya?zRY$3P53VlS?%%;`P z@fqu879>=|KDk^RNaK{1U982jtcnTeg=QdNpjf_?=ra+90!glH;SzzG2|<~F?)lng zEk$Yko^C$K-*nYx=#>?*C7VG1=1sExPT4lrrTCRmwL>f`$8BXZ?Ed{nNlmFDLaW^1 zawQU9R!Mn#wMSA3qKr0GS@U&zV)x+e2yPWcA6oAf!ql&yJa;N=F<9M9AOX4DCTD|j z%-J*x0sTPtAX=UFnFO2480*SB+V%1#@B8m|xS>he&1>dm|Pt&F>tV0wsH z+DvQpL#G|RaV8d2eI~9rUjyOYz3~ueFc^&a*f9@xBV7*qk8CP6(Wc<;J?fw0wDIpLj#)cRL$n#;^?fM`-dF_`jjGu0D2u}s$U_crl#)Hl5br;2fX!2Q_9<5_+4r7(qPJosVluLalmNWBR(;I zUR^{(?X0y3!s@sFzCpStp4%H;s;hjpn_DT$RrZ2NBFzuMA_OA1VT~NiZao*si8?Xb zQXu^EYamxEFylTwVRtZG0<*uV1rnG7~z?! z$x`-ElEGgY9(mh6F|7Ny@Y!EcivY`ba$b~h4D|fie-59!7X^#pI8~q%gzZ+i>MZ$z z#goGi^h=i#+>30AfyG&HvF4v5J&5C5M{u0hYp!(@feD<3%X7hiu|fBr0GF0Jk8bWs zCS@N{{bnx0?niI*gT{jdaqkhy+Q61$49I^624*XI;{JK^{`_^>DeYsm^EdYL&OJID{1hZ4 z@{aM3K5cDkjVZ?Dv6vDHYHspxTf+u?3H`b!VU*WHke>I~2k#WI(=)%PmF&5`)dN;u zc;24O_SXzflR?e`Bt9)s90!acGJFE`_Q`)FBLx$!*@cT2yDKHvG`HuDO>`!4B}(7Tu7WQ%s1jwJ_-tz<2%PzMCk;DCKNrR51) zKhq_~v?T~V5h}ZUG{E|#=t98c(KB%y+)+a`d~q$V*g|99f%PN|*1OEk_EJ@J=HdB( zOoptHy3qNGS`*(n3H^Xf@5lkBmXIWc&ZXZbeoh?q{Z`9avd%v@#pd4<3>iXQq1B~g z%AX?cSUV=E`rI9UQ<}~-k5T9!{4-UTCb5>LBtXGYP{Z|s%rP6M22}x1Z zQ+brl{GC`eho}+!hG|Z%;nP1;*&3&%X-ec9m^u$KzToh4% z>0`@0a}HTp91+V6>4b(Biq%M^8c%80%(fV#qBdJGsbx8XSxTy_c!#{PhPS1ZM*&xJ zAwmuhCJwBWYnubo8K>fAjv4TZocWRG9cdo7F06bx*ft4_sJlq7d$IK3rjatKE@~`b zkzU$z;I1{c-w@Ta7oyB^c-!dcd#T!=xXoJbOG+QKC6qt4Rk1c#Wdk7bV9HHeg#O#a z6$x)}_cBdN5eOGwOKsFoDmvn5#%xt~48(QJ?mYe_q5I{{l4ni>sk&dgq2o@O`h?JD zfxdm?BuQd=$ zR~4rZRy6bck4N)xs#P1Gnsa|QQkYDQfwCV9IDX*=d+^1jGe=VwH6Jp$zd`SS2+}M< zA77aH_dYUoUg(zpsm7Xrnr!v4_4@-W?GM6C?Ui_TGAkRn=HzY+ZEPDqBj?sBBio}U z`$U2b>CyT)GlBX-p?2?_UAyoTIS!cUKer*EfzxE2PRgH2u~m`lpJug1)!2}P2yN}| zgP8No1C84i2-VSi*8A}~@q51_gi|&<;Aa;)n45v@*Dn+1pQpJMo?7P=`Bi%?P`9Y- za_8U|UGXPrQ0(0-C!*#DT^2_%0)BWzU2;IOLUxZo&V^TB7d_v`O` zA{s*7*)*{={?q)xyys&snn!lX3Oi?je({kd^lIo(Mn8KstR7(WU zlX$?#m1SeSR~06^g8F(pI>UcQE`BMIy8ggM*J&g%sWL2B6fIZi|ipUBIa z;^?ah(4Jhq?X}A*`Y#*OIV|XD^RyQm?WQ5@cjPh0%LG1|`c457xBJZcjqQ`q1z1QX zf&18&=dh7rSCM$jOP(oUzLzN0U-3GIrpGfb%A(5K+%$17f3+4h^TwQx7FOOg_n1kb zbrkX5c9!gk?RchB%18cfJ~}XGMGY{lpSl3zKTSqSOG)lmFcfR`BDBE)-1mS*UcVe1 zbm}9<_dsEURM%m+bN<*H-JnuX}gzxI=9zsd; z&_r{_M_HE0%LM&cMd#4ZKbs!=ifH1Jc|O>&;fU>OKX0PV zwP|2+fNf1HYosV@d+#xD&5$;xipG}2^}6GP`Bff+i|25je(5r`Ei29Fjg2mbj{&#DzFZu1^hEPq?oe1AtCdbH zjor;(F=3+<$NxCY(|2>+VWq=^DzT)!(iM1WvJ=et0nCD@t3%SJlB5x>ZQKH#h}nS+ ztHpKpE1-P&h2-RMynomC!5#^bq2-R2%Jty3bDC{iHN8LYawbe)_?`4kbp0S|J0SHU z3bj^k{z^Q1u4N`R6QaptrQV`*+p0L;EWP9SK!6MLN}`5OgGGqF;`Cwn9+Z{iQZ((_ zKq5C@gq@!3oSWI2Oyh|oMSnO=ev=UFYol3P65eo^7ZJx4xhEJcY|KCCQ>?zzDlb2< zGw=tl79kk$7&U>9KcT-l%X05rG)=(G{8fnRuONf1;k>M)TP?BOCD~45^rjJa<}14J zX?r&C+wP1PfyZ17nnXk24fm@NR68hukBd)v}PMBiNl1R^MsZfq$??3*SP8 zDmEM~$pRJiG>D@Atgcs{jX0!#(DAdHJNlg{VejO!kwX|l zh*aXv6sqO7qhPMd%gnU4AOrZW$$s_)=Sv8)E;y zAt~~cjGs;&2g9;q@7z1#WK53Gkx!=}R&P}9XXT^4pa~%W&v0|QhYS4Oa&No`+ah4z zbypy(<{3PUr#f`i*J|>&w!paF=4Us5HThoohGM_`REM{r$l|FmbT0oFfHhy}9$R4WX(eq2%3#V}yUmeAWPhKMJ1S)&o&2~tA8*`kyAoe!U0Xq$c< zO>eFXQ&^ovsw;4R@MFW(y;YE}UFJUCBGeh+792GJN&UDA3%Ug86wCtoSGO?n>1;=? z3&+O}wKIM02vFn|!jQ{ET}k*8cLe7rK>h%#80y{`bgOSm7Or@V=51m0HKh^b}c;Mde(@x8t72nS%W*M>#x z*Nm61IGtS+O8KfmFXSWuI!7>>3SC6rvQk%aUf0Kn$``q$5e7PU*lMJaq_ zl-LY$s4HU6@lPBn{O*_$J%8r#(Su`Jrl4d#vg>1HP%y5*r1^PkS3=Q!Ks(UgcuV$n zgQ70D&|sfTA!E~2*uaPJbwQ2g0>?km!i{QqY^X{01mYKc^;KHe_V*BK+#2_-44%+f zos=`3Y2Cv}VK+m1mpj5&+8U5Rf=)`_d1pi3{Zf&5cLc&=O8}7GaTbzvfmtHwwchNt zUl{Me^C7%o;0W55 zaG-GESn zrSQxt=~}$n^l8vBJxx9+$|Ah@{Vx1XJd<_0BG(RQQ``mveddf7_C|$nYvf)Hpl4rxRpTv`%Sr z!13`U{S5Q_toX}>D}%u4x1n$04TG}g$qj*=xgu?6?&-gtxDH?((#wFl`VYpPNlQ4c z`DAFs@n`ig-cj4J^Q;bm1J)U{k*O4A@uprRgx>sj2BNkcjEc>*oVKJmJ-94QOTBhX z3ZnJXe6tp_7??pjp(pg1J6f1itKj$dOzjX?!is_`Z<~{k#1kn}Pe}g06NN{WkGNlniV1wFeq)W z;$d7S-!Ng*`8yeFG8;}Q$EZ%j<*V6?o1Z<*N&Puq58nXqY-_Er^|KiO1laEnWYz!S zlc_<#C&z=LtGiC;J3QX2UtsIRG;b0J6{5;ub{D?Uo^Q`BSmbz@k1-jJ*Bs+m8 zn%1oI2#s)3AtVg(@2IK|_&d>NK8^43yP#e;1Jd!kq7+~Z2m&_97C8K3^IaR>EY$6T zHM%+A)1&Yh@IB6Go~Tgu)!9vJQaov`=jJ^-4s}SrG@yrH;g<_LcQh^2za2Vytl2@W(HH^P?-V|xX&S1V_F*5F}}Kq+P#&=%=??J zt`_W~d}J~H*Y1dhku?5k|7O#=E*eC83~v!4`)ttZdMa@ke;z5Be@u>#tb4L+%~y8Q z|7~tQd{w-z3(HbB3<+J&SNXaH`=H8(TfQH;=UC@V$(c)=UsYa+%9wTTUlW2Wj{@>* z2VBkZOB_i9`*ZnSczot6mz@(Xwtvnb&=K86bduZ71)xW#h`rJ+o`iXblBMP34lmb*0d0C1S3n%%pe&7O-ul{^UbKo(R zCx9b<5191lMN&)p3P0%aJ(cCg5BgsDM}ysfKRTK96Y?vbx*_XOTx(Ae;-}UJEai!` zU)-ey-n{ztSTPV;;?mri?+V08IXa$E*P?3CZ4T)04P!7joY*Wf&Xhjw&xXsoABdms zb7zkCw`%ocmQVB(>?y%S&ab&WX;g~Xq^hVM2W;;6%p|g)>}0RE`r-wwz)D^bAD{@sL6 z;O#PKYYQ#4oH13#%~P&&b~wz{{0C&A=i)3RUYWt0$-`g5JD6SlQY16`YQ|1=D;Cu^ zh*M*jSFpa;FEX@#(nZ4;c(~LJW3C5a1IkQ{R%>o2J7x%XQz-ut4$ieTLD4IQGJQGo89MGCKcXq*#8y_A4AvIXCzY~e3m8)^L4f=kg1I7^Y zX{$tVLkd4nXiIzclYzv|t1PLq-;-s53`blHVIHup)M#PbGcm6pRj1*dPua9}eJ{R< zENoIJ<_V1h$kw~UMkKdjT{T0ck3H~w_(We=U#p64?HHkL^l)LBrG;vwdk=9LPN#Q$BLwuf-R`n6H8EHNz0FzYKG@{A7@e zKyZ-GCnW~YJs`Ua(T!;=DVte+*Jg(!dBe=BU;&a}?p{JR$6B(#1t#+}tBdApo*dkC zQdM#>%!4zZhZu-{)!b?a*zL41ajFjN`k#upTCn*e8XuXN>{>;D{DJ zS9~!fpz~?@vWIpRL-y;1Q8smE799@P6XMWdA)Ph%zxHxuK}}kW@IIue)5wJL4rUmC zda)P*Tvr70-d&t=GxB{iZi}Zc%oQE3{@1<^Uh1Ue7hN5n^t=2{ij?sE_vP4j9!p-p zU_}2Syz(k7QZYp3p5vXK?QK0Lw9_<R1Lja_xA7>3FaIR&P-L0A2~Wo`4uI3zrcZI{StL1s{Vx2N{t69Zn_K^5J;S%|i0^w-+}j!Yhptfw4UOq0VT8*WkgM z-=1XB#z;XtjwE&xWPY055vZ_A`?Ue_dKuQ5iv&l8BPNA%A2Y{8hSzMj#i_x(ZZxr0Havs{j zGl#DT&f{st%n&H!{i}YaKrv4YV8rbB0{j&_G_&Ph{*!h1Qy?81L2+))s@xCf1LgCP zBLf$wLIF&_s~keEVmvl`6};=Sb;$p??0N~cy2B`a8F;xSvwuw$)y;&Ne1l`oBCiCgTRei6x*@AVt<81#UE=>eQ-J_)K%QYDzx(e-l^F4VOo%9sVlBcb}DQj z+AjBS%@dCyBnM<5c{!~ytTI-`?C7~Fn8l;jJ*CYyY8h(c@hds_gcO{e1p1Yz!<%R5 zS?0<*WUo5YD%RJqgj%#e9SbWz2^VDm9P4IgfKzV6Fd$uLY`mm%M=WNm3R0^Sur5p8 zy8#rdfzrim5BCcEd|8(&Lo48Bx&D~{%j{6eZwK_nds>erD^!9_9~(;V)Rs^Z6W5 za#7>26@xA}K6OezF$5wx zn>AbmzqGQ6qPQ1`3S?|u!UzsqmOHZhi4pWAKS^HGj;kuU!4Uqu#ZZgIaaOY)JlA2K zvBOal_N4WQBjGcqedhqd0i3{sF_gIVtW`l*_PQO8RoB@9(Re{m=s6g0f7D$x^Gn0Y zAoq(%L^y=k?L2TEfEY#js$nSV3y0N_5a;|BOl};$^K7Oa#q@oDiBQM^(>A~xGxaN~ zVX8M5kT|EA4#w#}RQ4DFpwI*8w%Og`hd!O}B)r*`S5N3SfP(gc6~hN_#AsA6eGqXZ zUqyJ?QgR|%9YAVzi2MoEco5QMEJ+Gts!!*sW1aTyrNr|CQ4!<2;%}bGdV@V$Sh4`f z!D7RnI{z38iP0lj39jXGt%b8b7X{Ezr5YAI%R7Lj_w06{INmXe7R$r$d~wt$ZZDX9 zSZo;&{>Y9xaUkqEe}JTg`|pdMaQo=3t_1g*BTQbu*B)4 zl-#hVgs3ds&7fT-KAlW@FyFh|5Z6oMg4b5F0-1Toslbd`-?3$f4B8}EtfgSKO2$Ee zxzUx`zWNr_Ea(c#HlO{x1q&B^92o2xkDE?nT?gX4>@7RoT7P^f z8S)Q+YFH+F(TfKZ)G#rgF~2nGFrG)wCbZjwb%P; z9;qk4UAAD*74hExvmX8-5Q+YhDGreU#3^`&@JKP!axfyrq~h%AhmRbLqHeS?@8*uO zPcg0ZtotdrMf{Jkm19M9eB|hpVHv^zeXyEWYWZ|#C3%`Mqx7T|px1v?uG3(@(gi(x zL07+off>T%REiZBoHzc*$&h=(ED%dAKt2~wQQ6cxRrM=0eppq6k6k_O&W8MvSMWQ} zp5p)f3!8dhu6Ogq*Dwo0eZ|UR);tCjU6Q# z>s~B0S68m;aCLNXAJ0=H1k{^R4(RxYWJnCPRgAw_tC|l;Qi1YclWW(F8ateuq?>m9 zY)J?Nzlg=3g4ao!1i1)32I`0G#kj-Oo+fKS>FvHPSQhR_sIIC$scHMkAs}|KL_1u* zN<{wZ(#VAlk-Bnbqj46Kl{gkn5G8a~5z}(j>FmtrpPpUCg2;e+(PIDb5vZU$hw!^3 z9cF@)q(zE-)66TkvkR-WWD22e+U)EKR8VX*x`2=D&JPGOnin5F!SnYi%zvJGro*&x zu7YV#b1WuC@amDq#!7@&8ZO=k229jp#w2(a=~OecE+Luo`dI?~u`;8TPt3_^TK020ihID7bm9ofAM8`?@9yrPpYJ0?jsaL*9gwbG z{c>FC*(42{*M6&*YfD&g&HG$u+z(G^f{)OfcpYYX!WgtDtxHoaxF?K^FNaSzE+Z?N zQG{C>DgunRj_fyp`8wyGO{rThIc@%`A;FSfc`|`_%By$jX>AAnB>bKV3*<~h?QoYC zgNFF`&rbB>kL}ABRw8*mvQDJvFk=(!kPDJuTE|L>Y53Jz-;n)k47Z`|sEjON*tI}G zFX`P+GHgACcS$5V^6|AD6`=LSZas$o0FaN>00(H9kzdjF8=m-)xEU- zfJ2x=hy}tGfxjh~snQ-WoVIpc#i({t=Z+qJd8}gm7+}U7LF;~(Lc4|5iIv(RGjePgw1`q!1%D@x_dt>asMK1GCpCacWH7o0Etpzdiqakg_Bb>pp0)f%+lP>#{a(!>^jY+uAEyIya;E)1{h;ccVEONgm{&dcc{;l zXK&%^+9@Wg%_x78geR6}(+hPRyYJq%2W~so3%%r3)yK*+73A)&Kg9^p_63>^f&r@! zOMYAR220fCKCmUbZo+QQ{A^lo;lbNfYWV->_7&`nvrC{hYh8pWEwMTBGFi4L$%$AO zu$Q-vOWBz?%cz?7^=whLJ=P3Il73tQHU)s>fzE+^*}pLk<wzqmB{|WDuZ+^EB?Q2 z6aU8!ivN4~-<>4?s~m2ajwn5&8H_@w-W9I}Q~leAdJ90H-E;qSivLme|JBG0_5|P> omj9cg{%7_5|3CZt=$KE~%NIE}Wmtg!w+9*BG&iW#yZ7|}0Z?l3+yDRo literal 0 HcmV?d00001 From 8578dc7b3e715f52e6acddd5a375852737daefeb Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Tue, 28 Jun 2022 10:10:55 +0300 Subject: [PATCH 052/105] fixed typo --- .../doc/Arrangement_on_surface_2/examples.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/examples.txt b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/examples.txt index 5e8b1f376be..1196580e382 100644 --- a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/examples.txt +++ b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/examples.txt @@ -43,7 +43,7 @@ \example Arrangement_on_surface_2/unbounded_non_intersecting.cpp \example Arrangement_on_surface_2/unbounded_rational_functions.cpp \example Arrangement_on_surface_2/vertical_ray_shooting.cpp -\example Arrangement_on_surface_2/draw_arr +\example Arrangement_on_surface_2/draw_arr.cpp \example Arrangement_on_surface_2/linear_conics.cpp \example Arrangement_on_surface_2/parabolas.cpp \example Arrangement_on_surface_2/ellipses.cpp From 4ceb757656b7bf6b2455e943db6e3dbf314fc02b Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Tue, 28 Jun 2022 10:11:02 +0300 Subject: [PATCH 053/105] Added shadows --- .../Arrangement_on_surface_2/fig/draw_arr.png | Bin 16301 -> 16103 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/fig/draw_arr.png b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/fig/draw_arr.png index ea7cf9f9809e84c5cf935999e51c448ec6d479fe..6e7b0c874b35cd8629c6c5a449475961af43e348 100644 GIT binary patch literal 16103 zcmeIZXH-+&_b$2L& zs;CVBP$&REw&A4Um0yQs3g9o8n>1){)@5v8hRsg9er|X@$G3ArV?h$aY<3)HZwKTo{VC=!+E4Zcg6;C;8 zI>~pDZ_~RFbOc*TOXP;+^Art1TICKiA#+b-l)R%CTb!-2%0Os2SqHL(~@0zXNp_0xs{rUl_5f#p84T90-7ET0fR9 zN-whxAe5SwqqymkdTr2nVh9fHBlp$PR2c7EBL)C)?MG?48X`rnqf+cwYLZkq6I9r* zH?P<95>YbC_;`nt031h&0YbAtd+_KemD%sFbdu^74jrV8-y>PfC)`RbtARFOk{v95T5N)z@~2{s@J1_0)i zsw&UP!P!ub98!Dxl^#c0-AHY90!fg~q;2WWM6$JTIov65&VVk;r$7fucaU zt@cWOxYt(VDqV2RiwKP2{7fGY^zL21L^Tc@!N&*yGf<*eibe5gOTpQNC1C6*7H&In zg8}S_gZ9_!ZXi71Iff&8^@a(n3M9h{vM9kN3ZY8)IIbAP3__bQ-qJQF>Q;f!6)W0dZ6}q~mBZ*Jh6V(fTCG-|oigNY7^1QgCgNFjFP7K{U zWiP@pHLG{bAHnOe@bOq~DDCkFCFO4(n{&M$qj_Y@+gC^!{^b-lEL$y^)0)~}7n!Ph zSxOo~OkC^vi68y<-$rVQQ-N|*kK!A=&-2wdKWdlc&&^E{`)d0g=7$-D|GF6gK$zCN zShk)NkguC_Q{XP_X`c&SX8U%Ce)9D(x9C+qd7f;| zVO=2T`=a#&kF%fJ$C_U=IgS&_qUEogQOso>Jr5|tdQ!LQ7d8HkHom@4|T_qskF=4U!B&!B()DqE6=!v^{bK`+= zuErU`7Il9qNnJwX>DKRhecI#rp_N3v+f}aL`oAx{#W^u1v-25==kM%jcjF;ysL~Pl z4Vpz7D4K?999LdF_|n9OXtCP2rG<_S-NXPX1vdW-6BSSU%WtDP0neD*&)yjMCpDxEq?-yYwISO=o3VXLErLd|q9&bi( zyCo7&h>2>PLgM0uF&#d7qQAYP0?)>+7#LR98f8Wto&^L1h@V!W;`2vJ^;h1TNtNkF zovSst9Y#)HTuhhinEKX;pr=33TTXqtd zo=kP3iv(Ql?^SU(pAKr|Ke~N4IgrQL@+D4gabH%c`rq>(ZJ35Kv>zDElQk)Z1bE%vMSr?cv$>B3F}awzMfvLD_(Nm z&P?d@o*8FgAO zO(`qx6ds*`AJ*F63D$}IDZ1P#Nl)2-&5Q|_KeOHVc}Bmg6IG~B(%{Uf$C)rx!=X@X z8lm0vL4oG+^QfDAx_O!d|1O7-5>NKyZ{`%Iv>qu2Z0=p;ce4bkwKbI~DRC|OJ74`; za}XO{s$J4kvr5-e5JiUKT_n^8oi*QhaC<1=aH=xzlj#Jm{Ea*kL?u>lEdg`lE68wr zIcwF(DbBjVz>%KKps$_F&5C2ag! z^q2P9WY)^l)H5@SyFpDTF)X+5#aS%8y2WQI#)?lCK~HcX4RO{_)6`x~j}=Y$9bjy( zzK}Y^(3+42m-JG3--6C-&Xj)($z1! zHKY{~lciEnMu-}2Mk~unHD#CJ^va%BSXP4(Z}I38U6e3Wm1PsoX+qq^s4`%~@kRMX z7t8t6k#DX_wYY&M+nfOPvA_$i=8I1e`=!c(nkFihKVH0Nazq?ko@6=IR3NGC=R_NE|MOjZE6KK0uXJV3 zObUC6%b!6DkBM_}fge77B7QQrc9-usBaW?v(Z&wPb42}0=yTXxEGLfVTqI39oNRj1t zkjB8k@N1FJh!8Y$k{3uQRTdI^H@uzwux%|XDEBV4QNfd_8z5|#dx}I>56qkgh#o}_ z1gwIvh;)Tx$A#6|pGBj3^Wy3apUEjHN%18s`t_}>9pj*ty`1;#XT%*Yf_~1q1Rwf3 zDQCc$Oyyv|^U>@0p8WHpuB~BJb!lW##TlQ}(X0YCvDA0N(QJ6Psa&sAe7jR&zni7~ zDM$vnAXDO;rm+3~2T=^SvIaO@f=Y*0>NbOBEjFgxbmnQFwEg|cwfaHSIG3(B#opgv ze#|83V@1n3v84N5U%tl$35~szlkwSEfT0)B(B$Nd#ZF+VsQOLFXckT{-hHjy3$$SQ z`|8u^4a%+Qyy_jx-lba5;vZQ8JJiK@U}xLiV{7SKr#ZwE()}zKvvMl0snVd+qM-L^ zeDh+*`Lj2Q@<9hX8Y@jpIb)7LgHXL=MI(L(*#4lr3^U}H)ZrFDC<`uNaLw*Ot3Lk)P+|D668ySLrcM0YY~{W{`;j=k_py2Rjh0E^N~R^fUza1?6gE%(T3G|t!0 zEk-a0J0JI|>BD*Z?^ZN&XnT9Rj0Wk3`>MRea`oo^O3TbeFwS`*zd-dyv2lr7TaoAH zB%fnP?P+juCh18nvByJZ_?hSoCsN$%%>MgQ?=yT(>b>QCoiPVK+QzM=6Yq{L80%KSx$k5%-c*?&t6qYnRVNv`ieL@p>*U>R_yu@Z8j9d;jYV zzql!j|3$&1lq6QZx=hEEXj%UJC5F93^Pa=kw+p_95;GNaz53Ya+>Tq*>_xnDo7!X&}pM zdZeb7-*4i+j#<(0iVr?s$YZgiV`XNhgU{WzszVu!{U7I_1pL`O?5*LQa-HW(r)O~_ z{$rH<3!gD~H}2GMDbpkT2EXC>y&a8d3cnoCeM|}8YuS;a=YK?`j(;hkCu&eUdc0$k zDcNPpECGsAQY*LC{8uY4Of{tIwc1Wl{)It7EAfzk`HYM5po=&chq;hD1j6A;ZBCOs zc*2TJ#_Cp9^EzvwP^%akW)xlJmp*^U)Us%o6*y^VvX^zCqoGl08Zg}ypI<6{p)u)t z7~nhnAG+r zHhn6pIL-82AJ20VFTZltS9olz`*LCv;?J2J;vtBw{f?QlU{azVsBGP&8?J_vCV{e} zd}P0;<23qUeX7)*yMQE_+F|XWO%Rvx)0&VhdVynKk!e5YyJQ!h_f>V?gSkW^Cx1%C zS}$QaoY7_UxKdnMHJNvGP?@PD1~i99rNp!N{Vxd`j%%Z6L!7(o=zN+#pOI8foHQ|Y zv+d%}CFq40Z#)-2Z?s}ZUcLEXpvFekdG@Y<^$^G}^qRtiu$rP_Y@H);M z{**phPtIbxH6c-NTA-cTz=zaH3O;)l*a2!>^?E~{YF?9_9+^wlSk8-J85}XY;OC?N zVZT%{Ve3O!no8H=t3sFPCGa{fIySvppkR7=Wbu7zulXeV1XZr*(Tnz4{Ud5p?AHHS z$7?Deu4ZDwW$npTVv;(S(0hKNv-9k>dEc`&(~nn8Pq+#DKYs5}?;rNVq4A&&Cmhjg ztc(jQJMMgVjn&19I}!501e*IF3J@!8t6Nz<23V7Nk0XoHqHnVut|Li;f$f%GUnOO< znniv6VCrpA8~b?iDZ#oH%uRg%^b~oVzI3c}{q*j8(%aE8`;MtI76mEFt;1Hn^$aZO z58RfYQ3HA`Tgq<)k1q|SHqIkS<{R;w33$`Kzfg%x24z-*%S_%)5%j1WS;eoEjw3JP z0+ZKD%h>r-TH3p{IPWiW5%;syOEvGUD$5+FCG#`J+ZbRcaJ+q|OzH)^=*c>ROV3ee zewq5yI4GSt=+FIfi4B|h{G9W3CBosMP=M23n|hMNGYQZ20TAx)v)}0m*#2rqp@;AF zL4NLL@~aya;)WgmK9Nq<{+LBEsw z%5DlX)~Z~q{JdPjV_~Xeuv=fx-MV7%UDALKtqn&)S_v+pCrn96>DSDR=*S$H(e8Op z*6_x}#)9hL=R|UTatcEIKQJ)vtBAm8Tr4aYR{sH}e8!}R-TW7&;iRh#E!l*B@Y?m- z{0lk$Ls9HVe8W~|^Qslm@zF!Ap*2&laQ6Ety(>mDN0ZTou@VRLe1@%x3%g&+0!Q#^ zQpW?h0{Q9>H?v$rrcb|(@#OTc%~YIgfJr?e+v_a&QJQ-%5B>KAU&8$)6=AH_Nw}Po z5q9Iy4y~%w`^!N%;BbG1$9PA0TUOiz&ISW6$i`McpG;=Ya{oh4tc?qJ$}h3duupI~ZO|(hxBj_= ztK=`$I9-@o{yf%ZXq(e!$}h9$p5?iEpIEDLnsl(9b!@1vx9c>a0~vDuXD|JXctAK< zZeDX4c&~iBa9Ca9Nk`x*64Y{b?(Vu?zkNWZypVoAE#V{WD7>=iw>cJkv+Po%me}+r zFB@H)b@P7DO?6;== z7(QX@LNc2DwYT+Tj)Wsl)Hh{!wVB+C=Pic4hm!m)LZjpH1^5F)l_DJ-bkXpA^c2n{ zg1{`kBz$qA%9${UL$`dyZFXD)7oyc>-fzy_5O1*E3X|SHKLi6jiF>)(P9xU%+M+Mx*b?n>hlwGM`1~2klU7jBkxty zJciEp>AypJ{7%Ve{P%@d;%h%VE>mUuoexiRdY>m3+%z2*@@QFm|Nh$9QFD%JJgB34 zaE_~eHnuEPhe1Z0hteLkQ`${smeu)SzI~ZKF>W?1uecjtC0**^@an4|3kR+JV;S$? zk1l`FQwNy*g%zF-~x7_~RvO$#l%UFi0+V zeU&s(WxRGV*ZR@@sh3Mqz9(DlPeMaUh+V3I%JKWPjLv%E^;<*pXODfPdz0R7j=RP^ zXq_DqUt3sXM}o}P5&M{UuUu+@PX=yh-|y%RbKN;6Vhe4(p#b;kL$0{M&OCsHLCA z*ZK608sKj+G7ZOwPGK*Pe9LEyWtk>$iw`^EBz15^OZ+Y4Z*Y~=c7{VJOJ$i$rtLq5 zTJZJNEzxzK(s0S76DeY3%D6cGVIA+gm^Nd#hTAX-Sn#R^)_}o<6#CdAPTiLGu|_7gheFl}6U1^TF*yhTOuf;c|nqczN4ou%baAe0VKb z8MMh#%<>e6##h+H_>t>!Y)sVZUusd&8DDTgOVU&aheD=N0sK$%o{!#ITl=*6DS}z6 zz63pcGcU?L-y*edo016_^H(H^85**Y{YL;Pdo|q6Pcn){|yI|?a945 z%dZeH!=syQ@lx#Xs4`gCUH3BnTs_BP-;F~>R5HU%xuBjtHbBuF{-q_FlgQJVoTWXAEtWz--r7I8^V@;kWP=a zJlE}@Oro!!u%zT~dhv`Vf9|w_!e<%v);sb90s&iDsSjqy{ilnMr#ub=h=Uq|SWw|D z1vu-JK%@>&uNpR4zAk$*G+K@))G`L0S8N+&}9UZ7-1WJ9Ic})&b{Yd#0vl zw>5o@qiiwm{#e40M#V`JSUTMs8P@6O=mgS#RnY+LB- zC~w(nGLuTH6ZsubIZcS2(aF>NWpent@>6hG&59zvQe*9qcQ$(XP-EDLvg1#t;NqDP z$yZB*&?NEz*PUW&)g-P4@$v=VVMd-?0T%ilN<)ur1p8bb8}cTj%17J>8j)7>=nmg~u1P&KkMYtkN>em`Ng9}iZoiz^!f-O^qah!Z@K?7Ri>>*t4)`hs$--qBkPEPL8jd3~GOF%0O?yvJk4`^+RH z6|AePaQ>P}L9xA0tv8i68}e>1RueDy6rAZWl3vqxHd$?z0;cp}3NQWgSlN9&{Uc$+ zvAvY#;&0Jv-v|%WSIZ~ImiDWott-~rZ2=PjqWqICMt48@B!T+o;Kc~Ov3g)1t-4w~ z^R=#8aqC+fB*(uAyFuCK-_8{iJ8~j?Y&e?IuqrD1-Nstj^P!tm!$`W2bhdth zVS|F9Oo{f_l{$|uTh$=_Sspv?HE4hgcmINW;+?41=OZY1xcu9 zYarAAO#$U6wt?&8^t7+=tFi4=-rjVrCo6vmkY=sYkxM#XS$Cnz^gAH>gkp4OR#Kv# zWW}cqluU$B_a+LPj|e$%?Yn~ljzX%r<#(yOh~O5>&OLoBH=XM0#s=y_w&PV3Gsku0 zhy&``->VFaOge#<@@YqBl>DzAesTIrMLuHn{_k#}!2aAboD_ZTE0};~xP1vMA z(Go0BObVFz1P0ERGo6 z@Yoqp0y@)?@&V8GfF@YjF7UY)s^17&u?2 z`3i>pD+ig67qsy$5X?r%%m?D8Y#SHm0YJw zpy;$lEZh5UCe`WINHa|RXC~HZPF)u0GD-@tX3X(pm@#56x&3@g^3s5;)5%zAn1IiA zzeu|o`qVFYRqoD*VsK-Yy+jNuhfyG(s41&Qz+bhkt9&GI&%WBaO(wmIL>D}!YMY?J zY~p0|RD5juLDwCm2J&D9=ia~mK|{$#UjyfltWG6`gp*1>@@X3S`$ZO4QbiMxP>AO3ZDhX9Kl zkoSpN;MAK6LLb5kgxv~;y3&9a8NB)JFXEdt$($Slh`t$4Vi6@Bp10P?4&v(fS1knQ z7!HkOrJ?D(jfW^w$^jd5vT#1 z+0RY+fx51mX`YowNU2GE-b$q7gM@;^@3@XXemSwp`})ZRO!2-PXXVOym&=b7?j_zu zl3*h+a!C6TjY5@pCH4YqgCKVNd3@!WIC97o*%j}pLTt3Le?CNkWbu0V4+0kQ8QC)D z9V{Q5LSFH&%4&)byS>G{qbi}xRcVMBi8`Cac1#qqglur;99~TJbYukZqW7(<^ONGg zacsobnGD$^7i8uuaJ04bYRZDv`=S@{)VzkF>M22C^ZPfA1{Gg9ZMmV;(PgO`LVr5} zUAlU$U|`uKEN(?gyWg|ipO!=v}%8(CJ7&HV(hZBW(mN&X2Te)VF>Q*E0Wvh30 zcsR=KPs_@Dg>#ipsC&+PkSZe5+QZUC3~kw`nTd7CA=>!OYF?&$D@pOx?(`Im{)kR# zW9GNxHM%nF$wdMDd?kgsK@ZF9b7+U9IYZ?P36N;)s#Za+ukfe)+|cdL+qN!pIpbH_ z0`7Vf*!6Ee264!YzI-o0on6Y(Z6zL6ZikvvGnUsuWjnQf@th1Y{0=XkZkt*d_EW^~ z#!N?x`if(T+nu%8el9VcAtQPQ%-!|WzS+^W&NXuPAGi*-USi~G#H7VYf9YZId6e+z zk*Sz`lZg2I+Ay{7?v$934%>td|A(-mL$M0TdhUz!_y3{{UJLECv4FM)^W@Py~ zG20#OXhWFp!U3&;gWz{}xiI1(vewlfmH*jkC;hF2z~o8(p389OwJ+u8^tdgn3&PHN zKd=q|v#+{+Fpd%U^O_a2O>XiIZW7Vuvmgu4dC>`j1vgq2O)zE40M|gTvg9eV=PWxT z{h^4E4QqPY2_KZ>QZ%_@P8|XO7Xli90JR(dH)Q9(L#ZkQLBOJ4Y|k*lPXeXa&kjQe z``-^{k;uPh1wxepZlXmC3P6L&_35TXC{1ZF+kT$&N zcfEA@+$ZSbT{tWzAg%j@H+i1@nLP*Z8SGCCE5dfYsLx{6(ZZnvXbcBE?~-^BX6-o} z>At>9vK^^h0DUMc=I3z@jflUpi{)YTYJyf4WB?}D=}kJL3*YJVql^>^k^Ot6?PiYE zNnW$~U_{K5UA?Zr*(RV_4$&$3p(-Kfv(ok(Yk>w7Lw?W#2(b_#kWC2$(Vn4=L5d@(b?&9FH^Jn zi%1^1_U4pJt-x6P{#-YTw~=LJcJb~qImDe#OzM~pdHMk#g5LsSZyr6nZ5Agc{h|}0 z3sbxHp7!CIsu_9nRlB*L9&61m`D=&viqp%oVIbXBv8eY4i{-Ha`Xdzqy7AV}viAGj z4s83pJnj01qlK4bj4JFNKYy{RO#Rb*Dd6_-WSZOHF?0WInbf6fm&QM6H?)}dKUXob zn%A~tx&;rVWZpQskl-G2B{{o)=_j-LK|5wRW|n6aq)+REcFc6lj4H+Q zr%xkfme0cRpSFQn32rFoo4@3lsx;q+TmBvszO*!DVP<$KX@K`~2-!NtKSx7fLnA-W z$9=W}_4;*;5*^e?Qc{%62bElPcgF$9)wU1Fcea={`Dc49FUp|7)-U^ZZ=az(pYx`~ui|CDA`)tfsU%lOzk-6ZX z%|NFUELfI4u++StlTryYAF;eB8B8x(siVf24*3wriiv!<9X*4--2M44NNNl#VAkkm zbw_8B9Oiw?q9x|&vE(cT7K+J%Lkk}TMu@hAp8tMc+!x~`qLDiv<5i_5(R&<>1rQvt z;9?5%&$+dpcU=<&=I%6lxZR;;R@KqH0(2l?^1Zp_q2D%AsnWU3zwg=oc7%2Q0}Jl_ z;?jS+*9S^T<6TRYkWIn*7YMr^l z5|7zLBxl93P+2hCekj9}hvrQWdX67AQqzPH>Zu(&Afey``*PcIhaCbn_h8Vr=m7<1 zDw@U_$jyeE!DHkC^m444>$8Th{IW4OTe*+P2&vJ55|0!C@7Jv6&4|svKhn5nzinf3 z3NEN4$e@)JKkkNYS+J_Zp;|ZBe4yJA5HE+n0Tk}htO#Gy4M=D@7b3YAZek*0oj^+U z0D!y%!EoEJGWoYErOBh0-kmEBq?zRruOwvs5wO`ec73$)r@uI<7*1c2yi`KKL!G^x z-)D1~ciMzi(9j$S*$;SV;i(ZcFi2zXh7a_cu@b%O%8bi5{VVdjlF&P{h)9^A*V~`I zHm+^sVMW5l$WSK1av5L|G?9FwS2ij0@?BxcS@(MC$&cK?7pPn(e|FrSS4(@;9xMdA zC@5(Tmtiscm806}2ZO-6!6#HWl|_xTVkznv|3GtumN9ZBkUz1kh+8i<4f;SsSSP%c zOdzbjy++0ZnutD_)jV2Y>j!1CnXFwn+3)GHH>luZ=c|z*k>;?8Yvg7mIF9k(&1|{0 zr7vhRWNrj)je~W&u)4xPg*OLjxOteDNAGeqk~%~-Keg#@UD4T09G_3k{gwrp%(B_V zZ(00fdN)64(+TW(0Rp$=I`7R*y_x7EG8fE2Dn+hMr?gU4d%u&ly9PVGG3W!`gb#1a z${zmXiXJj2i-{=Y26CBT!T&yVi(_b;gLI?_|Mj5yx)26T${{dO;xh>nrh>d(BxrIi z6d?N-jA~Y&W5+Lg;Uod$!89~tCO^Us!;2|^YYGT>$j%3*yK&YXkL zOd)Y&Q$fb)d_i`V{+kOaQe7Wc~A z*FfdA9Q64P1MlBcG?S!8@%2!gaf(kg&O1-wteXx25&uORqjRT?9Fr;QlhxT{w>_jw z5nr5{lgzYgaJyNs-3K;=XJIDC>p<_$CGuePItjARVOY$V0t_$)Jt3W3!o_TIy9&k6 zNrkHqh)br@AT$1gfXs@906*G%S$PltS++A$=c4*n&OM8;09>iSs2;xVo#pE1ox4XT z?u3mZ@t);c2=wfHcL%C7eJK0yHJF4>j&9$7{?^Ft9s~yuEco7=-EGWP0%?}+730Rls;Q*U zhI9a^4lziz@f=?LqIvO*VgE>5ei#dVe~Znv{2IUpKjNj9;1>-iJ53i7v--HnkKg>BowaZxr6@}e zdJjpTo>OWa+oQT-d*|PVRwt0&HKa3-1TNLwz1KnBo&O?3-5xmfANL=Kl~aiQ zeyT5e>(MN$3OxXQf)Gd|KM|IR7|*EqvzITY-)KO$99aAF#{TY)Df`rwx_~i8h-CyT z5cflrHg~~cvl0=3#judceFhLnFeG{#C403;#!2+Wg3xQ^o?ZJQXQgrj@K-_zq>-Pf z^Y{Cj&<?ICe*}vtdDR8XMFEX1Aq$nOYj)z@dj<7R_!gQ;NzPw zaqluvkfKv8#ZfiYXTY2yL^ju-f!S3-pR1hdU@#$K@$miE4J<~EmTYP~`aT{2O^P7> zwgs2qKHoZY8-BpCpT})}`bAD*@oHVuJPT2Y@WM}|66Y(M%`!GgWB zcLnecXGJtFufwxq2>pb;CN9K}mUexO0v>$?%>8lR9R=lzvfEi^be;EL!Bqn2M~1Z? zEtx{g({DNTu4L|h;6{WWL&G4f_h68_m!T@6&t1m8szsGtN<#g}kj~ZbkGWrz?=OrW zo|O`)071iXL!wfIi^|vazJ(DPQoj@`ZKh7&b07=6D9zyCQBn-FXMvQNb=S&qou+AlIpp zH(~E1Wna~$N=_1R?q5vdUSrIv00S2ZCM6d09`-W@fiM#~*NeDoj~Dj7e8Qz9e9~82 zj}rinz*v@8yxu3-nkeuH1-a?*NO5*r$;9AC5~-S>3FaLu{HQOn1d!Ifu_#eg#64?? z${pT3(Q43`0C^;(y20iE>yU0#^6sw{FEbtB`@a+zq{yv-Xu_r%= zQ&U(DhzkF7G5Y#DAr%etDkMPR9XRZ3qE#CYnZwPX%|Yq*@)yt2#m0MH71CUDZ)4JD z00uyPAVlk#ys3L7{lTyjsxw1%JtSRhc?S_}W|8a2+1e4j4F;y({4C>b6lCV=JyX3a z&89!2&}3E5^qXG{ZIL6?VZp4ov?mV(%~VjV<8ML(X|B}`f&mbITMnRplFyA;v?8_W zTvNh4XM@xCbu*PL&3_Kpy)rqOtRs!OavR-c6Nv7w7m#HICczk#&VRyp;Tb!JrAU>0 zIZ#;&Z)FzW-BW=AS*&pS{_ZxbBHMM`$0Qq5RA-(nCpB(3jK(6D2joF(7=$+Uk^KNi zFzU+W`OPBD`QniUezKh6NLq200imrtn{jj zxuxnpqwd#r!K{Bpd=QDsJyVhbNl{G}0jI-4H|nJJR2#y1|H--&;@nh24lWQRw|}(g z>@q}Y$y&@6>9?&SbNiH>8gS(1*X24z!=vRI?k0mrk0yJpI6G3qRI%kn?~2X>XZ8I6r8k<6M;tz>HBS^uzaJoM~ z8t>V2n5~#-Gm>L@GUTOpQPGvuV%nJ{a$w}t)fI;`UjLdB(Db!AIkeoM=Jx*BR*D)CPG7Y^(Q^<*0p_WS(yA9fx}Z>+WEL+OHx-PYEJ-(fKcucuPQ#zn>= z;D(ix-)KTIB$p>~k5frZRj*71d)F*1t98#=a`u?ITMn2kf6rPQtv^lk_{0F_+wD!v zMklBKG#cT-@6H|pcjTV1{`!$26e+gTlK$o7pKT}|WH?Qi&UN7CNn6U#j(3@Se@rEQ z;wQH|yZC~fE(ZPZ&XrQ8bxke>REJUnJ>U1XTbgZ#_+bbtT^MwJbmCcJDb)F=rk5YC z#jJK|YSzQ7gc7g-H9kqgfnO}~dSPfjvekbYP6DJ`*|BOmCq16x?iY8o-5~E4U(*{q zd)fGIzUbxom9cE^&+R;??fXeYL&0!Z>uN>{dbC_>;uA-RNgKy4PT+IoTiNHS?$Ez_ zsLp5a8Q8X0*QerY4_LWLIL}@IbD(}T{;@=nO3(fIbFaWa66@x(PkylFf8>Cyoil*B z;Z3M1^Z03MmmC@db27d z#xURr%qEmTDdWVG`%!(Ilcss-wFmerVF5#&4P6ncp=l;NAPM( z8)jEtnJ0{ml3w82^~lE|nD=U`6cD(Nsh!{4czCc#1KpnnA#?5!Sxq&G(F~Bb+sbh_ zoD@0<7x!L6#&Bep{`b6)<4VG7i%8bao=_8zlC?k$8*krD9MHRRo5DS^vsa`o8*lDP z&x*KY3HrXe`~fASLiOA3evzG#$IwmZ_R^#?YLW^xZ6tq)?7-!N8g;1L{b$e?S^TqO zB88%#H6gQPA+k=Xz6VU*cS0~rSHn0d>n0EiS7eppP|j4hCAv-ntzxf2NYYG~kXi0L z?(BCs7Zt<~JS(1;B@{6CM9~-RAR}YIs)Eju9v$5KbNXY({l(6WCuAQGq#>!IK+^nhg)E2gQ5j$7@;kMVYWw9;cr z#o0457^v77K%Pk@Kz~C=~^4jR5gW>1HIML<@S$ zRRwxGMsO!Gpa`TmmK!@1JccvfqHL6}nook0$mWAm|Ai$Aa|fC;>E!mh_%#Fyxs+I2 z;Iaf12YNy_U4DZIzoyWI;lY#4f(1c$&P~c^PECmU^$=OsVhZn3 z(_B=r$QN-+_bMrH9S zJTrK%lVYB-!o!}}d11g%+t{&!yAdl-54W6_wF_ba_7E`W6I5p{ZqlK@^rOmn7cc^0 zr3Tfj7+Em1A}C=UdCT%?ov^+z=rr$#!vj^%A^GLE)P^kH#sPes-6K%pknCy zC3pnvA7@6w`ES!iGQiYY*9j2w7*!c?K=0SJK7 z>7Lr{^%sM(lWWD#K4V<)R|NP&Ff(f96kqH?C=1Nmv;>9+=Pptq;6MXdVV=c*`4qX% z+m^b#bj6C3hBz2_6aPURpnuJZ@O+sjM!$>*h7_G>QIJ$Px%eu;pt+2fY3{+R&yCdA zV3IynA8`_PGKqVn#x9hRpauRp3gl#Y*SU3N7L`HzIykmr@GGvE8VF{C!+QF#vc{a$ zq~d0sy(FH$KFhuvfdCt<@Gs#j97ph!xNe}sP!n= zC>8&-k%f_gNhBxBRF@_lE2WTG&nypx@dPITCd-`W{xe+%tq#Mzo^8(fezckkW)(1J z1LGvDQIyhp_*&EVJV(-S2$tlsLZAlb<(*knz76*LB2H?k&bR}K=MRf7wT+~O@UiJ6 zZXP;%u+E@cvzqN{WXtS)<|1v=%@w_$W;5MIwuiqYjxHA@Il0A(?CvUjs)eqxWmlWhWiA3 z1k#Br$(2ATk9M5<4VcJY^{Ox$+qE5)2^i_l&NXps_e|zlxaw_QF-CQM+47W)*187A zpmoNCMvUi^TAg3a*IzAaG8H`v1^cSN!~beGHu?`(B_t%?dlpVp$%Ltz-<1P9%3NSW z;C~LdY~g*O2d`r2!PW$DSqTNZpV6%URj>yeW)J`G;Qz%MFa95#-0Q{4e8r*3e$$Fo zTbvP-WsLmR%B2rrK(npE=#%(euocEKKivLPmHV=b`rrNE|Bby1LN)>O>kq&_iRfh$ z`2U*z|0@vxU+45c{n^NcP|XEk8f$ph*pNO*+L*WDHSuTzy^eflWRrakSI6f2#H7T7#ytSYb+bW!{ibYiBL68` zV1O51ywjDwx{^2a{PF#s^n<;(`ch;7U{Y#lhPY>MhDa@=tgC>7{}dN91K-ncL9u+J zR{-Ees^oiqdoz^zt5oypx1H9)x!6VUv%4TK0D{k$ySQXHOQ8wfhv|RI*amoEiC-1L zPn4^P_}tDpT`p!5kbVz3^whZct@p%ycP;-#I8fTt48FC5GNF5G zCD@#3tE^9@77kTC;f4*%fIO78ekSdZ9^midBhYX=5d7@%V$IUY=>-Jxmo5Hlx+VBt P7XUy$QCF;xHxKzAu8PYz literal 16301 zcmeIZc{r5s`#(IPC|l|sm25@c5wbIky=31hYf4#%Fk={ol%=wjH9Il(Az?5Kl~4&| z9otaZW(+f7nC#Ep=kpxL^ZVm_9N#~le}9f+j=ASvuKT*q<#oQ!^Sr#UG&kfvb@3Dk z1mZTjZD0)o9b*8WUmPcZGs1VZxPULVU_B#S4&X0>!{a&d`vUCd9hgnPBN)Ox=po3{ zKLGkrCip?n!-xLCUI8#VYo`_nBnmPz(6tTCTO)&$G_lK-U9r_2~-mX~*) z>*#q{eLP+%=;NF5(utHco>?U`_7;0C%Lj_#k8-TGcA_T#`!9>$9X4G9{%6-Gjr@a% zlY{h>?3tNdjlS%LLdClBlrR0?)#o-Lo=XMHh>qp(t38xK%`qi2o3d-%yaGy^cPy`_ zWpe2Qb8$8uvBfx!jKZu&MkI{NxVkK>_-2PwW4pdBHyD?t8edJ*WeR{mjrVe_@vb&1 zx%OIFV`TChpDmm<+WMw+rku6AXt{?%r4PEyxb^B+F5Dmp^y6M!`i(Qd)87Q%R}teI z!v`y@pRtB52Hm}&U@MjRjCK_SB7aWzsj9TEzLsx(EvxU}!a-?e%P&&drWMY$CrCFz zAi}et)+$?YrL%0cEjZsAW1r=%@R*~2u}3@F;awdrzqSNtSj!d;>4?d7{W_q!LpecDD&!wZ zjs3CCrbTNhyA1!CC>_x7X&unoI4#t4@3#JAX^)9AL=#+FsD;xfLT77#zCN}XJXs4( zN;325xAJX7j=gq#cki`AcH+0i_qPn0WM+z1Re$Gn4PW6j3rO^(=}3CuQ0$=m*%t=A z$0e_pDT~`gHMnE!1*{dMAAYS-^@-?ul^BxPt}HKKDd_*Fm1_*;%}F*a^RBY41jKhj`{l!&DQs}zN)s+q zM$jId@p3x^Br-;YUywt(FY6S_W-3`?R%`~r=Fgf^ZK;pLofOdP2Dj*cCZFY)muK`n zTxznbHX4i^XjP!X$9$T$%_Pzk&cxLo3~d>gb6HG3MRni58{S)HTWOnd`@C^^n&Sde-H);W`mY^x%V_kq{M-M)A|7L}9cvsN{OPU4)(ynP;vmfz%z*PJOiw5rRU zY6>@%cDU})s)>#%PA)!ND3H(Svm5h)8(Cj=|2NIt`<`f>-s~ix%A6@ha3ycYkzC{B zpDZXc{m5$UTjQ{|ulwEt4V9B4E1hrd-7Utstm#l`+XU^c5ci%O<})+Tga)v4R3q`T zVP8l}W@d>ND=!s^6*uq>TRg?Bb2+7%KsrdmzCoR-nC;e`1AzjX%O+zy3B^e1$0V9J^kqw!$7ifPRN6l>J=O3aLs|Ep6 zUy&q|isYiUd>u_IG_31XSs2m|DDxKvdI6|qx2i{(8RkugQ_H0Ao~<~d+uNpIk?N1p z$0X8DCZ$+-ZPG=?;KU>6PW(}1QXrXj{P5vPvSWjBY9n$>io~RbXZVa1P8Q54 zmNg$t3c{x<%f0%>p-5(7r<-(^T&lR8w4H=?7;2O1V3aC*^jq7fH#r}RWsS-94rz@8 z{9v?a@frBCl`Rw}Zj@7-jr6OknvWY+?1S8J9pZ~k-}u_|BFye;bpy{ea&rCKjo2Ae zr+A@|H}5BFzCHAvyX{atmOi)$n<$o6#(5%ov9+Ct<XEyiA1Q?oS9+`0Pir(wLXHs!EO zQduF-;qnl8v{$kW{&8o}s#g8Teg3W|nR;{}V^^&#k;Z;2v!|y_$wjK#5o()K>7mz` znd}u2f!mrtJCc(pRq0x75|`dzs;r=J>Y*1KVXv>46=Ir{WZ~;mHS?!-(N<6YS=hM^_NCy}NsVG-G>O_rb))GDIHV{nsKUO{JUncK~el#hoK0{ zbnb9~7f!6B4b{>2F!r@~YAsyCV)?J1ANm1UX3?8t;yAtu8he-w7qi5kCg9pZ#9Y^}y zysG9a59V!ly9Dr-lKHTwnb+@@I;&J;oSLbqr~?FYtXs~1=TDy-^0i6m!rL?xskdk zRAF5F#zm4wG0|<;Q3(GigI~t6)I*^-UU;@9H>%!95b&F^>g3VS3#AJF)tiOp!&GD_vpN#jrifN;D7y=-A z@zN#2t|E~#J-1UEH^Q3pM#|^l0#)2dbv861sI{@@YT2@%Cu~sG%rtXKc+eRAmf5if z1@CxEQo^-c>>Z*uqm>`Wy;D7z-H?LfvH+E&|PjP2~?%&S~;?D0yN2XWTBKX&Kg-OuKC zJ9~Toe&bdX=V9M1eI8{a1Ffrv?d*J;)S>52?L3mOZrCrkt^}grT$7B^MIoVlrlEB& z_RoW(!B59ocgGPO)oasOFG}k1D%|Oj?=FQ~)hKmf z>Tz6IxwOo5VUEt?P5W*zx;Z1qyYJLb{(tgHArrGiGFFWu|;vL|8?5P zy8h1a%X58OJtl4?=lUF~Y-_#dIQhj^$&n zbm@Ov7A!eoL7Od!aj$Tthxqv-=fdY|OOhQikdhLBFjPq-2>AN>MY!(S*xZCHw>NAJ zGsTlCjIn5wHvBkge28DDI>?I9mw_;2xs~UXx=YfP#uW)esx5by^HLhrb%f;(2PC_FWtneGZ zvO*$IQ+Us3hxtnujYp*yJ1f^}i%nv`rLQbfSa~xOz_pg+)fSqzh4{Td7vyj;*d1Bz zV-p-D#{Rtrjyr(n_Pc%X+4}HeVcaRex7Ec6xuj^3yQ7|Oj)0mBn@U8!n@kaz;m^Au z{2gG-z7g+Bd7ZaaF2og6YmZvXu1Y!z-|u>LDmIbUMsEf)R~s5bhdwP4!d$>!FK0g6 zS`DHGCR0nPQ6Xu<$j}BXbh`GObfzz+=TK|19ErGnpdi zqEK2Fu_d^hB8Rf$6iD>C_gLrX&rn~}%9ktYgUbLBRd1M`i((ib_-{Ts=--2LzH^NB&A~Krmz}RsLuJ!Zm09=&J^VgeK$)nN@zrAsxM%}lZTR7@XH)Ot zxdp+qlgKV~)Z1mZ-+l)p8AqDsDGm{!@3fx?4C~!F#wB4*zx1 zcZ+>c?Jh5b@k(LR**X#=eY~6S<_(lPnv_%#-v>j z<5NrJP&>Z6v%Ix-m)*VA-@0>ic`P#mMGHsZ#JM8Qg78`(B-G3&LvH1&28?sMg~o|f zKE_9uuT3MoCWn89?KK=V`5`o;Hgosj%PvfEDzUvPY>fnX(Iq(}$Ck&@nKDjQ4^q^P zQ(;6B)5pu}T{+QnJ3QFq&1?OMvBirx_wyI)#+Bb6@i&!)BWPm|*hFfQq)2fci5Zi8 z=kACN`%+Csy^qU_&(Q(Jid_2L_l@ELf7AyLsFy>DJw4m~H4d0e99F`+%vyWmu-B>S zxTjAO&iEWYr2KRl+&2$D}oWCn<}pSa{Ix zQ88anY7NdRn0Rj&FNCu$JYZ;(1)68d0#JKDXO`qA%R#|}S( zIQI(w90esNLM=m~@nN4mgz@{4P%z^nbmnoKaOiJ$jP`tXYN^P|*<>chp7r!C`se`$1?zuf7#4MBwpF5geXlH9PZRk^G{0-ug z-@p@5jih?)rEr}dX_W{r>hTFnw zFa`?`p5BTJN=@8RF1R*Ul_a)dV;)&0?!7!9=}EJGbC6?dma+9opg_Xt+w$h_l!KOb zdF9!Hpmu&4*SE$GeOx;)u6-}`@XWEUw;i*w02|3gQ4*9O5R9DbR$)$F&Umitk>f)J z3RaOOozdfEDV5=q%p=s&4%8J6itx(Z{nu^kh+CL|qk99JX*M=e3yL{!uJ?z{+~CT{ zoi-LvOARZ^_joT~`Q5y2ld0>I_;Piw)?=J|jJsh`{tX^6w?k9L(RKyJjU=_##DNGu zTj^P_&Az+g&{1qxolFk(V?XhJ_rqMI0brG3;N?7S?^C*x0 zboEVLf*((9)9#kgzYBl43FS=*k({V#J`x}jdb_Jj|DuQp5g=~Gu~&97JDK*$o_JYO zWUmXD@#!3xo|oi^^?T8=opdy0;ucYC9=Y-Y`E6<*NM_)GZx7f~@$FiBa}9Y}_p-dJ zf@2HJ%V8t4RRxjHuPN)V|1Q>b>7YHv6wJI`S$LBya(;Y~YVW%<+xsw6@}hJZ7pZa3 z5}cpotpTLJd&&8ZHfrzZA@l4eSJS5IAC#l9G#r(d3H`1mCOpHxI^7mvOpln(1!%Px zZhoK*z9^|J+4U+U#Xfy-pwnJm{;uuSTw=9sOH zQdKQkID^@!@$EM>RjK#8oxrWXiZ)HrhQXN%>3S z(!7ncTsL~Zc?@rkd)KNN>ct61-LD2pOj?D+zt0Oa&z1ph-+%qV`M846`+eVur&E%W zDD1?2gVe@*9tLH19mERrMcUarWq6T=xJmz3YpY6I0HlXr8(yk4YbF%~zIeQg)G5{K zukti%^1Vdx?)cioI5mz-e|NC%pt)ncKY;R*7w=Y`tf^O?x32`*p2$?64sCBO+;KKv z&Tq5QZl#?7LT4;zT)Od_%_T1ng=?fBst~eYq*D)2@9v1n;q6q$Jk{S44F8cye0Ep8 z0DzWeKb*dR%OB1BgPN_>(rN!rlU@--&3OJc7eFXUfy<;S`#!8IKqc>fsCpDTt3_zY zPWQi{%6RInU!7X!F`jYF%xi4c&^Fhf%VfOgR#TO=J>E9`Zk^FBy%bXkSf7WrzCOG8 z=%lG}xS^qPJ**zcr_nmfT>3UPBNv58r(2Mp}m>U486)ajjEZa<~b#^SX& z=5B*=;o)b)M+I%`Jx+|dqrJ84&dy)I1gO8VTuMi40v7-3f9pWRwfg7B?|H-$+p3lH za&0?(ef=t1DJ0V^;@;936TJUQirbC?p8SckF|dn*+s!>vt#jL3zSD@*%rIRkURvGz zTZ>4ETGa=fW$rsP(Ed%FlDvGaVB{eu#CJX$*_Z29-rT+e-^|R-%Oj*j?%TNho(YD3 z^>sx%xbB~^tG46j;UUwtk!az`_STzJc4&3?1OKL6qjE-dcqC@T9CDM6?9FXL(6xY? z6n+zu<-PvtBbItNB<)ru;KqpH=HmHx?vj1y^6Z=!lSXn$S$qG`Wb0?&k)s9zQc0n_ zO;+2#VKh7ronD4|-jC2D9x-nH4N!Q>R^6Dd+rg*uZ+|N`hW0UQTAA7V;+xh_b&D$w zRIE&)-@caHcUxikpYyGLw>tMoSHQb(O44tD-Q;|nrK_ok&hS$8^~zwUHUu3@;$OXs z^`m?rOyD2DM}<7D;N#E;Ssi`9geNN-g)?a*ONPQ@+^VxR)AT>+IQHOv;;#>!*4OP| z<8eLgjc%mi!m5n-{BnM#!xiHzIEp~?%1r^+A_)_I-?jB#a>tzJW6QxQe7PCg#s~sr z#k(`hb;Gf8YHrf@m)`30x)h`KdKiDsI@wizKT3|VhjQ~SG3ahB#+^|N`Fz+fN3`{| z#mz9G@b6YR1qJqcad7~^4j$ngr?G2<Ug#CVi+5TkT zCbR8+Pqg}|Wu@Bq>RB-5^I0X!f4yL^#xNrv+6GXual-nIrFL^F->@Wn(9s3xOv?VD zJis#K02@BM&B^}{PI%hZ=XMI@Fb2r`#U8wFMD3X${J|Ac96E8Hu17(W=^c!WI&XRh zYU0L zo`yjPpuN^C<8#~&<&5O+dB?P>RkytlEd4)Q`^OTsn!+s~P}<*TkGmbeD`jU}O@vRl z$4lk*55N|5Y;Fa&zAp&sfN^$}9y6O3`}rCby)55gK3mK=a z->-j5u?|}rZw7J}TZQ6}(KTmYd~V+=EAPw6lf4EMUPJ$_Lt<+E+${m-Y~SQ)2hJa7 zmkm!Tc)zWNI#>yyuxszXKDE>HMZeN^3|6VRnNdmcu#Syhjh3rd_i}nLKO*H&CH2pH zDW%SPkG8QAlRnLM8h?wSX%ZRIb^z9TTrNI-B{+o{Ie#`OaxF?muum{a?$cLK52a-p z7#Q1xQ&LyQ_+Vs#D);U4-#ir+5z^nI@TO*Fs{UQoL_z37Ya?zRY$3P53VlS?%%;`P z@fqu879>=|KDk^RNaK{1U982jtcnTeg=QdNpjf_?=ra+90!glH;SzzG2|<~F?)lng zEk$Yko^C$K-*nYx=#>?*C7VG1=1sExPT4lrrTCRmwL>f`$8BXZ?Ed{nNlmFDLaW^1 zawQU9R!Mn#wMSA3qKr0GS@U&zV)x+e2yPWcA6oAf!ql&yJa;N=F<9M9AOX4DCTD|j z%-J*x0sTPtAX=UFnFO2480*SB+V%1#@B8m|xS>he&1>dm|Pt&F>tV0wsH z+DvQpL#G|RaV8d2eI~9rUjyOYz3~ueFc^&a*f9@xBV7*qk8CP6(Wc<;J?fw0wDIpLj#)cRL$n#;^?fM`-dF_`jjGu0D2u}s$U_crl#)Hl5br;2fX!2Q_9<5_+4r7(qPJosVluLalmNWBR(;I zUR^{(?X0y3!s@sFzCpStp4%H;s;hjpn_DT$RrZ2NBFzuMA_OA1VT~NiZao*si8?Xb zQXu^EYamxEFylTwVRtZG0<*uV1rnG7~z?! z$x`-ElEGgY9(mh6F|7Ny@Y!EcivY`ba$b~h4D|fie-59!7X^#pI8~q%gzZ+i>MZ$z z#goGi^h=i#+>30AfyG&HvF4v5J&5C5M{u0hYp!(@feD<3%X7hiu|fBr0GF0Jk8bWs zCS@N{{bnx0?niI*gT{jdaqkhy+Q61$49I^624*XI;{JK^{`_^>DeYsm^EdYL&OJID{1hZ4 z@{aM3K5cDkjVZ?Dv6vDHYHspxTf+u?3H`b!VU*WHke>I~2k#WI(=)%PmF&5`)dN;u zc;24O_SXzflR?e`Bt9)s90!acGJFE`_Q`)FBLx$!*@cT2yDKHvG`HuDO>`!4B}(7Tu7WQ%s1jwJ_-tz<2%PzMCk;DCKNrR51) zKhq_~v?T~V5h}ZUG{E|#=t98c(KB%y+)+a`d~q$V*g|99f%PN|*1OEk_EJ@J=HdB( zOoptHy3qNGS`*(n3H^Xf@5lkBmXIWc&ZXZbeoh?q{Z`9avd%v@#pd4<3>iXQq1B~g z%AX?cSUV=E`rI9UQ<}~-k5T9!{4-UTCb5>LBtXGYP{Z|s%rP6M22}x1Z zQ+brl{GC`eho}+!hG|Z%;nP1;*&3&%X-ec9m^u$KzToh4% z>0`@0a}HTp91+V6>4b(Biq%M^8c%80%(fV#qBdJGsbx8XSxTy_c!#{PhPS1ZM*&xJ zAwmuhCJwBWYnubo8K>fAjv4TZocWRG9cdo7F06bx*ft4_sJlq7d$IK3rjatKE@~`b zkzU$z;I1{c-w@Ta7oyB^c-!dcd#T!=xXoJbOG+QKC6qt4Rk1c#Wdk7bV9HHeg#O#a z6$x)}_cBdN5eOGwOKsFoDmvn5#%xt~48(QJ?mYe_q5I{{l4ni>sk&dgq2o@O`h?JD zfxdm?BuQd=$ zR~4rZRy6bck4N)xs#P1Gnsa|QQkYDQfwCV9IDX*=d+^1jGe=VwH6Jp$zd`SS2+}M< zA77aH_dYUoUg(zpsm7Xrnr!v4_4@-W?GM6C?Ui_TGAkRn=HzY+ZEPDqBj?sBBio}U z`$U2b>CyT)GlBX-p?2?_UAyoTIS!cUKer*EfzxE2PRgH2u~m`lpJug1)!2}P2yN}| zgP8No1C84i2-VSi*8A}~@q51_gi|&<;Aa;)n45v@*Dn+1pQpJMo?7P=`Bi%?P`9Y- za_8U|UGXPrQ0(0-C!*#DT^2_%0)BWzU2;IOLUxZo&V^TB7d_v`O` zA{s*7*)*{={?q)xyys&snn!lX3Oi?je({kd^lIo(Mn8KstR7(WU zlX$?#m1SeSR~06^g8F(pI>UcQE`BMIy8ggM*J&g%sWL2B6fIZi|ipUBIa z;^?ah(4Jhq?X}A*`Y#*OIV|XD^RyQm?WQ5@cjPh0%LG1|`c457xBJZcjqQ`q1z1QX zf&18&=dh7rSCM$jOP(oUzLzN0U-3GIrpGfb%A(5K+%$17f3+4h^TwQx7FOOg_n1kb zbrkX5c9!gk?RchB%18cfJ~}XGMGY{lpSl3zKTSqSOG)lmFcfR`BDBE)-1mS*UcVe1 zbm}9<_dsEURM%m+bN<*H-JnuX}gzxI=9zsd; z&_r{_M_HE0%LM&cMd#4ZKbs!=ifH1Jc|O>&;fU>OKX0PV zwP|2+fNf1HYosV@d+#xD&5$;xipG}2^}6GP`Bff+i|25je(5r`Ei29Fjg2mbj{&#DzFZu1^hEPq?oe1AtCdbH zjor;(F=3+<$NxCY(|2>+VWq=^DzT)!(iM1WvJ=et0nCD@t3%SJlB5x>ZQKH#h}nS+ ztHpKpE1-P&h2-RMynomC!5#^bq2-R2%Jty3bDC{iHN8LYawbe)_?`4kbp0S|J0SHU z3bj^k{z^Q1u4N`R6QaptrQV`*+p0L;EWP9SK!6MLN}`5OgGGqF;`Cwn9+Z{iQZ((_ zKq5C@gq@!3oSWI2Oyh|oMSnO=ev=UFYol3P65eo^7ZJx4xhEJcY|KCCQ>?zzDlb2< zGw=tl79kk$7&U>9KcT-l%X05rG)=(G{8fnRuONf1;k>M)TP?BOCD~45^rjJa<}14J zX?r&C+wP1PfyZ17nnXk24fm@NR68hukBd)v}PMBiNl1R^MsZfq$??3*SP8 zDmEM~$pRJiG>D@Atgcs{jX0!#(DAdHJNlg{VejO!kwX|l zh*aXv6sqO7qhPMd%gnU4AOrZW$$s_)=Sv8)E;y zAt~~cjGs;&2g9;q@7z1#WK53Gkx!=}R&P}9XXT^4pa~%W&v0|QhYS4Oa&No`+ah4z zbypy(<{3PUr#f`i*J|>&w!paF=4Us5HThoohGM_`REM{r$l|FmbT0oFfHhy}9$R4WX(eq2%3#V}yUmeAWPhKMJ1S)&o&2~tA8*`kyAoe!U0Xq$c< zO>eFXQ&^ovsw;4R@MFW(y;YE}UFJUCBGeh+792GJN&UDA3%Ug86wCtoSGO?n>1;=? z3&+O}wKIM02vFn|!jQ{ET}k*8cLe7rK>h%#80y{`bgOSm7Or@V=51m0HKh^b}c;Mde(@x8t72nS%W*M>#x z*Nm61IGtS+O8KfmFXSWuI!7>>3SC6rvQk%aUf0Kn$``q$5e7PU*lMJaq_ zl-LY$s4HU6@lPBn{O*_$J%8r#(Su`Jrl4d#vg>1HP%y5*r1^PkS3=Q!Ks(UgcuV$n zgQ70D&|sfTA!E~2*uaPJbwQ2g0>?km!i{QqY^X{01mYKc^;KHe_V*BK+#2_-44%+f zos=`3Y2Cv}VK+m1mpj5&+8U5Rf=)`_d1pi3{Zf&5cLc&=O8}7GaTbzvfmtHwwchNt zUl{Me^C7%o;0W55 zaG-GESn zrSQxt=~}$n^l8vBJxx9+$|Ah@{Vx1XJd<_0BG(RQQ``mveddf7_C|$nYvf)Hpl4rxRpTv`%Sr z!13`U{S5Q_toX}>D}%u4x1n$04TG}g$qj*=xgu?6?&-gtxDH?((#wFl`VYpPNlQ4c z`DAFs@n`ig-cj4J^Q;bm1J)U{k*O4A@uprRgx>sj2BNkcjEc>*oVKJmJ-94QOTBhX z3ZnJXe6tp_7??pjp(pg1J6f1itKj$dOzjX?!is_`Z<~{k#1kn}Pe}g06NN{WkGNlniV1wFeq)W z;$d7S-!Ng*`8yeFG8;}Q$EZ%j<*V6?o1Z<*N&Puq58nXqY-_Er^|KiO1laEnWYz!S zlc_<#C&z=LtGiC;J3QX2UtsIRG;b0J6{5;ub{D?Uo^Q`BSmbz@k1-jJ*Bs+m8 zn%1oI2#s)3AtVg(@2IK|_&d>NK8^43yP#e;1Jd!kq7+~Z2m&_97C8K3^IaR>EY$6T zHM%+A)1&Yh@IB6Go~Tgu)!9vJQaov`=jJ^-4s}SrG@yrH;g<_LcQh^2za2Vytl2@W(HH^P?-V|xX&S1V_F*5F}}Kq+P#&=%=??J zt`_W~d}J~H*Y1dhku?5k|7O#=E*eC83~v!4`)ttZdMa@ke;z5Be@u>#tb4L+%~y8Q z|7~tQd{w-z3(HbB3<+J&SNXaH`=H8(TfQH;=UC@V$(c)=UsYa+%9wTTUlW2Wj{@>* z2VBkZOB_i9`*ZnSczot6mz@(Xwtvnb&=K86bduZ71)xW#h`rJ+o`iXblBMP34lmb*0d0C1S3n%%pe&7O-ul{^UbKo(R zCx9b<5191lMN&)p3P0%aJ(cCg5BgsDM}ysfKRTK96Y?vbx*_XOTx(Ae;-}UJEai!` zU)-ey-n{ztSTPV;;?mri?+V08IXa$E*P?3CZ4T)04P!7joY*Wf&Xhjw&xXsoABdms zb7zkCw`%ocmQVB(>?y%S&ab&WX;g~Xq^hVM2W;;6%p|g)>}0RE`r-wwz)D^bAD{@sL6 z;O#PKYYQ#4oH13#%~P&&b~wz{{0C&A=i)3RUYWt0$-`g5JD6SlQY16`YQ|1=D;Cu^ zh*M*jSFpa;FEX@#(nZ4;c(~LJW3C5a1IkQ{R%>o2J7x%XQz-ut4$ieTLD4IQGJQGo89MGCKcXq*#8y_A4AvIXCzY~e3m8)^L4f=kg1I7^Y zX{$tVLkd4nXiIzclYzv|t1PLq-;-s53`blHVIHup)M#PbGcm6pRj1*dPua9}eJ{R< zENoIJ<_V1h$kw~UMkKdjT{T0ck3H~w_(We=U#p64?HHkL^l)LBrG;vwdk=9LPN#Q$BLwuf-R`n6H8EHNz0FzYKG@{A7@e zKyZ-GCnW~YJs`Ua(T!;=DVte+*Jg(!dBe=BU;&a}?p{JR$6B(#1t#+}tBdApo*dkC zQdM#>%!4zZhZu-{)!b?a*zL41ajFjN`k#upTCn*e8XuXN>{>;D{DJ zS9~!fpz~?@vWIpRL-y;1Q8smE799@P6XMWdA)Ph%zxHxuK}}kW@IIue)5wJL4rUmC zda)P*Tvr70-d&t=GxB{iZi}Zc%oQE3{@1<^Uh1Ue7hN5n^t=2{ij?sE_vP4j9!p-p zU_}2Syz(k7QZYp3p5vXK?QK0Lw9_<R1Lja_xA7>3FaIR&P-L0A2~Wo`4uI3zrcZI{StL1s{Vx2N{t69Zn_K^5J;S%|i0^w-+}j!Yhptfw4UOq0VT8*WkgM z-=1XB#z;XtjwE&xWPY055vZ_A`?Ue_dKuQ5iv&l8BPNA%A2Y{8hSzMj#i_x(ZZxr0Havs{j zGl#DT&f{st%n&H!{i}YaKrv4YV8rbB0{j&_G_&Ph{*!h1Qy?81L2+))s@xCf1LgCP zBLf$wLIF&_s~keEVmvl`6};=Sb;$p??0N~cy2B`a8F;xSvwuw$)y;&Ne1l`oBCiCgTRei6x*@AVt<81#UE=>eQ-J_)K%QYDzx(e-l^F4VOo%9sVlBcb}DQj z+AjBS%@dCyBnM<5c{!~ytTI-`?C7~Fn8l;jJ*CYyY8h(c@hds_gcO{e1p1Yz!<%R5 zS?0<*WUo5YD%RJqgj%#e9SbWz2^VDm9P4IgfKzV6Fd$uLY`mm%M=WNm3R0^Sur5p8 zy8#rdfzrim5BCcEd|8(&Lo48Bx&D~{%j{6eZwK_nds>erD^!9_9~(;V)Rs^Z6W5 za#7>26@xA}K6OezF$5wx zn>AbmzqGQ6qPQ1`3S?|u!UzsqmOHZhi4pWAKS^HGj;kuU!4Uqu#ZZgIaaOY)JlA2K zvBOal_N4WQBjGcqedhqd0i3{sF_gIVtW`l*_PQO8RoB@9(Re{m=s6g0f7D$x^Gn0Y zAoq(%L^y=k?L2TEfEY#js$nSV3y0N_5a;|BOl};$^K7Oa#q@oDiBQM^(>A~xGxaN~ zVX8M5kT|EA4#w#}RQ4DFpwI*8w%Og`hd!O}B)r*`S5N3SfP(gc6~hN_#AsA6eGqXZ zUqyJ?QgR|%9YAVzi2MoEco5QMEJ+Gts!!*sW1aTyrNr|CQ4!<2;%}bGdV@V$Sh4`f z!D7RnI{z38iP0lj39jXGt%b8b7X{Ezr5YAI%R7Lj_w06{INmXe7R$r$d~wt$ZZDX9 zSZo;&{>Y9xaUkqEe}JTg`|pdMaQo=3t_1g*BTQbu*B)4 zl-#hVgs3ds&7fT-KAlW@FyFh|5Z6oMg4b5F0-1Toslbd`-?3$f4B8}EtfgSKO2$Ee zxzUx`zWNr_Ea(c#HlO{x1q&B^92o2xkDE?nT?gX4>@7RoT7P^f z8S)Q+YFH+F(TfKZ)G#rgF~2nGFrG)wCbZjwb%P; z9;qk4UAAD*74hExvmX8-5Q+YhDGreU#3^`&@JKP!axfyrq~h%AhmRbLqHeS?@8*uO zPcg0ZtotdrMf{Jkm19M9eB|hpVHv^zeXyEWYWZ|#C3%`Mqx7T|px1v?uG3(@(gi(x zL07+off>T%REiZBoHzc*$&h=(ED%dAKt2~wQQ6cxRrM=0eppq6k6k_O&W8MvSMWQ} zp5p)f3!8dhu6Ogq*Dwo0eZ|UR);tCjU6Q# z>s~B0S68m;aCLNXAJ0=H1k{^R4(RxYWJnCPRgAw_tC|l;Qi1YclWW(F8ateuq?>m9 zY)J?Nzlg=3g4ao!1i1)32I`0G#kj-Oo+fKS>FvHPSQhR_sIIC$scHMkAs}|KL_1u* zN<{wZ(#VAlk-Bnbqj46Kl{gkn5G8a~5z}(j>FmtrpPpUCg2;e+(PIDb5vZU$hw!^3 z9cF@)q(zE-)66TkvkR-WWD22e+U)EKR8VX*x`2=D&JPGOnin5F!SnYi%zvJGro*&x zu7YV#b1WuC@amDq#!7@&8ZO=k229jp#w2(a=~OecE+Luo`dI?~u`;8TPt3_^TK020ihID7bm9ofAM8`?@9yrPpYJ0?jsaL*9gwbG z{c>FC*(42{*M6&*YfD&g&HG$u+z(G^f{)OfcpYYX!WgtDtxHoaxF?K^FNaSzE+Z?N zQG{C>DgunRj_fyp`8wyGO{rThIc@%`A;FSfc`|`_%By$jX>AAnB>bKV3*<~h?QoYC zgNFF`&rbB>kL}ABRw8*mvQDJvFk=(!kPDJuTE|L>Y53Jz-;n)k47Z`|sEjON*tI}G zFX`P+GHgACcS$5V^6|AD6`=LSZas$o0FaN>00(H9kzdjF8=m-)xEU- zfJ2x=hy}tGfxjh~snQ-WoVIpc#i({t=Z+qJd8}gm7+}U7LF;~(Lc4|5iIv(RGjePgw1`q!1%D@x_dt>asMK1GCpCacWH7o0Etpzdiqakg_Bb>pp0)f%+lP>#{a(!>^jY+uAEyIya;E)1{h;ccVEONgm{&dcc{;l zXK&%^+9@Wg%_x78geR6}(+hPRyYJq%2W~so3%%r3)yK*+73A)&Kg9^p_63>^f&r@! zOMYAR220fCKCmUbZo+QQ{A^lo;lbNfYWV->_7&`nvrC{hYh8pWEwMTBGFi4L$%$AO zu$Q-vOWBz?%cz?7^=whLJ=P3Il73tQHU)s>fzE+^*}pLk<wzqmB{|WDuZ+^EB?Q2 z6aU8!ivN4~-<>4?s~m2ajwn5&8H_@w-W9I}Q~leAdJ90H-E;qSivLme|JBG0_5|P> omj9cg{%7_5|3CZt=$KE~%NIE}Wmtg!w+9*BG&iW#yZ7|}0Z?l3+yDRo From 59085d2ac0b0b0b5cb426f11fcb0d722fb8968ea Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Tue, 28 Jun 2022 10:11:14 +0300 Subject: [PATCH 054/105] dded stats --- .../examples/Arrangement_on_surface_2/draw_arr.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/draw_arr.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/draw_arr.cpp index d43858da296..6d6874f872a 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/draw_arr.cpp +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/draw_arr.cpp @@ -29,6 +29,10 @@ int main() { CGAL::insert(arr, ctr_xcv(Point(0,0), Point(0,-3))); + std::cout << arr.number_of_vertices() << ", " + << arr.number_of_edges() << ", " + << arr.number_of_faces() << std::endl; + CGAL::draw(arr); return EXIT_SUCCESS; From a480de297beeda3d48d14d687779f6df5746e387 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Tue, 28 Jun 2022 10:11:38 +0300 Subject: [PATCH 055/105] dded a subsection that describes how arrangements can be visualized --- .../Arrangement_on_surface_2.txt | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Arrangement_on_surface_2.txt b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Arrangement_on_surface_2.txt index 29a714186dc..d563c1bf036 100644 --- a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Arrangement_on_surface_2.txt +++ b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Arrangement_on_surface_2.txt @@ -6597,7 +6597,7 @@ member functions when operating on an arrangement-with-history object. \cgalExample{Arrangement_on_surface_2/edge_manipulation_curve_history.cpp} -\section aos_sec-io Input/Output Streams +\section aos_sec-io Input/Output Streams and Visualization In some cases, one would like to save an arrangement object @@ -6742,6 +6742,24 @@ arrangement formatter class (see Section \ref arr_ssecarr_io_aux_data) and defines a simple textual input/output format. \cgalAdvancedEnd + +\subsection arr_ssecarr_io_vis Drawing an Arrangement + + +An arrangement data structure can be visualized by calling the \link PkgArrangementOnSurface2Draw CGAL::draw() \endlink function as shown in the following example. This function opens a new window showing the given arrangement. A call to this function is blocking; that is, the program continues execution only after the user closes the window. + +\cgalExample{Arrangement_on_surface_2/draw_arr.cpp} + +This function requires `CGAL_Qt5`, and is only available if the macro `CGAL_USE_BASIC_VIEWER` is defined. +Linking with the cmake target `CGAL::CGAL_Basic_viewer` will link with `CGAL_Qt5` and add the definition `CGAL_USE_BASIC_VIEWER`. + +\cgalFigureBegin{aos_fig-draw_arr,draw_arr.png} +A snapshot of the window created by the program +\ref Arrangement_on_surface_2/draw_arr.cpp. The constructed arrangement consists +of 14 vertices, 15 edges, and 3 faces. Notice that the colors are generated at random. +\cgalFigureEnd + + \section aos_sec-bgl Adapting to Boost Graphs From b299d6a6f6408248a19b5c94a3dcf28d40088289 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Tue, 28 Jun 2022 10:36:57 +0300 Subject: [PATCH 056/105] Small fix --- Installation/CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index a6f9737ddb0..32629d30285 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -70,7 +70,7 @@ Release date: June 2022 - Improved the traits class template that handles conics, namely `Arr_conic_traits_2`. This includes the following: (i) Fixed a couple of bugs and slightly optimized some functions. (ii) Introduced functionality that approximates conics with polylines. (This is used to draw conic curves.) - (iii) **Breaking change**: Changed the interface to generate conic curves. In the past, curves where generated directly using the constructors of the conic and x-monotone conic constructs. Now, they are constructed via function objects provided by the traits. This eliminates the constructions of temporary kernels. The old functionality is obsolete, but still supported for a limited number of versions. It depends on a static member function of the traits. In the next version this function will no longer be static, implying that the old functionality will no longer be supported. + (iii) **Breaking change**: Changed the interface to generate conic curves. In the past, curves where generated directly using the constructors of the conic and x-monotone conic constructs. Now, they are constructed via function objects provided by the traits. This eliminates the constructions of temporary kernels. The old functionality is obsolete, but still supported for a limited number of versions. It depends on a static member function of the traits. In a future version this function will no longer be static, implying that the old functionality will no longer be supported. [Release 5.4](https://github.com/CGAL/cgal/releases/tag/v5.4) From b7d0249e24f10da47c298162f8b3c3586fd19c46 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 28 Jun 2022 11:14:28 +0200 Subject: [PATCH 057/105] Fix the CHANGES.md --- Installation/CHANGES.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index bb391e895a6..4edff3ab2bd 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -6,13 +6,13 @@ Release History Release date: December 2022 -### [2D Arrangements](https://doc.cgal.org/5.5/Manual/packages.html#PkgArrangementOnSurface2) -- Fixed the intersect_2, compare_y_at_x_right, and compare_y_at_x_left function objects of the traits class template that handles geodesic arcs on sphere and applied a small syntactical fix to the tracing traits. +### [2D Arrangements](https://doc.cgal.org/5.6/Manual/packages.html#PkgArrangementOnSurface2) +- Fixed the `intersect_2`, `compare_y_at_x_right`, and `compare_y_at_x_left` function objects of the traits class template that handles geodesic arcs on sphere and applied a small syntactical fix to the tracing traits. - Introduced a function template, namely, `draw_arrangement(arr)`, that renders arrangements based on the `Basic_viewer_qt` class template. At this point only 2D arrangements on the plane induced by (i) segments and (ii) conics are supported. - Improved the traits class template that handles conics, namely `Arr_conic_traits_2`. This includes the following: - (i) Fixed a couple of bugs and slightly optimized some functions. - (ii) Introduced functionality that approximates conics with polylines. (This is used to draw conic curves.) - (iii) **Breaking change**: Changed the interface to generate conic curves. In the past, curves where generated directly using the constructors of the conic and x-monotone conic constructs. Now, they are constructed via function objects provided by the traits. This eliminates the constructions of temporary kernels. The old functionality is obsolete, but still supported for a limited number of versions. It depends on a static member function of the traits. In a future version this function will no longer be static, implying that the old functionality will no longer be supported. + 1. Fixed a couple of bugs and slightly optimized some functions. + 2. Introduced functionality that approximates conics with polylines. (This is used to draw conic curves.) + 3. **Breaking change**: Changed the interface to generate conic curves. In the past, curves where generated directly using the constructors of the conic and x-monotone conic constructs. Now, they are constructed via function objects provided by the traits. This eliminates the constructions of temporary kernels. The old functionality is obsolete, but still supported for a limited number of versions. It depends on a static member function of the traits. In a future version this function will no longer be static, implying that the old functionality will no longer be supported. From c92d65efbe975d264808c6faa3db073e331c4327 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 13 Jul 2022 02:26:32 +0300 Subject: [PATCH 058/105] Fixed the drawing of non-linear curves based on the correct pixel/GLuint ratio. --- .../include/CGAL/draw_arrangement_2.h | 55 ++++++++++++++++--- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h index ed72186a417..b011a3ae528 100644 --- a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h +++ b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h @@ -45,6 +45,10 @@ class Arr_2_basic_viewer_qt : public Basic_viewer_qt { typedef typename Arr::Ccb_halfedge_const_circulator Ccb_halfedge_const_circulator; + // typedef double Approximate_number_type; + // typedef CGAL::Cartesian Approximate_kernel; + // typedef Approximate_kernel::Point_2 Approximate_point_2; + public: /// Construct the viewer. /// @param arr the arrangement to view @@ -55,16 +59,45 @@ public: Base(parent, title, true, true, true, false, false), m_arr(arr), m_uni(0, 255) - {} + { + // mimic the computation of Camera::pixelGLRatio() + auto bbox = bounding_box(); + CGAL::qglviewer::Vec minv(bbox.xmin(), bbox.ymin(), 0); + CGAL::qglviewer::Vec maxv(bbox.xmax(), bbox.ymax(), 0); + auto diameter = (maxv - minv).norm(); + m_pixel_ratio = diameter / m_height; + } + /*! Intercept the resizing of the window. + */ virtual void resizeGL(int width, int height) { + CGAL::QGLViewer::resizeGL(width, height); m_width = width; m_height = height; - // std::cout << width << "," << height << std::endl; + CGAL::qglviewer::Vec p; + auto ratio = camera()->pixelGLRatio(p); + if (ratio != m_pixel_ratio) { + m_pixel_ratio = ratio; + add_elements(); + } + } + + //! \todo intercept the scaling of the scene and apply add_elements() + + //! Compute the bounding box + CGAL::Bbox_2 bounding_box() { + // At this point we assume that the arrangement is not open, and thus the + // bounding box is defined by the vertices. + //! The bounding box + CGAL::Bbox_2 bbox; + for (auto it = m_arr.vertices_begin(); it != m_arr.vertices_end(); ++it) + bbox += it->point().bbox(); + return bbox; } //! void add_elements() { + // std::cout << "ratio: " << this->pixel_ratio() << std::endl; clear(); m_visited.clear(); @@ -85,10 +118,12 @@ public: draw_point(it->point()); m_visited.clear(); - - // auto bb = bounding_box(); } + /*/ Obtain the pixel ratio + */ + double pixel_ratio() const { return m_pixel_ratio; } + protected: /*! Find the halfedge incident to the lexicographically smallest vertex * along the CCB, such that there is no other halfedge underneath. @@ -204,10 +239,13 @@ protected: protected: //! The window width in pixels. - int m_width; + int m_width = 500; //! The window height in pixels. - int m_height; + int m_height = 450; + + //! The ratio between pixel and opengl units (in world coordinate system). + double m_pixel_ratio = 1; //! The arrangement to draw const Arr& m_arr; @@ -289,7 +327,7 @@ public: curr = curr->twin()->next(); std::vector polyline; - double error(0.01); + double error(this->pixel_ratio()); bool l2r = curr->direction() == ARR_LEFT_TO_RIGHT; approx(std::back_inserter(polyline), error, curr->curve(), l2r); auto it = polyline.begin(); @@ -309,7 +347,7 @@ public: const auto* traits = this->m_arr.geometry_traits(); auto approx = traits->approximate_2_object(); std::vector polyline; - double error(0.01); + double error(this->pixel_ratio()); approx(std::back_inserter(polyline), error, curve); auto it = polyline.begin(); auto prev = it++; @@ -331,6 +369,7 @@ void draw(const Arrangement_2& arr, Arr_2_viewer_qt mainwindow(app.activeWindow(), arr, title); mainwindow.add_elements(); mainwindow.show(); + app.exec(); } From 6b1315b620367dbae7fe85b3e49f6c0989bea7e9 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Fri, 22 Jul 2022 13:05:17 +0300 Subject: [PATCH 059/105] Pacified some compilers, e.g., replaced specific type with 'auto'. --- .../include/CGAL/Arr_conic_traits_2.h | 8 ++++---- .../include/CGAL/Arr_geometry_traits/Conic_arc_2.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index b1cf4d5fbb3..2d243b01f35 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -2502,7 +2502,7 @@ public: } // Set the arc properties (no need to compute the orientation). - set(arc, rat_coeffs); + m_traits.set(arc, rat_coeffs); // Make sure that all midpoints are strictly between the // source and the target. @@ -3077,7 +3077,7 @@ public: // Go over the vertical tangency points and try to update the x-points. Alg_point_2 tan_ps[2]; auto n_tan_ps = m_traits.vertical_tangency_points(xcv, tan_ps); - for (int i = 0; i < n_tan_ps; ++i) { + for (auto i = 0; i < n_tan_ps; ++i) { if (CGAL::to_double(tan_ps[i].x()) < x_min) x_min = CGAL::to_double(tan_ps[i].x()); if (CGAL::to_double(tan_ps[i].x()) > x_max) @@ -3086,7 +3086,7 @@ public: // Go over the horizontal tangency points and try to update the y-points. n_tan_ps = m_traits.horizontal_tangency_points(xcv, tan_ps); - for (int i = 0; i < n_tan_ps; ++i) { + for (auto i = 0; i < n_tan_ps; ++i) { if (CGAL::to_double(tan_ps[i].y()) < y_min) y_min = CGAL::to_double(tan_ps[i].y()); if (CGAL::to_double(tan_ps[i].y()) > y_max) @@ -3461,7 +3461,7 @@ public: auto side = CGAL::sign(val); CGAL_assertion(side != ZERO); cv.set_extra_data(a, b, c, side); - const auto& target = cv.target(); + CGAL_assertion_code(const auto& target = cv.target()); CGAL_assertion(side == cv.sign_of_extra_data(target.x(), target.y())); } diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h index 4c535b52d00..9f2f4ac9887 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h @@ -1452,7 +1452,7 @@ protected: /// \name Flag manipulation functions. //@{ template - static constexpr size_t flag_mask(const T flag) { return 0x1 << flag; } + static constexpr auto flag_mask(const T flag) { return 0x1 << flag; } void reset_flags() { m_info = 0; } From 627c8d5953921db866980703fe034885a4515de6 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Sat, 23 Jul 2022 15:55:30 +0300 Subject: [PATCH 060/105] Added code to prevent blocking when running the test suite --- .../include/CGAL/draw_arrangement_2.h | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h index b011a3ae528..d9e8f7c8189 100644 --- a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h +++ b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h @@ -359,18 +359,25 @@ public: template void draw(const Arrangement_2& arr, const char* title = "2D Arrangement Basic Viewer") { - typedef GeometryTraits_2 Gt; +#if defined(CGAL_TEST_SUITE) + bool cgal_test_suite=true; +#else + bool cgal_test_suite=qEnvironmentVariableIsSet("CGAL_TEST_SUITE"); +#endif - CGAL::Qt::init_ogl_context(4,3); + if (!cgal_test_suite) { + typedef GeometryTraits_2 Gt; - int argc = 1; - const char* argv[2] = {"t2_viewer", nullptr}; - QApplication app(argc, const_cast(argv)); - Arr_2_viewer_qt mainwindow(app.activeWindow(), arr, title); - mainwindow.add_elements(); - mainwindow.show(); + CGAL::Qt::init_ogl_context(4,3); - app.exec(); + int argc = 1; + const char* argv[2] = {"t2_viewer", nullptr}; + QApplication app(argc, const_cast(argv)); + Arr_2_viewer_qt mainwindow(app.activeWindow(), arr, title); + mainwindow.add_elements(); + mainwindow.show(); + app.exec(); + } } } From 72235f65d583a658ba073472f592d01a7b494c7c Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Mon, 25 Jul 2022 00:05:09 +0300 Subject: [PATCH 061/105] Added support for drawing arrangements induced by circular arcs and (linear) segment (Arr_circle_segment_traits_) --- .../Arrangement_on_surface_2/CMakeLists.txt | 3 + .../Arrangement_on_surface_2/circles.cpp | 3 + .../circular_arcs.cpp | 3 + .../Arrangement_on_surface_2/polylines.cpp | 3 + .../CGAL/Arr_circle_segment_traits_2.h | 178 +++++++++++ .../include/CGAL/Arr_conic_traits_2.h | 78 ++--- .../include/CGAL/draw_arrangement_2.h | 293 ++++++++++++------ 7 files changed, 421 insertions(+), 140 deletions(-) diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/CMakeLists.txt b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/CMakeLists.txt index 213a2566931..3d61e7b6c81 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/CMakeLists.txt +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/CMakeLists.txt @@ -21,4 +21,7 @@ if(CGAL_Qt5_FOUND) target_link_libraries(parabolas PUBLIC CGAL::CGAL_Basic_viewer) target_link_libraries(ellipses PUBLIC CGAL::CGAL_Basic_viewer) target_link_libraries(hyperbolas PUBLIC CGAL::CGAL_Basic_viewer) + target_link_libraries(polylines PUBLIC CGAL::CGAL_Basic_viewer) + target_link_libraries(circles PUBLIC CGAL::CGAL_Basic_viewer) + target_link_libraries(circular_arcs PUBLIC CGAL::CGAL_Basic_viewer) endif() diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/circles.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/circles.cpp index 014cae1d161..f12cfb5af63 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/circles.cpp +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/circles.cpp @@ -1,6 +1,8 @@ //! \file examples/Arrangement_on_surface_2/circles.cpp // Constructing an arrangement of circles using the circle-segment traits. +#include + #include "arr_circular.h" int main() { @@ -27,5 +29,6 @@ int main() { std::cout << "The vertex with maximal degree in the arrangement is: " << "v_max = (" << v_max->point() << ") " << "with degree " << v_max->degree() << "." << std::endl; + CGAL::draw(arr); return 0; } diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/circular_arcs.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/circular_arcs.cpp index 926162f1997..11043fb5555 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/circular_arcs.cpp +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/circular_arcs.cpp @@ -1,6 +1,8 @@ //! \file examples/Arrangement_on_surface_2/circular_arc.cpp // Constructing an arrangement of various circular arcs and line segments. +#include + #include "arr_circular.h" #include "arr_print.h" @@ -56,5 +58,6 @@ int main() { Arrangement arr; insert(arr, curves.begin(), curves.end()); print_arrangement_size(arr); + CGAL::draw(arr); return 0; } diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/polylines.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/polylines.cpp index b81c2ad65fc..51fa18d82c8 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/polylines.cpp +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/polylines.cpp @@ -4,6 +4,8 @@ #include #include +#include + #include "arr_polylines.h" #include "arr_print.h" @@ -44,5 +46,6 @@ int main() { insert(arr, pi2); insert(arr, pi3); print_arrangement_size(arr); // print the arrangement size + CGAL::draw(arr); return 0; } diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h index 746ef587cac..919b3ec0548 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -378,6 +379,183 @@ public: } //@} + /// \name Functor definitions for approximations. Used by the landmarks + // point-location strategy and the drawing procedure. + //@{ + typedef double Approximate_number_type; + typedef CGAL::Cartesian Approximate_kernel; + typedef Approximate_kernel::Point_2 Approximate_point_2; + + class Approximate_2 { + protected: + using Traits = Arr_circle_segment_traits_2; + + /*! The traits (in case it has state) */ + const Traits& m_traits; + + /*! Constructor + * \param traits the traits. + */ + Approximate_2(const Traits& traits) : m_traits(traits) {} + + friend class Arr_circle_segment_traits_2; + + public: + /*! Obtain an approximation of a point coordinate. + * \param p the exact point. + * \param i the coordinate index (either 0 or 1). + * \pre i is either 0 or 1. + * \return An approximation of p's x-coordinate (if i == 0), or an + * approximation of p's y-coordinate (if i == 1). + */ + Approximate_number_type operator()(const Point_2& p, int i) const { + CGAL_precondition((i == 0) || (i == 1)); + return (i == 0) ? (CGAL::to_double(p.x())) : (CGAL::to_double(p.y())); + } + + /*! Obtain an approximation of a point. + */ + Approximate_point_2 operator()(const Point_2& p) const + { return Approximate_point_2(operator()(p, 0), operator()(p, 1)); } + + /*! Obtain an approximation of an \f$x\f$-monotone curve. + */ + template + OutputIterator operator()(const X_monotone_curve_2& xcv, double error, + OutputIterator oi, bool l2r = true) const { + if (xcv.is_linear()) return approximate_segment(xcv, oi, l2r); + return approximate_arc(xcv, error, oi, l2r);; + } + + private: + /*! Handle segments. + */ + template + OutputIterator approximate_segment(const X_monotone_curve_2& xcv, + OutputIterator oi, + bool l2r = true) const { + // std::cout << "SEGMENT\n"; + auto min_vertex = m_traits.construct_min_vertex_2_object(); + auto max_vertex = m_traits.construct_max_vertex_2_object(); + const auto& src = (l2r) ? min_vertex(xcv) : max_vertex(xcv); + const auto& trg = (l2r) ? max_vertex(xcv) : min_vertex(xcv); + auto xs = CGAL::to_double(src.x()); + auto ys = CGAL::to_double(src.y()); + auto xt = CGAL::to_double(trg.x()); + auto yt = CGAL::to_double(trg.y()); + *oi++ = Approximate_point_2(xs, ys); + *oi++ = Approximate_point_2(xt, yt); + return oi; + } + + template + OutputIterator add_points(double x1, double y1, double t1, + double x2, double y2, double t2, + double error, OutputIterator oi, + Op op, Transform transform) const { + auto tm = (t1 + t2)*0.5; + + // Compute the canocal point where the error is maximal. + double xm, ym; + op(tm, xm, ym); + + auto dx = x2 - x1; + auto dy = y2 - y1; + + // Compute the error; abort if it is below the threshold + auto l = std::sqrt(dx*dx + dy*dy); + auto e = std::abs((xm*dy - ym*dx + x2*y1 - x1*y2) / l); + if (e < error) return oi; + + double x, y; + transform(xm, ym, x, y); + add_points(x1, y1, t1, xm, ym, tm, error, oi, op, transform); + *oi++ = Approximate_point_2(x, y); + add_points(xm, ym, tm, x2, y2, t2, error, oi, op, transform); + return oi; + } + + /*! Compute the circular point given the parameter t and the transform + * data, that is, the center (translation) and the sin and cos of the + * rotation angle. + */ + void circular_point(double r, double t, double& x, double& y) const { + x = r * std::cos(t); + y = r * std::sin(t); + } + + /*! Transform a point. In particular, rotate the canonical point + * (`xc`,`yc`) by an angle, the sine and cosine of which are `sint` and + * `cost`, respectively, and translate by (`cx`,`cy`). + */ + void transform_point(double xc, double yc, double cx, double cy, + double& x, double& y) const { + x = xc + cx; + y = yc + cy; + } + + /*! Handle circular arcs. + */ + template + OutputIterator approximate_arc(const X_monotone_curve_2& xcv, + double error, OutputIterator oi, + bool l2r = true) const { + auto min_vertex = m_traits.construct_min_vertex_2_object(); + auto max_vertex = m_traits.construct_max_vertex_2_object(); + const auto& src = (l2r) ? min_vertex(xcv) : max_vertex(xcv); + const auto& trg = (l2r) ? max_vertex(xcv) : min_vertex(xcv); + auto xs = CGAL::to_double(src.x()); + auto ys = CGAL::to_double(src.y()); + auto xt = CGAL::to_double(trg.x()); + auto yt = CGAL::to_double(trg.y()); + + const typename Kernel::Circle_2& circ = xcv.supporting_circle(); + auto r_sqr = circ.squared_radius(); + auto r = std::sqrt(CGAL::to_double(r_sqr)); + + // Obtain the center: + auto cx = CGAL::to_double(circ.center().x()); + auto cy = CGAL::to_double(circ.center().y()); + + // Inverse transform the source and target + auto xs_t = xs - cx; + auto ys_t = ys - cy; + auto xt_t = xt - cx; + auto yt_t = yt - cy; + + // Compute the parameters ts and tt such that + // source == (x(ts),y(ts)), and + // target == (x(tt),y(tt)) + auto ts = std::atan2(r*ys_t, r*xs_t); + if (ts < 0) ts += 2*M_PI; + auto tt = std::atan2(r*yt_t, r*xt_t); + if (tt < 0) tt += 2*M_PI; + auto orient(xcv.orientation()); + if (xcv.source() != src) orient = CGAL::opposite(orient); + if (orient == COUNTERCLOCKWISE) { + if (tt < ts) tt += 2*M_PI; + } + else { + if (ts < tt) ts += 2*M_PI; + } + + *oi++ = Approximate_point_2(xs, ys); + add_points(xs_t, ys_t, ts, xt_t, yt_t, tt, error, oi, + [&](double tm, double& xm, double& ym) { + circular_point(r, tm, xm, ym); + }, + [&](double xc, double& yc, double& x, double& y) { + transform_point(xc, yc, cx, cy, x, y); + }); + *oi++ = Approximate_point_2(xt, yt); + return oi; + } + }; + + /*! Obtain an Approximate_2 functor object. */ + Approximate_2 approximate_2_object() const { return Approximate_2(*this); } + //@} + /// \name Intersections, subdivisions, and mergings //@{ diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index 2d243b01f35..019685ee0a1 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -1674,9 +1674,9 @@ public: double a; double ts, tt; double cx, cy; - m_traits.approximate_parabola(r_m, t_m, s_m, u_m, v_m, w_m, cost, sint, - xs_t, ys_t, xt_t, yt_t, a, ts, tt, cx, cy, - xcv); + m_traits.approximate_parabola(xcv, + r_m, t_m, s_m, u_m, v_m, w_m, cost, sint, + xs_t, ys_t, xt_t, yt_t, a, ts, tt, cx, cy); auto ds = parabolic_arc_length(xs_t, 2.0*std::abs(ys_t)); auto dt = parabolic_arc_length(xt_t, 2.0*std::abs(yt_t)); @@ -1694,9 +1694,9 @@ public: double a, b; double cx, cy; double ts, tt; - m_traits.approximate_ellipse(r_m, t_m, s_m, u_m, v_m, w_m, cost, sint, + m_traits.approximate_ellipse(xcv, r_m, t_m, s_m, u_m, v_m, w_m, cost, sint, xs_t, ys_t, ts, xt_t, yt_t, tt, - a, b, cx, cy, xcv); + a, b, cx, cy); namespace bm = boost::math; auto ratio = b/a; @@ -1746,31 +1746,29 @@ public: /*! Obtain an approximation of a point. */ Approximate_point_2 operator()(const Point_2& p) const - { return std::make_pair(operator()(p, 0), operator()(p, 1)); } + { return Approximate_point_2(operator()(p, 0), operator()(p, 1)); } /*! Obtain an approximation of an \f$x\f$-monotone curve. */ template - OutputIterator operator()(OutputIterator oi, double error, - const X_monotone_curve_2& xcv, - bool l2r = true) const { + OutputIterator operator()(const X_monotone_curve_2& xcv, double error, + OutputIterator oi, bool l2r = true) const { if (xcv.orientation() == COLLINEAR) - return approximate_segment(oi, xcv, l2r); + return approximate_segment(xcv, oi, l2r); CGAL::Sign sign_conic = CGAL::sign(4*xcv.r()*xcv.s() - xcv.t()*xcv.t()); if (sign_conic == POSITIVE) - return approximate_ellipse(oi, error, xcv, l2r); + return approximate_ellipse(xcv, error, oi, l2r); if (sign_conic == NEGATIVE) - return approximate_hyperbola(oi, error, xcv, l2r); - return approximate_parabola(oi, error, xcv, l2r); + return approximate_hyperbola(xcv, error, oi, l2r); + return approximate_parabola(xcv, error, oi, l2r); } private: /*! Handle segments. */ template - OutputIterator approximate_segment(OutputIterator oi, - const X_monotone_curve_2& xcv, - bool l2r) const { + OutputIterator approximate_segment(const X_monotone_curve_2& xcv, + OutputIterator oi, bool l2r) const { // std::cout << "SEGMENT\n"; auto min_vertex = m_traits.construct_min_vertex_2_object(); auto max_vertex = m_traits.construct_max_vertex_2_object(); @@ -1865,9 +1863,9 @@ public: * which approximates the arc. */ template - OutputIterator approximate_ellipse(OutputIterator oi, double error, - const X_monotone_curve_2& xcv, - bool l2r) const { + OutputIterator approximate_ellipse(const X_monotone_curve_2& xcv, + double error, OutputIterator oi, + bool l2r = true) const { // std::cout << "ELLIPSE\n"; auto min_vertex = m_traits.construct_min_vertex_2_object(); auto max_vertex = m_traits.construct_max_vertex_2_object(); @@ -1887,9 +1885,9 @@ public: double a, b; double cx, cy; double ts, tt; - m_traits.approximate_ellipse(r_m, t_m, s_m, u_m, v_m, w_m, cost, sint, + m_traits.approximate_ellipse(xcv, r_m, t_m, s_m, u_m, v_m, w_m, cost, sint, xs_t, ys_t, ts, xt_t, yt_t, tt, - a, b, cx, cy, xcv, l2r); + a, b, cx, cy, l2r); // std::cout << "a, b: " << a << "," << b << std::endl; *oi++ = Approximate_point_2(xs, ys); @@ -1954,7 +1952,7 @@ public: return oi; } - /*! Compute the hyperbolic point given the parameter t and the transform + /*! Compute the elliptic point given the parameter t and the transform * data, that is, the center (translation) and the sin and cos of the * rotation angle. */ @@ -1969,8 +1967,9 @@ public: * https://www.vcalc.com/wiki/vCalc/Parabola+-+arc+length */ template - OutputIterator approximate_parabola(OutputIterator oi, double error, - const X_monotone_curve_2& xcv, bool l2r) + OutputIterator approximate_parabola(const X_monotone_curve_2& xcv, + double error, OutputIterator oi, + bool l2r = true) const { // std::cout << "PARABOLA\n"; auto min_vertex = m_traits.construct_min_vertex_2_object(); @@ -1991,9 +1990,10 @@ public: double a; double ts, tt; double cx, cy; - m_traits.approximate_parabola(r_m, t_m, s_m, u_m, v_m, w_m, cost, sint, + m_traits.approximate_parabola(xcv, + r_m, t_m, s_m, u_m, v_m, w_m, cost, sint, xs_t, ys_t, xt_t, yt_t, a, ts, tt, cx, cy, - xcv, l2r); + l2r); // std::cout << "sint, cost: " << sint << "," << cost << std::endl; // std::cout << "a: " << a << std::endl; // std::cout << "xs' = " << xs_t << "," << ys_t << std::endl; @@ -2074,9 +2074,9 @@ public: /*! Handle hyperbolas. */ template - OutputIterator approximate_hyperbola(OutputIterator oi, double error, - const X_monotone_curve_2& xcv, - bool l2r) const { + OutputIterator approximate_hyperbola(const X_monotone_curve_2& xcv, + double error, OutputIterator oi, + bool l2r = true) const { // std::cout << "HYPERBOLA\n"; auto min_vertex = m_traits.construct_min_vertex_2_object(); auto max_vertex = m_traits.construct_max_vertex_2_object(); @@ -2093,9 +2093,10 @@ public: double a, b; double cx, cy; double ts, tt; - m_traits.approximate_hyperbola(r_m, t_m, s_m, u_m, v_m, w_m, cost, sint, + m_traits.approximate_hyperbola(xcv, r_m, t_m, s_m, u_m, v_m, w_m, + cost, sint, xs_t, ys_t, ts, xt_t, yt_t, tt, - a, b, cx, cy, xcv, l2r); + a, b, cx, cy, l2r); // std::cout << "a, b: " << a << "," << b << std::endl; // std::cout << "ts, tt: " << ts << "," << tt << std::endl; @@ -4027,14 +4028,15 @@ public: * The arc-length closed form can be found here: * https://www.vcalc.com/wiki/vCalc/Parabola+-+arc+length */ - void approximate_parabola(double& r_m, double& t_m, double& s_m, + void approximate_parabola(const X_monotone_curve_2& xcv, + double& r_m, double& t_m, double& s_m, double& u_m, double& v_m, double& w_m, double& cost, double& sint, double& xs_t, double& ys_t, double& xt_t, double& yt_t, double& a, double& ts, double& tt, double& cx, double& cy, - const X_monotone_curve_2& xcv, bool l2r = true) + bool l2r = true) const { auto min_vertex = construct_min_vertex_2_object(); auto max_vertex = construct_max_vertex_2_object(); @@ -4095,13 +4097,14 @@ public: /*! Handle ellipses. */ - void approximate_ellipse(double& r_m, double& t_m, double& s_m, + void approximate_ellipse(const X_monotone_curve_2& xcv, + double& r_m, double& t_m, double& s_m, double& u_m, double& v_m, double& w_m, double& cost, double& sint, double& xs_t, double& ys_t, double& ts, double& xt_t, double& yt_t, double& tt, double& a, double& b, double& cx, double& cy, - const X_monotone_curve_2& xcv, bool l2r = true) + bool l2r = true) const { auto min_vertex = construct_min_vertex_2_object(); auto max_vertex = construct_max_vertex_2_object(); @@ -4172,13 +4175,14 @@ public: /*! Handle hyperbolas. */ - void approximate_hyperbola(double& r_m, double& t_m, double& s_m, + void approximate_hyperbola(const X_monotone_curve_2& xcv, + double& r_m, double& t_m, double& s_m, double& u_m, double& v_m, double& w_m, double& cost, double& sint, double& xs_t, double& ys_t, double& ts, double& xt_t, double& yt_t, double& tt, double& a, double& b, double& cx, double& cy, - const X_monotone_curve_2& xcv, bool l2r = true) + bool l2r = true) const { auto min_vertex = construct_min_vertex_2_object(); auto max_vertex = construct_max_vertex_2_object(); diff --git a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h index d9e8f7c8189..e757c247976 100644 --- a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h +++ b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h @@ -21,17 +21,19 @@ #include #include +#include +#include + #include #ifdef CGAL_USE_BASIC_VIEWER #include #include -#include namespace CGAL { -// Viewer class for Polygon_2 +// Viewer class for`< Polygon_2 template class Arr_2_basic_viewer_qt : public Basic_viewer_qt { typedef GeometryTraits_2 Gt; @@ -45,9 +47,9 @@ class Arr_2_basic_viewer_qt : public Basic_viewer_qt { typedef typename Arr::Ccb_halfedge_const_circulator Ccb_halfedge_const_circulator; - // typedef double Approximate_number_type; - // typedef CGAL::Cartesian Approximate_kernel; - // typedef Approximate_kernel::Point_2 Approximate_point_2; + template + using approximate_2_object_t = + decltype(std::declval().approximate_2_object()); public: /// Construct the viewer. @@ -86,12 +88,33 @@ public: //! Compute the bounding box CGAL::Bbox_2 bounding_box() { + namespace bh = boost::hana; + auto has_approximate_2_object = + bh::is_valid([](auto&& x) -> decltype(x.approximate_2_object()){}); + // At this point we assume that the arrangement is not open, and thus the // bounding box is defined by the vertices. //! The bounding box CGAL::Bbox_2 bbox; - for (auto it = m_arr.vertices_begin(); it != m_arr.vertices_end(); ++it) - bbox += it->point().bbox(); + for (auto it = m_arr.vertices_begin(); it != m_arr.vertices_end(); ++it) { + bh::if_(has_approximate_2_object(Gt{}), + [&](auto& t) { + const auto* traits = this->m_arr.geometry_traits(); + auto approx = traits->approximate_2_object(); + auto has_operator = + bh::is_valid([](auto&& x) -> decltype(x.operator()(Point{}, int{})){}); + bh::if_(has_operator(approx), + [&](auto& a) { + auto x = approx(it->point(), 0); + auto y = approx(it->point(), 1); + bbox += CGAL::Bbox_2(x, y, x, y); + }, + [&](auto& a) { bbox += it->point().bbox(); } + )(approx); + }, + [&](auto& t) { bbox += it->point().bbox(); } + )(*this); + } return bbox; } @@ -167,36 +190,175 @@ protected: return ext; } - //! - virtual void draw_region(Ccb_halfedge_const_circulator circ) { - CGAL::IO::Color color(m_uni(m_rng), m_uni(m_rng), m_uni(m_rng)); - this->face_begin(color); - - auto ext = find_smallest(circ); - auto curr = ext; - do { - // Skip halfedges that are "antenas": - while (curr->face() == curr->twin()->face()) - curr = curr->twin()->next(); - - this->add_point_in_face(curr->source()->point()); - draw_curve(curr->curve()); - curr = curr->next(); - } while (curr != ext); - - this->face_end(); + //! Draw a region using aproximate coordinates. + // Call this member function only of the geometry traits is equipped to + // provide aproximate coordinates. + template + void draw_approximate_region(Halfedge_const_handle curr, + const Approximate& approx) { + std::vector polyline; + double error(this->pixel_ratio()); + bool l2r = curr->direction() == ARR_LEFT_TO_RIGHT; + approx(curr->curve(), error, std::back_inserter(polyline), l2r); + if (polyline.empty()) return; + auto it = polyline.begin(); + auto prev = it++; + for (; it != polyline.end(); prev = it++) { + this->add_segment(*prev, *it); + this->add_point_in_face(*prev); + } } - //! - virtual void draw_curve(const X_monotone_curve& curve) { + //! Draw an exact curve. + template + void draw_exact_curve(const XMonotoneCurve& curve) { const auto* traits = this->m_arr.geometry_traits(); auto ctr_min = traits->construct_min_vertex_2_object(); auto ctr_max = traits->construct_max_vertex_2_object(); this->add_segment(ctr_min(curve), ctr_max(curve)); } + //! Draw an exact region. + void draw_exact_region(Halfedge_const_handle curr) { + this->add_point_in_face(curr->source()->point()); + draw_exact_curve(curr->curve()); + } + + //! Utility struct + template + struct can_call_operator_curve { + template + constexpr auto operator()(F&& f) -> + decltype(f.template operator()(X_monotone_curve{}, double{}, T{}, bool{})) {} + }; + + //! Draw a region. + void draw_region(Ccb_halfedge_const_circulator circ) { + /* Check whether the traits has a member function called + * approximate_2_object() and if so check whether the return type, namely + * `Approximate_2` has an appropriate operator. + * + * C++20 supports concepts and `requires` expression; see, e.g., + * https://en.cppreference.com/w/cpp/language/constraints; thus, the first + * condition above can be elegantly verified as follows: + * constexpr bool has_approximate_2_object = + * requires(const Gt& traits) { traits.approximate_2_object(); }; + * + * C++17 has experimental constructs called is_detected and + * is_detected_v that can be used to achieve the same goal. + * + * For now we use C++14 features and boost.hana instead. + */ + namespace bh = boost::hana; + auto has_approximate_2_object = + bh::is_valid([](auto&& x) -> decltype(x.approximate_2_object()){}); + + CGAL::IO::Color color(m_uni(m_rng), m_uni(m_rng), m_uni(m_rng)); + this->face_begin(color); + + const auto* traits = this->m_arr.geometry_traits(); + auto ext = find_smallest(circ); + auto curr = ext; + do { + // Skip halfedges that are "antenas": + while (curr->face() == curr->twin()->face()) curr = curr->twin()->next(); + + bh::if_(has_approximate_2_object(Gt{}), + [&](auto& x) { + auto approx = traits->approximate_2_object(); + auto has_operator = bh::is_valid(can_call_operator_curve{}); + bh::if_(has_operator(approx), + [&](auto& x) { x.draw_approximate_region(curr, approx); }, + [&](auto& x) { x.draw_exact_region(curr); } + )(*this); + }, + [&](auto& x) { x.draw_exact_region(curr); } + )(*this); + curr = curr->next(); + } while (curr != ext); + + this->face_end(); + } + + //! Draw a curve using aproximate coordinates. + // Call this member function only of the geometry traits is equipped to + // provide aproximate coordinates. + template + void draw_approximate_curve(const XMonotoneCurve& curve, + const Approximate& approx) { + std::vector polyline; + double error(this->pixel_ratio()); + approx(curve, error, std::back_inserter(polyline)); + if (polyline.empty()) return; + auto it = polyline.begin(); + auto prev = it++; + for (; it != polyline.end(); prev = it++) this->add_segment(*prev, *it); + } + + //! Draw a curve. + template + void draw_curve(const XMonotoneCurve& curve) { + /* Check whether the traits has a member function called + * approximate_2_object() and if so check whether the return type, namely + * `Approximate_2` has an appropriate operator. + * + * C++20 supports concepts and `requires` expression; see, e.g., + * https://en.cppreference.com/w/cpp/language/constraints; thus, the first + * condition above can be elegantly verified as follows: + * constexpr bool has_approximate_2_object = + * requires(const Gt& traits) { traits.approximate_2_object(); }; + * + * C++17 has experimental constructs called is_detected and + * is_detected_v that can be used to achieve the same goal. + * + * For now we use C++14 features and boost.hana instead. + */ +#if 0 + if constexpr (std::experimental::is_detected_v) { + const auto* traits = this->m_arr.geometry_traits(); + auto approx = traits->approximate_2_object(); + draw_approximate_curve(curve, approx); + return; + } + draw_exact_curve(curve); +#else + namespace bh = boost::hana; + auto has_approximate_2_object = + bh::is_valid([](auto&& x) -> decltype(x.approximate_2_object()){}); + const auto* traits = this->m_arr.geometry_traits(); + bh::if_(has_approximate_2_object(Gt{}), + [&](auto& x) { + auto approx = traits->approximate_2_object(); + auto has_operator = bh::is_valid(can_call_operator_curve{}); + bh::if_(has_operator(approx), + [&](auto& x) { x.draw_approximate_curve(curve, approx); }, + [&](auto& x) { x.draw_exact_curve(curve); } + )(*this); + }, + [&](auto& x) { x.draw_exact_curve(curve); } + )(*this); +#endif + } + //! - virtual void draw_point(const Point& p) { this->add_point(p); } + void draw_point(const Point& p) { + namespace bh = boost::hana; + auto has_approximate_2_object = + bh::is_valid([](auto&& x) -> decltype(x.approximate_2_object()){}); + bh::if_(has_approximate_2_object(Gt{}), + [&](auto& x) { + const auto* traits = x.m_arr.geometry_traits(); + auto approx = traits->approximate_2_object(); + auto has_operator = + bh::is_valid([](auto&& x) -> decltype(x.operator()(Point{})){}); + bh::if_(has_operator(approx), + [&](auto& x) { /* x.add_point(approx(p)) */; }, + [&](auto& x) { x.add_point(p); } + )(*this); + }, + [&](auto& x) { x.add_point(p); } + )(*this); + } //! void add_ccb(Ccb_halfedge_const_circulator circ) { @@ -280,81 +442,6 @@ public: {} }; -//! -template -class Arr_2_viewer_qt, - Dcel> : - public Arr_2_basic_viewer_qt, Dcel> { -public: - typedef Arr_conic_traits_2 Gt; - typedef CGAL::Arrangement_2 Arr; - typedef Arr_2_basic_viewer_qt Base; - typedef typename Arr::Point_2 Point; - typedef typename Arr::X_monotone_curve_2 X_monotone_curve; - typedef typename Arr::Halfedge_const_handle Halfedge_const_handle; - typedef typename Arr::Face_const_handle Face_const_handle; - typedef typename Arr::Ccb_halfedge_const_circulator - Ccb_halfedge_const_circulator; - - /// Construct the viewer. - /// @param arr the arrangement to view - /// @param title the title of the window - Arr_2_viewer_qt(QWidget* parent, const Arr& arr, - const char* title = "2D Arrangement Basic Viewer") : - Base(parent, arr, title) - {} - - //! - virtual void draw_region(Ccb_halfedge_const_circulator circ) { - auto& uni = this->m_uni; - auto& rng = this->m_rng; - CGAL::IO::Color color(uni(rng), uni(rng), uni(rng)); - this->face_begin(color); - - const auto* traits = this->m_arr.geometry_traits(); - auto approx = traits->approximate_2_object(); - - // Find the lexicographically smallest halfedge: - auto ext = this->find_smallest(circ); - - // Iterate, starting from the lexicographically smallest vertex: - auto curr = ext; - do { - // Skip halfedges that are "antenas": - while (curr->face() == curr->twin()->face()) - curr = curr->twin()->next(); - - std::vector polyline; - double error(this->pixel_ratio()); - bool l2r = curr->direction() == ARR_LEFT_TO_RIGHT; - approx(std::back_inserter(polyline), error, curr->curve(), l2r); - auto it = polyline.begin(); - auto prev = it++; - for (; it != polyline.end(); prev = it++) { - this->add_segment(*prev, *it); - this->add_point_in_face(*prev); - } - curr = curr->next(); - } while (curr != ext); - - this->face_end(); - } - - //! - virtual void draw_curve(const X_monotone_curve& curve) { - const auto* traits = this->m_arr.geometry_traits(); - auto approx = traits->approximate_2_object(); - std::vector polyline; - double error(this->pixel_ratio()); - approx(std::back_inserter(polyline), error, curve); - auto it = polyline.begin(); - auto prev = it++; - for (; it != polyline.end(); prev = it++) this->add_segment(*prev, *it); - } -}; - //! template void draw(const Arrangement_2& arr, From 2aa04d9522a5efe4ac61c29f30f5e8e8230531e2 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Mon, 25 Jul 2022 11:08:28 +0300 Subject: [PATCH 062/105] Fixed compile-time dispatching --- .../include/CGAL/draw_arrangement_2.h | 79 ++++++++++++++----- 1 file changed, 59 insertions(+), 20 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h index e757c247976..c39e6d94ae0 100644 --- a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h +++ b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h @@ -84,7 +84,29 @@ public: } } - //! \todo intercept the scaling of the scene and apply add_elements() + /*! Compute an approximation of the bounding box of a point. + * \param[in] p the (exact) point. + * Call this member function only if the geometry traits is equipped with + * the coordinate-approximation functionality of a point coordinate. + * This function must be inlined (e.g., a template) to enable the + * compiled-time dispatching in the function `bounding_box()`. + */ + template + CGAL::Bbox_2 approximate_bbox(const Point& p, const Approximate& approx) { + auto x = approx(p, 0); + auto y = approx(p, 1); + return CGAL::Bbox_2(x, y, x, y); + } + + /*! Obtain the bounding box of a point. + * \param[in] p the point. + * We assume that if the coordinate-approximation functionality is not + * supported, the point supports the member function `bbox()`. + * This function must be inlined (e.g., a template) to enable the + * compiled-time dispatching in the function `bounding_box()`. + */ + template + CGAL::Bbox_2 exact_bbox(const Point& p) { return p.bbox(); } //! Compute the bounding box CGAL::Bbox_2 bounding_box() { @@ -98,21 +120,19 @@ public: CGAL::Bbox_2 bbox; for (auto it = m_arr.vertices_begin(); it != m_arr.vertices_end(); ++it) { bh::if_(has_approximate_2_object(Gt{}), - [&](auto& t) { + [&](auto& x) { const auto* traits = this->m_arr.geometry_traits(); auto approx = traits->approximate_2_object(); auto has_operator = - bh::is_valid([](auto&& x) -> decltype(x.operator()(Point{}, int{})){}); + bh::is_valid([](auto&& x) -> + decltype(x.operator()(Point{}, int{})){}); bh::if_(has_operator(approx), - [&](auto& a) { - auto x = approx(it->point(), 0); - auto y = approx(it->point(), 1); - bbox += CGAL::Bbox_2(x, y, x, y); - }, - [&](auto& a) { bbox += it->point().bbox(); } - )(approx); + [&](auto& x) + { bbox += x.approximate_bbox(it->point(), approx); }, + [&](auto& x) { bbox += x.exact_bbox(it->point()); } + )(*this); }, - [&](auto& t) { bbox += it->point().bbox(); } + [&](auto& x) { bbox += x.exact_bbox(it->point()); } )(*this); } return bbox; @@ -190,9 +210,12 @@ protected: return ext; } - //! Draw a region using aproximate coordinates. - // Call this member function only of the geometry traits is equipped to - // provide aproximate coordinates. + /*! Draw a region using aproximate coordinates. + * Call this member function only if the geometry traits is equipped with + * the coordinate-approximation functionality of a curve. + * This function must be inlined (e.g., a template) to enable the + * compiled-time dispatching in the function `draw_region()`. + */ template void draw_approximate_region(Halfedge_const_handle curr, const Approximate& approx) { @@ -266,7 +289,8 @@ protected: bh::if_(has_approximate_2_object(Gt{}), [&](auto& x) { auto approx = traits->approximate_2_object(); - auto has_operator = bh::is_valid(can_call_operator_curve{}); + auto has_operator = + bh::is_valid(can_call_operator_curve{}); bh::if_(has_operator(approx), [&](auto& x) { x.draw_approximate_region(curr, approx); }, [&](auto& x) { x.draw_exact_region(curr); } @@ -280,9 +304,12 @@ protected: this->face_end(); } - //! Draw a curve using aproximate coordinates. - // Call this member function only of the geometry traits is equipped to - // provide aproximate coordinates. + /*! Draw a curve using aproximate coordinates. + * Call this member function only of the geometry traits is equipped with + * the coordinate-aproximation functionality of a curve. + * This function must be inlined (e.g., a template) to enable the + * compiled-time dispatching in the function `draw_curve()`. + */ template void draw_approximate_curve(const XMonotoneCurve& curve, const Approximate& approx) { @@ -314,7 +341,8 @@ protected: * For now we use C++14 features and boost.hana instead. */ #if 0 - if constexpr (std::experimental::is_detected_v) { + if constexpr (std::experimental::is_detected_v) + { const auto* traits = this->m_arr.geometry_traits(); auto approx = traits->approximate_2_object(); draw_approximate_curve(curve, approx); @@ -340,6 +368,17 @@ protected: #endif } + /*! Add an approximation of a point. + * \param[in] p the (exact) point. + * Call this member function only if the geometry traits is equipped with + * the coordinate-approximation functionality of a point. + * This function must be inlined (e.g., a template) to enable the + * compiled-time dispatching in the function `draw_point()`. + */ + template + void draw_approximate_point(const Point& p, const Approximate& approx) + { this->add_point(approx(p)); } + //! void draw_point(const Point& p) { namespace bh = boost::hana; @@ -352,7 +391,7 @@ protected: auto has_operator = bh::is_valid([](auto&& x) -> decltype(x.operator()(Point{})){}); bh::if_(has_operator(approx), - [&](auto& x) { /* x.add_point(approx(p)) */; }, + [&](auto& x) { x.draw_approximate_point(p, approx); }, [&](auto& x) { x.add_point(p); } )(*this); }, From 8ab4747f4eaeb3119d1ce4779748f012b99ece13 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Mon, 25 Jul 2022 12:18:37 +0300 Subject: [PATCH 063/105] Used predefined windo x and y dimensions --- Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h index c39e6d94ae0..00119383a35 100644 --- a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h +++ b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h @@ -440,22 +440,21 @@ protected: protected: //! The window width in pixels. - int m_width = 500; + int m_width = CGAL_BASIC_VIEWER_INIT_SIZE_X; //! The window height in pixels. - int m_height = 450; + int m_height = CGAL_BASIC_VIEWER_INIT_SIZE_Y; //! The ratio between pixel and opengl units (in world coordinate system). double m_pixel_ratio = 1; - //! The arrangement to draw + //! The arrangement to draw. const Arr& m_arr; std::unordered_map m_visited; std::mt19937 m_rng; std::uniform_int_distribution m_uni; // guaranteed unbiased - }; //! Basic viewer of a 2D arrangement. From 3b3067ca5db784cc4d3f08b2fe7179f98987e23c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 25 Jul 2022 13:27:01 +0200 Subject: [PATCH 064/105] add missing dependency --- .../package_info/Arrangement_on_surface_2/dependencies | 1 + 1 file changed, 1 insertion(+) diff --git a/Arrangement_on_surface_2/package_info/Arrangement_on_surface_2/dependencies b/Arrangement_on_surface_2/package_info/Arrangement_on_surface_2/dependencies index bd73b84a902..a723fb58f63 100644 --- a/Arrangement_on_surface_2/package_info/Arrangement_on_surface_2/dependencies +++ b/Arrangement_on_surface_2/package_info/Arrangement_on_surface_2/dependencies @@ -10,6 +10,7 @@ Circulator Distance_2 Distance_3 Filtered_kernel +GraphicsView HalfedgeDS Hash_map Homogeneous_kernel From efcca95f05525449652ac8290f8d9c2ac0b7c32b Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Tue, 26 Jul 2022 17:45:35 +0300 Subject: [PATCH 065/105] Intialized Arr_polyhedral_sgm_polyhedron_3_vertex::m_processed --- .../Arr_polyhedral_sgm_polyhedron_3.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_spherical_gaussian_map_3/Arr_polyhedral_sgm_polyhedron_3.h b/Arrangement_on_surface_2/include/CGAL/Arr_spherical_gaussian_map_3/Arr_polyhedral_sgm_polyhedron_3.h index 70e9a8b6518..387a0cfa9d9 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_spherical_gaussian_map_3/Arr_polyhedral_sgm_polyhedron_3.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_spherical_gaussian_map_3/Arr_polyhedral_sgm_polyhedron_3.h @@ -64,11 +64,12 @@ public: typedef typename Base::Point Point; /*! Constructor */ - Arr_polyhedral_sgm_polyhedron_3_vertex() : Base(), m_marked(false) {} + Arr_polyhedral_sgm_polyhedron_3_vertex() : + Base(), m_processed(false), m_marked(false) {} /*! Constructor */ Arr_polyhedral_sgm_polyhedron_3_vertex(const Point & p) : - Base(p), m_marked(false) {} + Base(p), m_processed(false), m_marked(false) {} /*! Obtain the mutable (geometrical) point. Delegate */ Point & point() { return Base::point(); } From 480eb291698e880e3a38581ab3143befae4eab55 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Tue, 26 Jul 2022 17:46:03 +0300 Subject: [PATCH 066/105] Fixed typo --- Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index 019685ee0a1..3648835eb84 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -2508,7 +2508,7 @@ public: // Make sure that all midpoints are strictly between the // source and the target. Point_2 mp2(nt_traits->convert(p2.x()), nt_traits->convert(p2.y())); - Point_2 mp3(nt_traits->convert(p3.x()), m_nt_traits->convert(p3.y())); + Point_2 mp3(nt_traits->convert(p3.x()), nt_traits->convert(p3.y())); Point_2 mp4(nt_traits->convert(p4.x()), nt_traits->convert(p4.y())); if (! m_traits.is_strictly_between_endpoints(arc, mp2) || From 10c06642079893dda93b9b0775c1ebff6fcdb891 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Thu, 28 Jul 2022 14:15:14 +0300 Subject: [PATCH 067/105] Added missing include --- .../include/CGAL/Arr_circle_segment_traits_2.h | 8 +++++--- .../include/CGAL/Arr_conic_traits_2.h | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h index 919b3ec0548..ca001d7fc7f 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h @@ -23,14 +23,16 @@ * The header file for the Arr_circle_segment_traits_2 class. */ +#define _USE_MATH_DEFINES +#include +#include +#include + #include #include #include #include -#include -#include - namespace CGAL { /*! \class diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index 3648835eb84..74bd5b1efde 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -23,6 +23,7 @@ * The conic traits-class for the arrangement package. */ +#define _USE_MATH_DEFINES #include #include #include From 9787fff9a0a33e12a32eb8628c6bc4b1ceb85b2b Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 10 Aug 2022 17:44:00 +0300 Subject: [PATCH 068/105] laced 'unsigned int' with Multiplicity type to avoid a conversion warning --- Surface_sweep_2/include/CGAL/Surface_sweep_2.h | 2 +- .../include/CGAL/Surface_sweep_2/Surface_sweep_2_impl.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Surface_sweep_2/include/CGAL/Surface_sweep_2.h b/Surface_sweep_2/include/CGAL/Surface_sweep_2.h index 1e3ec6edf75..2b9329a8476 100644 --- a/Surface_sweep_2/include/CGAL/Surface_sweep_2.h +++ b/Surface_sweep_2/include/CGAL/Surface_sweep_2.h @@ -222,7 +222,7 @@ protected: * \param c2 The second curve. */ void _create_intersection_point(const Point_2& xp, - unsigned int mult, + Multiplicity mult, Subcurve*& c1, Subcurve*& c2); }; diff --git a/Surface_sweep_2/include/CGAL/Surface_sweep_2/Surface_sweep_2_impl.h b/Surface_sweep_2/include/CGAL/Surface_sweep_2/Surface_sweep_2_impl.h index de98db8e9a0..59f8134dc25 100644 --- a/Surface_sweep_2/include/CGAL/Surface_sweep_2/Surface_sweep_2_impl.h +++ b/Surface_sweep_2/include/CGAL/Surface_sweep_2/Surface_sweep_2_impl.h @@ -773,7 +773,7 @@ void Surface_sweep_2::_intersect(Subcurve* c1, Subcurve* c2, // template void Surface_sweep_2::_create_intersection_point(const Point_2& xp, - unsigned int multiplicity, + Multiplicity multiplicity, Subcurve*& c1, Subcurve*& c2) { From 90f74ea390eff3e3f9be48491e2b6294d3b30931 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 10 Aug 2022 17:44:57 +0300 Subject: [PATCH 069/105] Changed the order of inclusion. --- .../include/CGAL/Arr_circle_segment_traits_2.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h index ca001d7fc7f..55b17f4e850 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h @@ -23,10 +23,10 @@ * The header file for the Arr_circle_segment_traits_2 class. */ -#define _USE_MATH_DEFINES #include -#include +#define _USE_MATH_DEFINES #include +#include #include #include From d03c6bb9d2c1fcca70f19e1084aafd7a3a4ed1bc Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 10 Aug 2022 17:45:34 +0300 Subject: [PATCH 070/105] dded getters to obtain the internally algebraic kernel, rational kernel, and nt traits. Also, refractored a bit so that it can be used by the envelope sphere traits. --- .../include/CGAL/Arr_conic_traits_2.h | 191 +++++++++--------- 1 file changed, 100 insertions(+), 91 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index 74bd5b1efde..d3625192503 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -116,11 +116,11 @@ private: typedef std::shared_ptr Shared_rat_kernel; typedef std::shared_ptr Shared_alg_kernel; - typedef std::shared_ptr Shared_nt_Traits; + typedef std::shared_ptr Shared_nt_traits; const Shared_rat_kernel m_rat_kernel; const Shared_alg_kernel m_alg_kernel; - const Shared_nt_Traits m_nt_traits; + const Shared_nt_traits m_nt_traits; mutable Intersection_map m_inter_map; // Mapping conic pairs to their // intersection points. @@ -134,12 +134,24 @@ public: */ Arr_conic_traits_2(Shared_rat_kernel rat_kernel, Shared_alg_kernel alg_kernel, - Shared_nt_Traits nt_traits) : + Shared_nt_traits nt_traits) : m_rat_kernel(rat_kernel), m_alg_kernel(alg_kernel), m_nt_traits(nt_traits) {} + /*! Obtain the rational kernel. + */ + Shared_rat_kernel rat_kernel() { return m_rat_kernel; } + + /*! Obtain the algebraic kernel. + */ + Shared_alg_kernel alg_kernel() { return m_alg_kernel; } + + /*! Obtain the nt traits. + */ + Shared_nt_traits nt_traits() { return m_nt_traits; } + /*! Obtain the next conic index. */ static size_t get_index() { #ifdef CGAL_NO_ATOMIC @@ -303,94 +315,13 @@ public: if (x_res_right == EQUAL) q = xcv.right(); else { CGAL_precondition(x_res_right != LARGER); - q = point_at_x(xcv, p); + q = m_traits.point_at_x(xcv, p); } } // Compare p with the a point of the curve with the same x coordinate. return cmp_y(p, q); } - - private: - /*! Compute a point on an arc with the same \f$x\f$-coordiante as the given - * point. - * \param p The given point. - * \pre The arc is not vertical and `p` is in the \f$x\f$-range of the arc. - * \return A point on the arc with the same \f$x\f$-coordiante as `p`. - */ - Point_2 point_at_x(const X_monotone_curve_2& xcv, const Point_2& p) const { - // Make sure that p is in the x-range of the arc. - CGAL_precondition(! xcv.is_vertical()); - - CGAL_precondition_code(auto cmp_x = - m_traits.m_alg_kernel->compare_x_2_object()); - CGAL_precondition((cmp_x(p, xcv.left()) != SMALLER) && - (cmp_x(p, xcv.right()) != LARGER)); - - if (xcv.is_special_segment()) { - // In case of a special segment, the equation of the supported line - // (a*x + b*y + c) = 0 is stored with the extra data field, and we - // simply have: - const auto& extra_data = xcv.extra_data(); - Algebraic y = -(extra_data->a*p.x() + extra_data->c) / extra_data->b; - - // Return the computed point. - return Point_2(p.x(), y); - } - - // Compute the y-coordinate according to the degree of the supporting - // conic curve. - Algebraic y; - - if (xcv.degree_mask() == X_monotone_curve_2::degree_1_mask()) { - // In case of a linear curve, the y-coordinate is a simple linear - // expression of x(p) (note that v is not 0 as the arc is not vertical): - // y = -(u*x(p) + w) / v - y = -(xcv.alg_u()*p.x() + xcv.alg_w()) / xcv.alg_v(); - } - else if (xcv.orientation() == COLLINEAR) { - const auto& extra_data = xcv.extra_data(); - CGAL_assertion(extra_data != nullptr); - - // In this case the equation of the supporting line is given by the - // extra data structure. - y = -(extra_data->a * p.x() + extra_data->c) / extra_data->b; - } - else { - CGAL_assertion(xcv.degree_mask() == X_monotone_curve_2::degree_2_mask()); - - // In this case the y-coordinate is one of solutions to the quadratic - // equation: - // s*y^2 + (t*x(p) + v)*y + (r*x(p)^2 + u*x(p) + w) = 0 - Algebraic A = xcv.alg_s(); - Algebraic B = xcv.alg_t()*p.x() + xcv.alg_v(); - Algebraic C = (xcv.alg_r()*p.x() + xcv.alg_u())*p.x() + xcv.alg_w(); - - if (CGAL::sign(xcv.s()) == ZERO) { - // In this case A is 0 and we have a linear equation. - CGAL_assertion(CGAL::sign(B) != ZERO); - - y = -C / B; - } - else { - // Solve the quadratic equation. - Algebraic disc = B*B - 4*A*C; - - CGAL_assertion(CGAL::sign(disc) != NEGATIVE); - - // We take either the root involving -sqrt(disc) or +sqrt(disc) - // based on the information flags. - const auto nt_traits = m_traits.m_nt_traits; - y = (xcv.test_flag(X_monotone_curve_2::PLUS_SQRT_DISC_ROOT)) ? - (nt_traits->sqrt(disc) - B) / (2*A) : - -(B + nt_traits->sqrt(disc)) / (2*A); - } - } - - // Return the computed point. - return Point_2(p.x(), y); - } - }; /*! Obtain a Compare_y_at_x_2 functor object. */ @@ -841,8 +772,8 @@ public: * `ARR_RIGHT_BOUNDARY`—the arc approaches the identification curve from * the left at the arc right end. */ - Arr_parameter_space operator()(const X_monotone_curve_2 & xcv, - Arr_curve_end ce) const { + Arr_parameter_space operator()(const X_monotone_curve_2 & /* xcv */, + Arr_curve_end /* ce */) const { CGAL_error_msg("Not implemented yet!"); return ARR_INTERIOR; } @@ -1710,7 +1641,8 @@ public: } double hyperbola_length(const X_monotone_curve_2& xcv) { - double l; + CGAL_error_msg("Not implemented yet!"); + double l(0.0); return l; } }; @@ -3196,7 +3128,7 @@ public: // the arc is not infinite. Point_2 p_mid = m_alg_kernel->construct_midpoint_2_object()(source, target); - Point_2 ps[2]; + Alg_point_2 ps[2]; bool finite_at_x = (points_at_x(cv, p_mid, ps) > 0); bool finite_at_y = (points_at_y(cv, p_mid, ps) > 0); if (! finite_at_x && ! finite_at_y) { @@ -3542,13 +3474,90 @@ public: return 2; } + /*! Compute a point on an arc with the same \f$x\f$-coordiante as the given + * point. + * \param p The given point. + * \pre The arc is not vertical and `p` is in the \f$x\f$-range of the arc. + * \return A point on the arc with the same \f$x\f$-coordiante as `p`. + */ + Point_2 point_at_x(const X_monotone_curve_2& xcv, const Point_2& p) const { + // Make sure that p is in the x-range of the arc. + CGAL_precondition(! xcv.is_vertical()); + + CGAL_precondition_code(auto cmp_x = m_alg_kernel->compare_x_2_object()); + CGAL_precondition((cmp_x(p, xcv.left()) != SMALLER) && + (cmp_x(p, xcv.right()) != LARGER)); + + if (xcv.is_special_segment()) { + // In case of a special segment, the equation of the supported line + // (a*x + b*y + c) = 0 is stored with the extra data field, and we + // simply have: + const auto& extra_data = xcv.extra_data(); + Algebraic y = -(extra_data->a*p.x() + extra_data->c) / extra_data->b; + + // Return the computed point. + return Point_2(p.x(), y); + } + + // Compute the y-coordinate according to the degree of the supporting + // conic curve. + Algebraic y; + + if (xcv.degree_mask() == X_monotone_curve_2::degree_1_mask()) { + // In case of a linear curve, the y-coordinate is a simple linear + // expression of x(p) (note that v is not 0 as the arc is not vertical): + // y = -(u*x(p) + w) / v + y = -(xcv.alg_u()*p.x() + xcv.alg_w()) / xcv.alg_v(); + } + else if (xcv.orientation() == COLLINEAR) { + const auto& extra_data = xcv.extra_data(); + CGAL_assertion(extra_data != nullptr); + + // In this case the equation of the supporting line is given by the + // extra data structure. + y = -(extra_data->a * p.x() + extra_data->c) / extra_data->b; + } + else { + CGAL_assertion(xcv.degree_mask() == X_monotone_curve_2::degree_2_mask()); + + // In this case the y-coordinate is one of solutions to the quadratic + // equation: + // s*y^2 + (t*x(p) + v)*y + (r*x(p)^2 + u*x(p) + w) = 0 + Algebraic A = xcv.alg_s(); + Algebraic B = xcv.alg_t()*p.x() + xcv.alg_v(); + Algebraic C = (xcv.alg_r()*p.x() + xcv.alg_u())*p.x() + xcv.alg_w(); + + if (CGAL::sign(xcv.s()) == ZERO) { + // In this case A is 0 and we have a linear equation. + CGAL_assertion(CGAL::sign(B) != ZERO); + + y = -C / B; + } + else { + // Solve the quadratic equation. + Algebraic disc = B*B - 4*A*C; + + CGAL_assertion(CGAL::sign(disc) != NEGATIVE); + + // We take either the root involving -sqrt(disc) or +sqrt(disc) + // based on the information flags. + y = (xcv.test_flag(X_monotone_curve_2::PLUS_SQRT_DISC_ROOT)) ? + (m_nt_traits->sqrt(disc) - B) / (2*A) : + -(B + m_nt_traits->sqrt(disc)) / (2*A); + } + } + + // Return the computed point. + return Point_2(p.x(), y); + } + /*! Find all points on the arc with a given \f$x\f$-coordinate. * \param p A placeholder for the \f$x\f$-coordinate. * \param ps The point on the arc at `x(p)`. * \pre The vector `ps` should be allocated at the size of 2. * \return The number of points found. */ - int points_at_x(const Curve_2& cv, const Point_2& p, Point_2* ps) const { + int points_at_x(const Curve_2& cv, const Point_2& p, Alg_point_2* ps) const { // Get the y coordinates of the points on the conic. Algebraic ys[2]; int n = conic_get_y_coordinates(cv, p.x(), ys); @@ -3572,7 +3581,7 @@ public: * \pre The vector `ps` should be allocated at the size of 2. * \return The number of points found. */ - int points_at_y(const Curve_2& cv, const Point_2& p, Point_2* ps) const { + int points_at_y(const Curve_2& cv, const Point_2& p, Alg_point_2* ps) const { // Get the y coordinates of the points on the conic. Algebraic xs[2]; int n = conic_get_x_coordinates(cv, p.y(), xs); From 3b69bebc82d36767ac2a52b310aa0b35f7891bb2 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 10 Aug 2022 17:47:07 +0300 Subject: [PATCH 071/105] Add a constructor that accepts the anderlying conic traits, and used this conic traits properly. --- Envelope_3/include/CGAL/Env_sphere_traits_3.h | 668 ++++++++---------- 1 file changed, 284 insertions(+), 384 deletions(-) diff --git a/Envelope_3/include/CGAL/Env_sphere_traits_3.h b/Envelope_3/include/CGAL/Env_sphere_traits_3.h index 0159d74f030..555e87e552b 100644 --- a/Envelope_3/include/CGAL/Env_sphere_traits_3.h +++ b/Envelope_3/include/CGAL/Env_sphere_traits_3.h @@ -28,49 +28,47 @@ namespace CGAL { -template -class Env_sphere_traits_3 : public ConicTraits_2 -{ +template +class Env_sphere_traits_3 : public ConicTraits_2 { public: - typedef ConicTraits_2 Traits_2; - typedef Env_sphere_traits_3 Self; + typedef ConicTraits_2 Traits_2; + typedef Env_sphere_traits_3 Self; - typedef typename Traits_2::Point_2 Point_2; - typedef typename Traits_2::Curve_2 Curve_2; - typedef typename Traits_2::X_monotone_curve_2 X_monotone_curve_2; - typedef typename Traits_2::Multiplicity Multiplicity; + typedef typename Traits_2::Point_2 Point_2; + typedef typename Traits_2::Curve_2 Curve_2; + typedef typename Traits_2::X_monotone_curve_2 X_monotone_curve_2; + typedef typename Traits_2::Multiplicity Multiplicity; - typedef typename Traits_2::Rat_kernel Rat_kernel; - typedef typename Traits_2::Alg_kernel Alg_kernel; - typedef typename Traits_2::Nt_traits Nt_traits; + typedef typename Traits_2::Rat_kernel Rat_kernel; + typedef typename Traits_2::Alg_kernel Alg_kernel; + typedef typename Traits_2::Nt_traits Nt_traits; - typedef typename Rat_kernel::FT Rational; - typedef typename Rat_kernel::Point_2 Rat_point_2; - typedef typename Rat_kernel::Segment_2 Rat_segment_2; - typedef typename Rat_kernel::Line_2 Rat_line_2; - typedef typename Rat_kernel::Circle_2 Rat_circle_2; - typedef typename Rat_kernel::Point_3 Rat_point_3; + typedef typename Rat_kernel::FT Rational; + typedef typename Rat_kernel::Point_2 Rat_point_2; + typedef typename Rat_kernel::Segment_2 Rat_segment_2; + typedef typename Rat_kernel::Line_2 Rat_line_2; + typedef typename Rat_kernel::Circle_2 Rat_circle_2; + typedef typename Rat_kernel::Point_3 Rat_point_3; - typedef typename Alg_kernel::FT Algebraic; - typedef typename Alg_kernel::Point_2 Alg_point_2; - typedef typename Alg_kernel::Circle_2 Alg_circle_2; + typedef typename Alg_kernel::FT Algebraic; + typedef typename Alg_kernel::Point_2 Alg_point_2; + typedef typename Alg_kernel::Circle_2 Alg_circle_2; - typedef typename Rat_kernel::Sphere_3 Surface_3; + typedef typename Rat_kernel::Sphere_3 Surface_3; // here we refer to the lower part of the sphere only - typedef Surface_3 Xy_monotone_surface_3; + typedef Surface_3 Xy_monotone_surface_3; + protected: - typedef std::pair Intersection_curve; + typedef std::pair Intersection_curve; public: class Make_xy_monotone_3 { protected: - const Self & parent; + const Self& parent; public: - Make_xy_monotone_3(const Self * p) : parent(*p) - {} + Make_xy_monotone_3(const Self * p) : parent(*p) {} // create xy-monotone surfaces from a general surface // return a past-the-end iterator @@ -89,32 +87,28 @@ public: /*! Get a Make_xy_monotone_3 functor object. */ Make_xy_monotone_3 - make_xy_monotone_3_object() const - { - return Make_xy_monotone_3(this); - } + make_xy_monotone_3_object() const { return Make_xy_monotone_3(this); } - class Construct_projected_boundary_2 - { + class Construct_projected_boundary_2 { protected: - const Self & parent; + const Self& parent; public: - Construct_projected_boundary_2(const Self * p) : parent(*p) - {} + Construct_projected_boundary_2(const Self* p) : parent(*p) {} // insert into the OutputIterator all the (2d) curves of the boundary of // the vertical projection of the surface on the xy-plane // the OutputIterator value type is X_monotone_curve_2 template OutputIterator - operator()(const Xy_monotone_surface_3& s, OutputIterator o) const - { + operator()(const Xy_monotone_surface_3& s, OutputIterator o) const { + const auto gt_2 = parent.geometry_traits_2(); + // the projected boundary in a circle, with a projected center, // and same radius Rat_point_2 proj_center = parent.project(s.center()); Rat_circle_2 circ(proj_center, s.squared_radius()); - Curve_2 curve(circ); + Curve_2 curve = gt_2->construct_curve_2_object()(circ); Object objs[2]; CGAL_assertion_code(Object *p = ) parent.make_x_monotone_2_object()(curve, objs); @@ -128,14 +122,12 @@ public: assign(cv1, objs[0]); assign(cv2, objs[1]); - if(cv1.is_lower()) - { + if (cv1.is_lower()) { CGAL_assertion(cv2.is_upper()); *o++ = make_object(std::make_pair(cv1, ON_POSITIVE_SIDE)); *o++ = make_object(std::make_pair(cv2, ON_NEGATIVE_SIDE)); } - else - { + else { CGAL_assertion(cv2.is_lower()); *o++ = make_object(std::make_pair(cv1, ON_NEGATIVE_SIDE)); *o++ = make_object(std::make_pair(cv2, ON_POSITIVE_SIDE)); @@ -148,59 +140,57 @@ public: /*! Get a Construct_projected_boundary_2 functor object. */ Construct_projected_boundary_2 construct_projected_boundary_2_object() const - { - return Construct_projected_boundary_2(this); - } + { return Construct_projected_boundary_2(this); } - class Construct_projected_intersections_2 - { + class Construct_projected_intersections_2 { protected: - const Self & parent; + const Self& parent; public: - Construct_projected_intersections_2(const Self * p) : parent(*p) - {} + Construct_projected_intersections_2(const Self * p) : parent(*p) {} // insert into OutputIterator all the (2d) projections on the xy plane of // the intersection objects between the 2 surfaces // the data type of OutputIterator is Object - template + template OutputIterator - operator()(const Xy_monotone_surface_3& s1, - const Xy_monotone_surface_3& s2, - OutputIterator o) const - { + operator()(const Xy_monotone_surface_3& s1, const Xy_monotone_surface_3& s2, + OutputIterator o) const { + const auto gt_2 = parent.geometry_traits_2(); + auto ctr_cv = gt_2->construct_curve_2_object(); + auto nt_traits = gt_2->nt_traits(); + Rat_point_3 p1 = s1.center(); Rat_point_3 p2 = s2.center(); - const Rational a1 = p1.x(), b1 = p1.y(), c1 = p1.z(), - a2 = p2.x(), b2 = p2.y(), c2 = p2.z(); - const Rational sqr_r1 = s1.squared_radius(), - sqr_r2 = s2.squared_radius(); + const Rational a1 = p1.x(); + const Rational b1 = p1.y(); + const Rational c1 = p1.z(); + const Rational a2 = p2.x(); + const Rational b2 = p2.y(); + const Rational c2 = p2.z(); + const Rational sqr_r1 = s1.squared_radius(); + const Rational sqr_r2 = s2.squared_radius(); -// // the spheres intersect iff d(p1, p2) <= (r1+r2) -// // squaring this twice, we get the condition -// // sqr_d^2 + (1-2*sqr_d)(sqr_r1 + sqr_r2) - 2*sqr_r1*sqr_r2 <= 0 -// // with only rational numbers involved. -// // todo: check if it helps -// Rat_kernel ratk; -// Rational sqr_d = ratk.compute_squared_distance_3_object()(p1, p2); -// Sign do_inter = CGAL_NTS sign(sqr_d*sqr_d + (1-2*sqr_d)*(sqr_r1+sqr_r2)-2*sqr_r1*sqr_r2); -// if (do_inter == POSITIVE) -// return o; - - Nt_traits nt_traits; + // // the spheres intersect iff d(p1, p2) <= (r1+r2) + // // squaring this twice, we get the condition + // // sqr_d^2 + (1-2*sqr_d)(sqr_r1 + sqr_r2) - 2*sqr_r1*sqr_r2 <= 0 + // // with only rational numbers involved. + // // todo: check if it helps + // Rat_kernel ratk; + // Rational sqr_d = ratk.compute_squared_distance_3_object()(p1, p2); + // Sign do_inter = + // CGAL_NTS sign(sqr_d*sqr_d + (1-2*sqr_d)*(sqr_r1+sqr_r2)-2*sqr_r1*sqr_r2); + // if (do_inter == POSITIVE) + // return o; // we check if the centers of the 2 spheres have same z coordinate - // in this case the potential projected intersection is a segment // (or point) - if (CGAL_NTS compare(c1, c2) == EQUAL) - { - if (CGAL_NTS compare(b1, b2) == EQUAL) - { - if (CGAL_NTS compare(a1, a2) == EQUAL) + if (CGAL_NTS compare(c1, c2) == EQUAL) { + if (CGAL_NTS compare(b1, b2) == EQUAL) { + if (CGAL_NTS compare(a1, a2) == EQUAL) { // the same center, we have no intersection // (we don't return overlappings as intersections) - { return o; } @@ -234,24 +224,17 @@ public: Rational B = -8*b1*sqr_a_diff; Rational C = 4*sqr_a_diff*(sqr_a1+sqr_b1-sqr_r1) + m*m - 4*m*a1*a_diff; - Algebraic ys[2]; - Algebraic *ys_end; - std::ptrdiff_t n_ys; - ys_end = nt_traits.solve_quadratic_equation(A, B, C, ys); - n_ys = ys_end - ys; + Algebraic* ys_end = nt_traits->solve_quadratic_equation(A, B, C, ys); + std::ptrdiff_t n_ys = ys_end - ys; - if (n_ys == 0) - { - return o; // no intersection - } + if (n_ys == 0) return o; // no intersection // the x coordinate of the solution points Algebraic xs = m / (2*a_diff); - if (n_ys == 1) - { + if (n_ys == 1) { // intersection is a point Point_2 inter_point(xs , ys[0]); *o++ = make_object(inter_point); @@ -268,14 +251,12 @@ public: // equation (1) is: // 2(a1-a2)x - m = 0 - - Curve_2 res(0,0,0, 2*a_diff, 0, -m, COLLINEAR, end1, end2); + Curve_2 res = ctr_cv(0, 0, 0, 2*a_diff, 0, -m, COLLINEAR, end1, end2); parent.add_curve_to_output(res, o); //*o++ = make_object(Intersection_curve(res, TRANSVERSAL)); } - else - { + else { // here we have c1 == c2, b1 != b2. // the intersection lies on the plane // -2(a1-a2)x + m @@ -316,19 +297,15 @@ public: Rational E = -8*a1*sqr_b_diff - 4*m*a_diff + 8*b1*a_diff*b_diff; Rational F = 4*sqr_b_diff*(sqr_a1+sqr_b1-sqr_r1) + m*m - 4*m*b1*b_diff; - Algebraic xs[2]; - Algebraic *xs_end; - std::ptrdiff_t n_xs; + Algebraic xs[2]; - xs_end = nt_traits.solve_quadratic_equation(D, E, F, xs); - n_xs = xs_end - xs; + Algebraic* xs_end = nt_traits->solve_quadratic_equation(D, E, F, xs); + std::ptrdiff_t n_xs = xs_end - xs; - if (n_xs == 0) - { + if (n_xs == 0) { return o; // no intersection } - if (n_xs == 1) - { + if (n_xs == 1) { // intersection is a point Point_2 inter_point(xs[0], (-2*a_diff*xs[0] + m)/(2*b_diff) ); *o++ = make_object(inter_point); @@ -348,16 +325,15 @@ public: // equation (1) is: // 2(a1-a2)x + 2(b1-b2)y - m = 0 - Curve_2 res(0,0,0, 2*a_diff, 2*b_diff, -m, COLLINEAR, end1, end2); + Curve_2 res = + ctr_cv(0,0,0, 2*a_diff, 2*b_diff, -m, COLLINEAR, end1, end2); parent.add_curve_to_output(res, o); //*o++ = make_object(Intersection_curve(res, TRANSVERSAL)); } - } // now the potential intersection is (a part of) a circle, // and the projection is (a part of) an ellipse - else - { + else { // here we have c1 != c2. // the intersection lies on the plane: // -2(a1-a2)x -2(b1-b2)y + m @@ -411,7 +387,7 @@ public: Rational sqr_c1 = c1*c1, sqr_c2 = c2*c2; Rational m = sqr_a1 + sqr_b1 + sqr_c1 - - sqr_a2 - sqr_b2 - sqr_c2 + sqr_r2 - sqr_r1; + sqr_a2 - sqr_b2 - sqr_c2 + sqr_r2 - sqr_r1; Rational R = 4*sqr_c_diff + 4*sqr_a_diff; Rational S = 4*sqr_c_diff + 4*sqr_b_diff; @@ -419,26 +395,20 @@ public: Rational U = -8*a1*sqr_c_diff + 8*c1*c_diff*a_diff - 4*m*a_diff; Rational V = -8*b1*sqr_c_diff + 8*c1*c_diff*b_diff - 4*m*b_diff; Rational W = 4*sqr_c_diff*(sqr_a1+sqr_b1+sqr_c1-sqr_r1) - - 4*m*c1*c_diff + m*m; + 4*m*c1*c_diff + m*m; // if the full spheres do not intersect, the equation we get has no // real solution, so we should check it: bool ellipse_is_point = false; - if (!parent.is_valid_conic_equation(R, S, T, U, V, W, - ellipse_is_point)) - { + if (! parent.is_valid_conic_equation(R, S, T, U, V, W, ellipse_is_point)) return o; - } // we need only a part of the ellipse (as stated in (**)) so we // construct the cutting line, which is: // equation (*) <= min(c1,c2) -- for lower envelope // equation (*) >= max(c1,c2) -- for upper envelope - Rational z_plane; - if (parent.m_is_lower) - z_plane = ((c1 < c2) ? c1 : c2); - else - z_plane = ((c1 > c2) ? c1 : c2); + Rational z_plane = (parent.m_is_lower) ? + ((c1 < c2) ? c1 : c2) : ((c1 > c2) ? c1 : c2); // we get (for lower envelope) @@ -452,33 +422,30 @@ public: // for upper envelope, we should multiply the line equation by -1 int envelope_coef = 1; - if (!parent.m_is_lower) - envelope_coef = -1; + if (! parent.m_is_lower) envelope_coef = -1; Sign sign_c_diff = CGAL_NTS sign(c_diff); Rational la = envelope_coef*2*a_diff*sign_c_diff; Rational lb = envelope_coef*2*b_diff*sign_c_diff; Rational lc = envelope_coef*sign_c_diff*(2*c_diff*z_plane - m); - if (ellipse_is_point) - { + if (ellipse_is_point) { // as specified in the is_valid_conic_equation method, the // intersection point is: // Rational px = S*(4*U - T*V)/(T*T - 4*S*R); px = px / 2; - Rational py = -(T*px + V)/(2*S); + Rational py = -(T*px + V)/(2*S); // should check if the point is in the non-negative side of the // line - if (CGAL_NTS sign(la*px + lb*py +lc) != NEGATIVE) - { - *o++ = make_object(Point_2(px, py)); - } + if (CGAL_NTS sign(la*px + lb*py +lc) != NEGATIVE) + *o++ = make_object(Point_2(px, py)); return o; - } + } // EBEB 2012/06/29: Added because of - // no matching function for call to 'compare(CGAL::Env_sphere_traits_3::Rational&, int) + // no matching function for call to + // compare(CGAL::Env_sphere_traits_3::Rational&, int) Rational zero(0); // if (a1==a2) and (b1==b2) (*) is a plane parallel to the xy-plane @@ -490,9 +457,8 @@ public: CGAL_NTS compare(b_diff, zero) == EQUAL) { Sign sign_lc = CGAL_NTS sign(lc); - if (sign_lc != NEGATIVE) - { - Curve_2 res(R, S, T, U, V, W); + if (sign_lc != NEGATIVE) { + Curve_2 res = ctr_cv(R, S, T, U, V, W); parent.add_curve_to_output(res, o); //*o++ = make_object(Intersection_curve(res, TRANSVERSAL)); } @@ -505,31 +471,29 @@ public: // R*x^2 + S*y^2 + T*xy + U*x + V*y + W = 0 Alg_point_2 source, target, pmid; std::ptrdiff_t n_inter_points; - if (CGAL_NTS compare(lb, zero) != EQUAL) - { + if (CGAL_NTS compare(lb, zero) != EQUAL) { // Find the x-coordinates of the intersection points of the conic // curve and the line y = -(la*x + lc) / lb: // we get a quadratic equation Ax^2 + Bx + C = 0 // where A = lb*lb*R + la*(la*S - lb*T) // B = 2*la*lc*S - lb*(lc*T + la*V - lb*U) // C = S*lc*lc + lb*(lb*W - lc*V) - Rational A = lb*lb*R + la*(la*S - lb*T), - B = 2*la*lc*S - lb*(lc*T + la*V - lb*U), - C = S*lc*lc + lb*(lb*W - lc*V); + Rational A = lb*lb*R + la*(la*S - lb*T); + Rational B = 2*la*lc*S - lb*(lc*T + la*V - lb*U); + Rational C = S*lc*lc + lb*(lb*W - lc*V); - Algebraic inter_xs[2]; - Algebraic *inter_xs_end; + Algebraic inter_xs[2]; + Algebraic* inter_xs_end; - inter_xs_end = nt_traits.solve_quadratic_equation(A, B, C, inter_xs); + inter_xs_end = nt_traits->solve_quadratic_equation(A, B, C, inter_xs); n_inter_points = inter_xs_end - inter_xs; if (n_inter_points > 0) - source = Alg_point_2(inter_xs[0], - -(la*inter_xs[0] + lc) / Algebraic(lb)); - if (n_inter_points == 2) - { - target = Alg_point_2(inter_xs[1], - -(la*inter_xs[1] + lc) / Algebraic(lb)); + source = + Alg_point_2(inter_xs[0], -(la*inter_xs[0] + lc) / Algebraic(lb)); + if (n_inter_points == 2) { + target = + Alg_point_2(inter_xs[1], -(la*inter_xs[1] + lc) / Algebraic(lb)); // Get the conic points whose x-coordinate are in the middle of the // two endpoints. @@ -542,30 +506,30 @@ public: CGAL_precondition_code(int x_mid_n_y_points;); Alg_point_2 x_mid_y_points[2]; - Curve_2 inter_cv(R, S, T, U, V, W); + Curve_2 inter_cv = ctr_cv(R, S, T, U, V, W); CGAL_precondition_code(x_mid_n_y_points = ) - inter_cv.points_at_x(x_mid_point, x_mid_y_points); + gt_2->points_at_x(inter_cv, x_mid_point, x_mid_y_points); CGAL_precondition(x_mid_n_y_points > 0); Algebraic y1 = x_mid_y_points[0].y(), y2 = x_mid_y_points[1].y(); - if (CGAL_NTS compare(Algebraic(la)*x_mid + Algebraic(lb)*y1 + Algebraic(lc), - Algebraic(0) - ) == LARGER) - { + if (CGAL_NTS compare(Algebraic(la)*x_mid + Algebraic(lb)*y1 + + Algebraic(lc), + Algebraic(0)) == LARGER) + { pmid = Alg_point_2(x_mid, y1); } - else - { - CGAL_assertion(CGAL_NTS compare(Algebraic(la)*x_mid + Algebraic(lb)*y2 + Algebraic(lc), + else { + CGAL_assertion(CGAL_NTS compare(Algebraic(la)*x_mid + + Algebraic(lb)*y2 + Algebraic(lc), Algebraic(0)) == LARGER); pmid = Alg_point_2(x_mid, y2); } } } - else - { // lb == 0 + else { + // lb == 0 CGAL_assertion(CGAL_NTS compare(la, zero) != EQUAL); // Find the intersection of the vertical line x = -lc / la: @@ -574,21 +538,20 @@ public: // where A = S // B = T*inter_x + V // C = R*inter_x^2 + U*inter_x + W - Rational A = S, - B = T*inter_x + V, - C = R*inter_x*inter_x + U*inter_x + W; + Rational A = S; + Rational B = T*inter_x + V; + Rational C = R*inter_x*inter_x + U*inter_x + W; - Algebraic inter_points[2]; - Algebraic *inter_points_end; + Algebraic inter_points[2]; + Algebraic* inter_points_end; inter_points_end = - nt_traits.solve_quadratic_equation(A, B, C, inter_points); + nt_traits->solve_quadratic_equation(A, B, C, inter_points); n_inter_points = inter_points_end - inter_points; if (n_inter_points > 0) source = Alg_point_2(Algebraic(inter_x), inter_points[0]); - if (n_inter_points == 2) - { + if (n_inter_points == 2) { target = Alg_point_2(Algebraic(inter_x), inter_points[1]); // Get the conic points whose y-coordinate are in the middle of the @@ -599,32 +562,30 @@ public: Alg_point_2 y_mid_point(0, y_mid); Alg_point_2 y_mid_x_points[2]; - Curve_2 inter_cv(R, S, T, U, V, W); - - CGAL_precondition_code(int y_mid_n_x_points =) - inter_cv.points_at_y(y_mid_point, y_mid_x_points); + Curve_2 inter_cv = ctr_cv(R, S, T, U, V, W); + CGAL_precondition_code(int y_mid_n_x_points =) + gt_2->points_at_y(inter_cv, y_mid_point, y_mid_x_points); CGAL_precondition(y_mid_n_x_points > 0); Algebraic x1 = y_mid_x_points[0].x(), x2 = y_mid_x_points[1].x(); - if (CGAL_NTS compare( - Algebraic(la)*x1 + Algebraic(lb)*y_mid + Algebraic(lc), - Algebraic(0)) == LARGER) + if (CGAL_NTS compare(Algebraic(la)*x1 + Algebraic(lb)*y_mid + + Algebraic(lc), + Algebraic(0)) == LARGER) { pmid = Alg_point_2(x1, y_mid); } - else - { - CGAL_assertion(CGAL_NTS compare ( - Algebraic(la)*x2 + Algebraic(lb)*y_mid + Algebraic(lc), - Algebraic(0)) == LARGER); + else { + CGAL_assertion(CGAL_NTS compare(Algebraic(la)*x2 + + Algebraic(lb)*y_mid + + Algebraic(lc), + Algebraic(0)) == LARGER); pmid = Alg_point_2(x2, Algebraic(y_mid)); } } } - if (n_inter_points < 2) - { + if (n_inter_points < 2) { // we should check whether the ellipse is in the positive side of the // line - in which case we return the full ellipse // or not - in which case there is no intersection if @@ -634,31 +595,27 @@ public: // for this, we find a point inside the ellipse and substitute // its coordinates in the line equation - Curve_2 inter_cv(R, S, T, U, V, W); + Curve_2 inter_cv = ctr_cv(R, S, T, U, V, W); Alg_point_2 vtan_ps[2]; - CGAL_assertion_code(int n_vtan_ps =) - inter_cv.vertical_tangency_points(vtan_ps); - + CGAL_assertion_code(int n_vtan_ps =) + gt_2->vertical_tangency_points(inter_cv, vtan_ps); CGAL_assertion(n_vtan_ps == 2); Algebraic lval = Algebraic(la)*vtan_ps[0].x() + Algebraic(lb)*vtan_ps[0].y() + Algebraic(lc); Sign lval_sign = CGAL_NTS sign(lval); - if (lval_sign == POSITIVE) - { + if (lval_sign == POSITIVE) { // the full ellipse is in the positive side parent.add_curve_to_output(inter_cv, o); //*o++ = make_object(Intersection_curve(inter_cv, TRANSVERSAL)); return o; } - else if (lval_sign == NEGATIVE) - { + else if (lval_sign == NEGATIVE) { // the full ellipse is in the negative side, except maybe the point // source in the case n_inter_points = 1 (which lies on the line) - if (n_inter_points == 1) - *o++ = make_object(Point_2(source)); + if (n_inter_points == 1) *o++ = make_object(Point_2(source)); return o; } @@ -667,16 +624,14 @@ public: // n_inter_points == 1 and source = vtan_ps[0] CGAL_assertion(n_inter_points == 1 && source == vtan_ps[0]); // so we try the other vertical tangency point - lval = Algebraic(la)*vtan_ps[1].x() + - Algebraic(lb)*vtan_ps[1].y() + Algebraic(lc); + lval = Algebraic(la)*vtan_ps[1].x() + Algebraic(lb)*vtan_ps[1].y() + + Algebraic(lc); lval_sign = CGAL_NTS sign(lval); CGAL_assertion(lval_sign != ZERO); - if (lval_sign == POSITIVE) - parent.add_curve_to_output(inter_cv, o); + if (lval_sign == POSITIVE) parent.add_curve_to_output(inter_cv, o); //*o++ = make_object(Intersection_curve(inter_cv, TRANSVERSAL)); - else - *o++ = make_object(Point_2(source)); + else *o++ = make_object(Point_2(source)); return o; } @@ -688,15 +643,12 @@ public: // If the mid-point forms a left-turn with the source and the target // points, the orientation is positive (going counterclockwise). // Otherwise, it is negative (going clockwise). - Alg_kernel k; - typename Alg_kernel::Orientation_2 orient_f = k.orientation_2_object(); - Orientation orient; - if (orient_f(source, pmid, target) == LEFT_TURN) - orient = CGAL::COUNTERCLOCKWISE; - else - orient = CGAL::CLOCKWISE; + auto alg_kernel = gt_2->alg_kernel(); + auto orient_f = alg_kernel->orientation_2_object(); + Orientation orient = (orient_f(source, pmid, target) == LEFT_TURN) ? + CGAL::COUNTERCLOCKWISE : CGAL::CLOCKWISE; - Curve_2 res(R, S, T, U, V, W, orient, source, target); + Curve_2 res = ctr_cv(R, S, T, U, V, W, orient, source, target); CGAL_assertion(res.is_valid()); parent.add_curve_to_output(res, o); //*o++ = make_object(Intersection_curve(res, TRANSVERSAL)); @@ -709,18 +661,14 @@ public: /*! Get a Construct_projected_intersections_2 functor object. */ Construct_projected_intersections_2 construct_projected_intersections_2_object() const - { - return Construct_projected_intersections_2(this); - } + { return Construct_projected_intersections_2(this); } - class Compare_z_at_xy_3 - { + class Compare_z_at_xy_3 { protected: - const Self & parent; + const Self& parent; public: - Compare_z_at_xy_3(const Self * p) : parent(*p) - {} + Compare_z_at_xy_3(const Self* p) : parent(*p) {} // check which of the surfaces is closer to the envelope at the xy // coordinates of point (i.e. lower if computing the lower envelope, or @@ -728,8 +676,7 @@ public: // precondition: the surfaces are defined in point Comparison_result operator()(const Point_2& p, const Xy_monotone_surface_3& s1, - const Xy_monotone_surface_3& s2) const - { + const Xy_monotone_surface_3& s2) const { Comparison_result c2 = compare_in_point_second_method(p, s1, s2); CGAL_expensive_assertion_code( @@ -747,12 +694,10 @@ public: // answer is the same for each of these points Comparison_result operator()(const X_monotone_curve_2& cv, const Xy_monotone_surface_3& s1, - const Xy_monotone_surface_3& s2) const - { + const Xy_monotone_surface_3& s2) const { // we compute a middle point on cv and use the previous function Point_2 mid = parent.construct_middle_point(cv); - Comparison_result res = - parent.compare_z_at_xy_3_object()(mid, s1, s2); + Comparison_result res = parent.compare_z_at_xy_3_object()(mid, s1, s2); return res; } @@ -762,18 +707,15 @@ public: Comparison_result compare_in_point_first_method(const Point_2& p, const Xy_monotone_surface_3& s1, - const Xy_monotone_surface_3& s2) const - { + const Xy_monotone_surface_3& s2) const { // find the z coordinates of surface 1 over p Algebraic z1 = parent.compute_envelope_z_in_point(p, s1); // find the z coordinates of surface 2 over p Algebraic z2 = parent.compute_envelope_z_in_point(p, s2); Sign res = CGAL_NTS sign(z1 - z2); - if (parent.m_is_lower) - return res; - else - return -res; + if (parent.m_is_lower) return res; + else return -res; } // second method of compare in point @@ -796,10 +738,14 @@ public: { Rat_point_3 p1 = s1.center(); Rat_point_3 p2 = s2.center(); - const Rational a1 = p1.x(), b1 = p1.y(), c1 = p1.z(), - a2 = p2.x(), b2 = p2.y(), c2 = p2.z(); - const Rational sqr_r1 = s1.squared_radius(), - sqr_r2 = s2.squared_radius(); + const Rational a1 = p1.x(); + const Rational b1 = p1.y(); + const Rational c1 = p1.z(); + const Rational a2 = p2.x(); + const Rational b2 = p2.y(); + const Rational c2 = p2.z(); + const Rational sqr_r1 = s1.squared_radius(); + const Rational sqr_r2 = s2.squared_radius(); const Algebraic x1 = p.x(), y1 = p.y(); Rational c_diff = c1 - c2; @@ -814,34 +760,28 @@ public: if (CGAL_NTS sign(A2) == NEGATIVE) std::cout << "A2 = " << A2 << std::endl; - Sign res; // sign_a_plus_b_x_sqrt_e_plus_c_x_sqrt_f is a CGAL method which // computes the sign of quantity: a + b * sqrt(e) + c * sqrt(f) - - res = CGAL::sign_a_plus_b_x_sqrt_e_plus_c_x_sqrt_f(Algebraic(c_diff), - Algebraic(-1), - Algebraic(1), - A1, - A2); + Sign res = + CGAL::sign_a_plus_b_x_sqrt_e_plus_c_x_sqrt_f(Algebraic(c_diff), + Algebraic(-1), + Algebraic(1), + A1, + A2); return res; } }; /*! Get a Compare_z_at_xy_3 functor object. */ Compare_z_at_xy_3 - compare_z_at_xy_3_object() const - { - return Compare_z_at_xy_3(this); - } + compare_z_at_xy_3_object() const { return Compare_z_at_xy_3(this); } - class Compare_z_at_xy_above_3 - { + class Compare_z_at_xy_above_3 { protected: - const Self & parent; + const Self& parent; public: - Compare_z_at_xy_above_3(const Self * p) : parent(*p) - {} + Compare_z_at_xy_above_3(const Self* p) : parent(*p) {} // check which of the surfaces is closer to the envelope on the points above // the curve cv (i.e. lower if computing the lower envelope, or upper if @@ -854,27 +794,20 @@ public: operator()(const X_monotone_curve_2& cv, const Xy_monotone_surface_3& s1, const Xy_monotone_surface_3& s2) const - { - Comparison_result res = parent.compare_on_side(cv, s1, s2, false); - return res; - } + { return parent.compare_on_side(cv, s1, s2, false); } }; /*! Get a Compare_z_at_xy_above_3 functor object. */ Compare_z_at_xy_above_3 compare_z_at_xy_above_3_object() const - { - return Compare_z_at_xy_above_3(this); - } + { return Compare_z_at_xy_above_3(this); } - class Compare_z_at_xy_below_3 - { + class Compare_z_at_xy_below_3 { protected: - const Self & parent; + const Self& parent; public: - Compare_z_at_xy_below_3(const Self * p) : parent(*p) - {} + Compare_z_at_xy_below_3(const Self* p) : parent(*p) {} Comparison_result operator()(const X_monotone_curve_2& cv, @@ -889,46 +822,40 @@ public: /*! Get a Compare_z_at_xy_below_3 functor object. */ Compare_z_at_xy_below_3 compare_z_at_xy_below_3_object() const - { - return Compare_z_at_xy_below_3(this); - } + { return Compare_z_at_xy_below_3(this); } /***************************************************************************/ // public method needed for testing // checks if point is in the xy-range of surf - class Is_defined_over - { + class Is_defined_over { protected: - const Self & parent; + const Self& parent; public: - Is_defined_over(const Self * p) : parent(*p) - {} + Is_defined_over(const Self* p) : parent(*p) {} // checks if point is in the xy-range of surf - bool operator()(const Point_2& p, const Xy_monotone_surface_3& s) const - { + bool operator()(const Point_2& p, const Xy_monotone_surface_3& s) const { // project the surface on the plane Rat_point_2 proj_center = parent.project(s.center()); Rat_circle_2 boundary(proj_center, s.squared_radius()); - Nt_traits nt_traits; - Alg_kernel k; + const auto gt_2 = parent.geometry_traits_2(); + auto nt_traits = gt_2->nt_traits(); Alg_point_2 aproj_center(proj_center.x(), proj_center.y()); - Alg_circle_2 aboundary(aproj_center, nt_traits.convert(s.squared_radius())); + Alg_circle_2 aboundary(aproj_center, nt_traits->convert(s.squared_radius())); // check if the projected point is inside the projected boundary - return (!k.has_on_unbounded_side_2_object()(aboundary, p)); + auto alg_kernel = gt_2->alg_kernel(); + return (! alg_kernel->has_on_unbounded_side_2_object()(aboundary, p)); } }; /*! Get a Is_defined_over functor object. */ Is_defined_over is_defined_over_object() const - { - return Is_defined_over(this); - } + { return Is_defined_over(this); } /***************************************************************************/ @@ -1005,64 +932,52 @@ public: // and we solve the problem as for triangles Rat_point_3 p1 = s1.center(); Rat_point_3 p2 = s2.center(); - const Rational a1 = p1.x(), b1 = p1.y(), c1 = p1.z(), - a2 = p2.x(), b2 = p2.y(), c2 = p2.z(); + const Rational a1 = p1.x(); + const Rational b1 = p1.y(); + const Rational c1 = p1.z(); + const Rational a2 = p2.x(); + const Rational b2 = p2.y(); + const Rational c2 = p2.z(); Algebraic A1 = x0 - a1, B1 = y0 - b1, C1 = z0 - c1; Algebraic A2 = x0 - a2, B2 = y0 - b2, C2 = z0 - c2; - if (C1 != 0 && C2 != 0) - { + if (C1 != 0 && C2 != 0) { Sign sign1 = CGAL_NTS sign((A2*A3+B2*B3)/C2-(A1*A3+B1*B3)/C1); // to make sure the direction is correct, we take a second point on the // line: for vertical line we take (x0, y0+1) // otherwise we take (x0+1, y0+ m/n) Algebraic x1, y1; - if (n == 0) - { + if (n == 0) { x1 = x0; y1 = y0+1; } - else - { + else { x1 = x0+1; y1 = y0 + (m/n); } Sign sign2 = CGAL_NTS sign(-B3*x1+A3*y1-(-B3*x0+A3*y0)); // the answer negates according to the side of the line we ask of - Sign sign3 = (compare_on_right ? (CGAL_NTS sign(1)) : - (CGAL_NTS sign(-1))); + Sign sign3 = (compare_on_right ? (CGAL_NTS sign(1)) : (CGAL_NTS sign(-1))); return sign1 * sign2 * sign3; } - else if (C1 != 0 && C2 == 0) - { - // sphere 2 is on the envelope (both lower & upper) - return LARGER; - } - else if (C1 == 0 && C2 != 0) - - { - // sphere 1 is on the envelope (both lower & upper) - return SMALLER; - } - else - CGAL_error(); - + // sphere 2 is on the envelope (both lower & upper) + else if (C1 != 0 && C2 == 0) return LARGER; + // sphere 1 is on the envelope (both lower & upper) + else if (C1 == 0 && C2 != 0) return SMALLER; + else CGAL_error(); return EQUAL; } Rat_point_2 project(const Rat_point_3& p) const - { - return Rat_point_2(p.x(), p.y()); - } + { return Rat_point_2(p.x(), p.y()); } // compute the z coordinate of the surface s in point p on the envelope // (i.e. take lower point if lower envelope, upper otherwise) // precondition: s is defined at p Algebraic compute_envelope_z_in_point(const Point_2& p, - const Xy_monotone_surface_3& s) const - { + const Xy_monotone_surface_3& s) const { Algebraic res; // the point coordinates @@ -1079,57 +994,49 @@ public: // z^2 - 2cz + [(x1-a)^2 + (y1-b)^2 + c^2 - r^2] = 0 Algebraic x_diff = x1 - a, y_diff = y1 - b; // the coefficients are: - Algebraic A = 1, - B = -2*c, - C = x_diff*x_diff + y_diff*y_diff + c*c - sqr_r; + Algebraic A = 1; + Algebraic B = -2*c; + Algebraic C = x_diff*x_diff + y_diff*y_diff + c*c - sqr_r; Algebraic zs[2]; - Algebraic *zs_end; + Algebraic* zs_end; std::ptrdiff_t n_zs; - Nt_traits nt_traits; - zs_end = nt_traits.solve_quadratic_equation(A, B, C, zs); + auto nt_traits = m_geometry_traits_2->nt_traits(); + zs_end = nt_traits->solve_quadratic_equation(A, B, C, zs); n_zs = zs_end - zs; CGAL_precondition(n_zs > 0); - if (n_zs == 1) - // only one point is defined at p, this is the result - return zs[0]; + // only one point is defined at p, this is the result + if (n_zs == 1) return zs[0]; CGAL_assertion(n_zs == 2); Comparison_result comp = CGAL_NTS compare(zs[0], zs[1]); - if (m_is_lower) - res = ((comp == SMALLER) ? zs[0] : zs[1]); - else - res = ((comp == LARGER) ? zs[0] : zs[1]); - + if (m_is_lower) res = ((comp == SMALLER) ? zs[0] : zs[1]); + else res = ((comp == LARGER) ? zs[0] : zs[1]); return res; } // construct the point in the middle of cv - Point_2 construct_middle_point(const X_monotone_curve_2& cv) const - { + Point_2 construct_middle_point(const X_monotone_curve_2& cv) const { // get the x-value of the middle point - Alg_kernel k; - Alg_point_2 mid_x = k.construct_midpoint_2_object()(cv.source(), - cv.target()); + auto alg_kernel = m_geometry_traits_2->alg_kernel(); + Alg_point_2 mid_x = + alg_kernel->construct_midpoint_2_object()(cv.source(), cv.target()); -// TODO_NEW_DESIGN - this is not implemented in X_monotone_curve_2, but maybe we want it there? -// if (cv.is_segment()) -// return mid_x; - if (cv.is_vertical()) - return Point_2(mid_x); - - return Point_2(cv.point_at_x(mid_x)); + // TODO_NEW_DESIGN - this is not implemented in X_monotone_curve_2, but + // maybe we want it there? + // if (cv.is_segment()) return mid_x; + if (cv.is_vertical()) return Point_2(mid_x); + return Point_2(m_geometry_traits_2->point_at_x(cv, mid_x)); } // for the test - Point_2 construct_middle_point(const Point_2& p1, const Point_2& p2) const - { - Alg_kernel k; - return Point_2(k.construct_midpoint_2_object()(p1, p2)); + Point_2 construct_middle_point(const Point_2& p1, const Point_2& p2) const { + auto alg_kernel = m_geometry_traits_2->alg_kernel(); + return Point_2(alg_kernel->construct_midpoint_2_object()(p1, p2)); } // check if the equation @@ -1139,8 +1046,7 @@ public: template bool is_valid_conic_equation(const NT& r, const NT& s, const NT& t, const NT& u, const NT& v, const NT& w, - bool &is_point) const - { + bool& is_point) const { // initialize is_point to false, and will change it when we detect // that the equation represents a point is_point = false; @@ -1160,16 +1066,14 @@ public: // (the conic equation in this case represents hyperbola or 2 // intersecting lines) Sign sign_A = CGAL_NTS sign(t*t - 4*s*r); - if (sign_A == POSITIVE) - return true; + if (sign_A == POSITIVE) return true; // if A < 0 we have a sad parabula, so we should check if it crosses the // x-axis, i.e. if the equation f(x) = 0 has a real solution x. // this means that discriminant(f(x)) >= 0 // discriminant(f(x)) = B^2 - 4AC // = (2tv-4su)^2 - 4(t^2-4sr)(v^2-4sw) // = s(-tvu + su^2 + wt^2 + rv^2 - 4srw) - if (sign_A == NEGATIVE) - { + if (sign_A == NEGATIVE) { // (in this case the conic equation represents ellipse, circle, point // or no curve) Sign sign_s = CGAL_NTS sign(s); @@ -1178,9 +1082,7 @@ public: // solution for f(x), say x0. since we get f(x0)=0 and f(x)<0 forall // x!=x0, we have only one solution for (**). So the equation represents // a point with coordinates x0=-B/2A, y0=-(tx0 + v)/2s - if (sign_eq == ZERO) - is_point = true; - + if (sign_eq == ZERO) is_point = true; Sign sign_disc = CGAL_NTS sign(int(sign_s * sign_eq)); return (sign_disc != NEGATIVE); } @@ -1192,47 +1094,36 @@ public: // (in this case the conic equation represents parabola, 2 parallel lines, // 1 line or no curve) Sign sign_B = CGAL_NTS sign(s*(t*v - 4*u)); - if (sign_B != ZERO) - return true; + if (sign_B != ZERO) return true; Sign sign_C = CGAL_NTS sign(v*v - 4*s*w); - return (sign_C != NEGATIVE); } // for the test: - Point_2 vertical_ray_shoot_2(const Point_2& pt, - const X_monotone_curve_2& cv) const + Point_2 vertical_ray_shoot_2(const Point_2& pt, const X_monotone_curve_2& cv) + const { - if (cv.is_vertical()) - { - Alg_kernel k; - if (!k.less_y_2_object()(cv.left(), pt)) + if (cv.is_vertical()) { + auto alg_kernel = m_geometry_traits_2->alg_kernel(); + if (! alg_kernel->less_y_2_object()(cv.left(), pt)) return cv.left(); - else - { - CGAL_assertion(k.less_y_2_object()(cv.right(), pt)); + else { + CGAL_assertion(alg_kernel->less_y_2_object()(cv.right(), pt)); return cv.right(); } } - else - return cv.point_at_x(pt); + else return m_geometry_traits_2->point_at_x(cv, pt); } - template - OutputIterator add_curve_to_output(const Curve_2& c, OutputIterator oi) const - { + template + OutputIterator add_curve_to_output(const Curve_2& c, OutputIterator oi) const { Object objs[2]; Object* p_obj = this->make_x_monotone_2_object()(c, objs); - for(Object* o = objs; o != p_obj; ++o) - { + for(Object* o = objs; o != p_obj; ++o) { X_monotone_curve_2 cv; - if(assign(cv, *o)) - { - *oi++ = make_object(Intersection_curve(cv, 1)); - } - else - { + if(assign(cv, *o)) *oi++ = make_object(Intersection_curve(cv, 1)); + else { Point_2 pt; CGAL_assertion(assign(pt, *o)); assign(pt, *o); @@ -1242,45 +1133,54 @@ public: return oi; } + typedef std::shared_ptr Shared_geometry_traits_2; + /*! Default constructor. */ - Env_sphere_traits_3() : m_is_lower(true) + Env_sphere_traits_3() : + m_is_lower(true), + m_geometry_traits_2(new Traits_2) {} + /*! Constructor from a conic 2D geometry traits. */ + Env_sphere_traits_3(Shared_geometry_traits_2 geometry_traits_2) : + m_is_lower(true), + m_geometry_traits_2(geometry_traits_2) + {} + + /*! Obtain the undelying conic 2D geometry traits. + */ + const Shared_geometry_traits_2 geometry_traits_2() const + { return m_geometry_traits_2; } + protected: mutable bool m_is_lower; + +private: + //! The conic geometry-traits. + const Shared_geometry_traits_2 m_geometry_traits_2; }; /*! * Compare two spheres: first compare their center points in an * xyz-lexicographic order, then by their radii. */ -template -bool operator< (const CGAL::Sphere_3 & a, - const CGAL::Sphere_3 & b) +template +bool operator<(const CGAL::Sphere_3& a, const CGAL::Sphere_3& b) { - Kernel k; + Kernel k; Comparison_result res = k.compare_xyz_3_object()(a.center(), b.center()); - - if (res == EQUAL) - { - res = CGAL::compare (a.squared_radius(), b.squared_radius()); - } - + if (res == EQUAL) res = CGAL::compare (a.squared_radius(), b.squared_radius()); return (res == SMALLER); } /*! * Compare two spheres for equality. */ -template +template bool operator== (const typename Kernel::Sphere_3& a, - const typename Kernel::Sphere_3& b) -{ - Kernel k; - - if (! k.equal_3_object() (a.center(), b.center())) - return (false); - + const typename Kernel::Sphere_3& b) { + Kernel k; + if (! k.equal_3_object() (a.center(), b.center())) return (false); return (CGAL::compare (a.squared_radius(), b.squared_radius()) == EQUAL); } From 488ba8c4e487e63fc4f9ac1b624e9a0618784b33 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 10 Aug 2022 23:32:42 +0300 Subject: [PATCH 072/105] Used the traits to construct conics and x-monotone conics (instead of direct constructors of the conics). --- .../Minkowski_sum_2/Exact_offset_base_2.h | 181 ++++++++---------- 1 file changed, 76 insertions(+), 105 deletions(-) diff --git a/Minkowski_sum_2/include/CGAL/Minkowski_sum_2/Exact_offset_base_2.h b/Minkowski_sum_2/include/CGAL/Minkowski_sum_2/Exact_offset_base_2.h index f3cf0bb7bfa..ca77157ec5c 100644 --- a/Minkowski_sum_2/include/CGAL/Minkowski_sum_2/Exact_offset_base_2.h +++ b/Minkowski_sum_2/include/CGAL/Minkowski_sum_2/Exact_offset_base_2.h @@ -28,11 +28,9 @@ namespace CGAL { * A base class for computing the offset of a given polygon by a given * radius in an exact manner. */ -template -class Exact_offset_base_2 -{ +template +class Exact_offset_base_2 { private: - typedef Traits_ Traits_2; // Rational kernel types: @@ -48,7 +46,6 @@ protected: typedef Rational Basic_NT; private: - // Algebraic kernel types: typedef typename Traits_2::Alg_kernel Alg_kernel; typedef typename Alg_kernel::FT Algebraic; @@ -63,7 +60,6 @@ private: typedef CGAL::Gps_traits_2 Gps_traits_2; protected: - typedef CGAL::Polygon_2 Polygon_2; typedef CGAL::Polygon_with_holes_2 Polygon_with_holes_2; @@ -75,21 +71,15 @@ private: typedef typename Polygon_2::Vertex_circulator Vertex_circulator; protected: - typedef Arr_labeled_traits_2 Labeled_traits_2; - typedef typename Labeled_traits_2::X_monotone_curve_2 Labeled_curve_2; public: - /*! Default constructor. */ - Exact_offset_base_2 () - {} + Exact_offset_base_2() {} protected: - - /*! - * Compute the curves that constitute the offset of a simple polygon by a + /*! Compute the curves that constitute the offset of a simple polygon by a * given radius. * \param pgn The polygon. * \param orient The orientation to traverse the vertices. @@ -99,16 +89,16 @@ protected: * \pre The value type of the output iterator is Labeled_curve_2. * \return A past-the-end iterator for the holes container. */ - template - OutputIterator _offset_polygon (const Polygon_2& pgn, - CGAL::Orientation orient, - const Rational& r, - unsigned int cycle_id, - OutputIterator oi) const + template + OutputIterator _offset_polygon(const Polygon_2& pgn, + CGAL::Orientation orient, + const Rational& r, + unsigned int cycle_id, + OutputIterator oi) const { // Prepare circulators over the polygon vertices. - const bool forward = (pgn.orientation() == orient); - Vertex_circulator first, curr, next; + const bool forward = (pgn.orientation() == orient); + Vertex_circulator first, curr, next; first = pgn.vertices_circulator(); curr = first; @@ -116,38 +106,33 @@ protected: // Traverse the polygon vertices and edges and construct the arcs that // constitute the single convolution cycle. - Alg_kernel alg_ker; - typename Alg_kernel::Equal_2 f_equal = alg_ker.equal_2_object(); + const Rational sqr_r = CGAL::square (r); + Rational x1, y1; // The source of the current edge. + Rational x2, y2; // The target of the current edge. + Rational delta_x, delta_y; // (x2 - x1) and (y2 - y1), resp. + Algebraic len; // The length of the current edge. + Algebraic trans_x, trans_y; // The translation vector. + Alg_point_2 op1, op2; // The edge points of the offset edge. + Alg_point_2 first_op; // The first offset point. + Algebraic a, b, c; - Nt_traits nt_traits; - const Rational sqr_r = CGAL::square (r); - const Algebraic alg_r = nt_traits.convert (r); - Rational x1, y1; // The source of the current edge. - Rational x2, y2; // The target of the current edge. - Rational delta_x, delta_y; // (x2 - x1) and (y2 - y1), resp. - Algebraic len; // The length of the current edge. - Algebraic trans_x, trans_y; // The translation vector. - Alg_point_2 op1, op2; // The edge points of the offset edge. - Alg_point_2 first_op; // The first offset point. - Algebraic a, b, c; + unsigned int curve_index(0); + std::list xobjs; - unsigned int curve_index = 0; - Traits_2 traits; - std::list xobjs; - std::list::iterator xobj_it; - typename Traits_2::Make_x_monotone_2 - f_make_x_monotone = traits.make_x_monotone_2_object(); - Curve_2 arc; - X_monotone_curve_2 xarc; - bool assign_success; + Traits_2 traits; + auto nt_traits = traits.nt_traits(); + const Algebraic alg_r = nt_traits->convert(r); + auto f_make_x_monotone = traits.make_x_monotone_2_object(); - do - { + auto alg_ker = traits.alg_kernel(); + auto f_equal = alg_ker->equal_2_object(); + + bool assign_success; + + do { // Get a circulator for the next vertex (in the proper orientation). - if (forward) - ++next; - else - --next; + if (forward) ++next; + else --next; // Compute the vector v = (delta_x, delta_y) of the current edge, // and compute the edge length ||v||. @@ -158,8 +143,8 @@ protected: delta_x = x2 - x1; delta_y = y2 - y1; - len = nt_traits.sqrt (nt_traits.convert (CGAL::square (delta_x) + - CGAL::square (delta_y))); + len = nt_traits->sqrt(nt_traits->convert(CGAL::square(delta_x) + + CGAL::square(delta_y))); // The angle theta between the vector v and the x-axis is given by: // @@ -174,45 +159,39 @@ protected: // // trans_x = r*cos(alpha - PI/2) = r*sin(alpha) // trans_y = r*sin(alpha - PI/2) = -r*cos(alpha) - trans_x = nt_traits.convert (r * delta_y) / len; - trans_y = nt_traits.convert (-r * delta_x) / len; + trans_x = nt_traits->convert(r * delta_y) / len; + trans_y = nt_traits->convert(-r * delta_x) / len; // Construct the first offset vertex, which corresponds to the // source vertex of the current polygon edge. - op1 = Alg_point_2 (nt_traits.convert (x1) + trans_x, - nt_traits.convert (y1) + trans_y); + op1 = Alg_point_2(nt_traits->convert(x1) + trans_x, + nt_traits->convert(y1) + trans_y); - if (curr == first) - { + if (curr == first) { // This is the first edge we visit -- store op1 for future use. first_op = op1; } - else - { - if (! f_equal (op2, op1)) - { + else { + if (! f_equal (op2, op1)) { // Connect op2 (from the previous iteration) and op1 with a circular // arc, whose supporting circle is (x1, x2) with radius r. - arc = Curve_2 (Rat_circle_2 (*curr, sqr_r), - CGAL::COUNTERCLOCKWISE, - op2, op1); + auto ctr_cv = traits.construct_curve_2_object(); + Curve_2 arc = ctr_cv(Rat_circle_2 (*curr, sqr_r), + CGAL::COUNTERCLOCKWISE, op2, op1); // Subdivide the arc into x-monotone subarcs and append them to the // convolution cycle. xobjs.clear(); - f_make_x_monotone (arc, std::back_inserter(xobjs)); + f_make_x_monotone(arc, std::back_inserter(xobjs)); - for (xobj_it = xobjs.begin(); xobj_it != xobjs.end(); ++xobj_it) - { - assign_success = CGAL::assign (xarc, *xobj_it); + for (auto xobj_it = xobjs.begin(); xobj_it != xobjs.end(); ++xobj_it) { + X_monotone_curve_2 xarc; + assign_success = CGAL::assign(xarc, *xobj_it); CGAL_assertion (assign_success); CGAL_USE(assign_success); - *oi = Labeled_curve_2 (xarc, - X_curve_label (xarc.is_directed_right(), - cycle_id, - curve_index)); - ++oi; + *oi++ = Labeled_curve_2(xarc, X_curve_label(xarc.is_directed_right(), + cycle_id, curve_index)); curve_index++; } } @@ -220,25 +199,21 @@ protected: // Construct the second offset vertex, which corresponds to the // target vertex of the current polygon edge. - op2 = Alg_point_2 (nt_traits.convert (x2) + trans_x, - nt_traits.convert (y2) + trans_y); + op2 = Alg_point_2(nt_traits->convert(x2) + trans_x, + nt_traits->convert(y2) + trans_y); // The equation of the line connecting op1 and op2 is given by: // // (y1 - y2)*x + (x2 - x1)*y + (r*len - y1*x2 - x1*y2) = 0 // - a = nt_traits.convert (-delta_y); - b = nt_traits.convert (delta_x); - c = alg_r*len - nt_traits.convert (y1*x2 - x1*y2); + a = nt_traits->convert(-delta_y); + b = nt_traits->convert(delta_x); + c = alg_r*len - nt_traits->convert(y1*x2 - x1*y2); - xarc = X_monotone_curve_2 (a, b, c, - op1, op2); - - *oi = Labeled_curve_2 (xarc, - X_curve_label (xarc.is_directed_right(), - cycle_id, - curve_index)); - ++oi; + auto ctr_xcv = traits.construct_x_monotone_curve_2_object(); + X_monotone_curve_2 xarc = ctr_xcv(a, b, c, op1, op2); + *oi++ = Labeled_curve_2(xarc, X_curve_label(xarc.is_directed_right(), + cycle_id, curve_index)); curve_index++; // Proceed to the next polygon vertex. @@ -246,42 +221,38 @@ protected: } while (curr != first); - if (! f_equal (op2, first_op)) - { + if (! f_equal (op2, first_op)) { // Close the convolution cycle by creating the final circular arc, // centered at the first vertex. - arc = Curve_2 (Rat_circle_2 (*first, sqr_r), - CGAL::COUNTERCLOCKWISE, - op2, first_op); + auto ctr_cv = traits.construct_curve_2_object(); + Curve_2 arc = ctr_cv(Rat_circle_2 (*first, sqr_r), + CGAL::COUNTERCLOCKWISE, op2, first_op); // Subdivide the arc into x-monotone subarcs and append them to the // convolution cycle. - bool is_last; + bool is_last; xobjs.clear(); - f_make_x_monotone (arc, std::back_inserter(xobjs)); + f_make_x_monotone(arc, std::back_inserter(xobjs)); - xobj_it = xobjs.begin(); - while (xobj_it != xobjs.end()) - { - assign_success = CGAL::assign (xarc, *xobj_it); + auto xobj_it = xobjs.begin(); + while (xobj_it != xobjs.end()) { + X_monotone_curve_2 xarc; + assign_success = CGAL::assign(xarc, *xobj_it); CGAL_assertion (assign_success); CGAL_USE(assign_success); ++xobj_it; is_last = (xobj_it == xobjs.end()); - *oi = Labeled_curve_2 (xarc, - X_curve_label (xarc.is_directed_right(), - cycle_id, - curve_index, - is_last)); - ++oi; + *oi++ = Labeled_curve_2(xarc, X_curve_label(xarc.is_directed_right(), + cycle_id, curve_index, + is_last)); curve_index++; } } - return (oi); + return oi; } }; From af119658428f7ed36b89264a2fd425b0ccd43164 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Thu, 1 Sep 2022 10:14:52 +0300 Subject: [PATCH 073/105] Used the Multiplicitly type (instead of unsigned int) --- Arrangement_on_surface_2/include/CGAL/Arrangement_zone_2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arrangement_zone_2.h b/Arrangement_on_surface_2/include/CGAL/Arrangement_zone_2.h index 42b1e919d23..2d843e35162 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arrangement_zone_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arrangement_zone_2.h @@ -155,7 +155,7 @@ protected: // the right endpoint it its interior. Point_2 m_intersect_p; // The next intersection point. - unsigned int m_ip_multiplicity; // Its multiplicity + Multiplicity m_ip_multiplicity; // Its multiplicity // (0 in case of an overlap). bool m_found_intersect; // An intersection has been found. // (or an overlap). From e09b73be5981671f6df056ddbb8c47a1c0268378 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Thu, 1 Sep 2022 10:15:16 +0300 Subject: [PATCH 074/105] Defined M_PI properly --- .../include/CGAL/Arr_circle_segment_traits_2.h | 3 ++- Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h index 55b17f4e850..2e9aed130e9 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h @@ -23,9 +23,10 @@ * The header file for the Arr_circle_segment_traits_2 class. */ -#include +// Keep the following 2 lines first. #define _USE_MATH_DEFINES #include +#include #include #include diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index d3625192503..40c48687b61 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -23,11 +23,12 @@ * The conic traits-class for the arrangement package. */ +// Keep the following 2 lines first. #define _USE_MATH_DEFINES +#include #include #include #include -#include #include #include @@ -2960,7 +2961,7 @@ public: // In case of a full conic (an ellipse or a circle), compute the // horizontal and vertical tangency points and use them to bound the arc. Alg_point_2 tan_ps[2]; - CGAL_assertion_code(int n_tan_ps); + CGAL_assertion_code(size_t n_tan_ps); CGAL_assertion_code (n_tan_ps = m_traits.vertical_tangency_points(xcv, tan_ps)); From 0d69f62beea148bee7e54d8b95a0a758d0630e86 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Mon, 5 Sep 2022 01:46:17 +0300 Subject: [PATCH 075/105] Initialized _m_location --- .../include/CGAL/Curved_kernel_via_analysis_2/Point_2.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Curved_kernel_via_analysis_2/Point_2.h b/Arrangement_on_surface_2/include/CGAL/Curved_kernel_via_analysis_2/Point_2.h index a5f7b53afae..8f82ebdb3f9 100644 --- a/Arrangement_on_surface_2/include/CGAL/Curved_kernel_via_analysis_2/Point_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Curved_kernel_via_analysis_2/Point_2.h @@ -75,8 +75,7 @@ public: typedef typename Curve_kernel_2::Curve_analysis_2 Curve_analysis_2; //! default constructor - Point_2_rep() { - } + Point_2_rep() : _m_location(CGAL::ARR_INTERIOR) {} //! constructs a "finite" point on curve, //! implies CGAL::NO_BOUNDARY in x/y From e0b44a32739ef1e0227ab540f8da83b94499d6b8 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 7 Sep 2022 20:02:55 +0300 Subject: [PATCH 076/105] (Temporarily restated deprecated functions. --- .../CGAL/Arr_geometry_traits/Conic_arc_2.h | 142 +++++- .../Conic_x_monotone_arc_2.h | 454 ++++++++++++++++++ 2 files changed, 589 insertions(+), 7 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h index 9f2f4ac9887..758c213510c 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_arc_2.h @@ -251,10 +251,10 @@ public: { // Get the circle properties. Rat_kernel ker; - Rat_point_2 center = ker.construct_center_2_object() (circ); + Rat_point_2 center = ker.construct_center_2_object()(circ); Rational x0 = center.x(); Rational y0 = center.y(); - Rational R_sqr = ker.compute_squared_radius_2_object() (circ); + Rational R_sqr = ker.compute_squared_radius_2_object()(circ); // Produce the correponding conic: if the circle center is (x0,y0) // and its squared radius is R^2, that its equation is: @@ -740,7 +740,7 @@ public: CGAL::to_double(m_target.y()) : CGAL::to_double(m_source.y()); // Go over the vertical tangency points and try to update the x-points. - Point_2 tan_ps[2]; + Alg_point_2 tan_ps[2]; int n_tan_ps; int i; @@ -774,12 +774,12 @@ protected: * \pre The vpts vector should be allocated at the size of 2. * \return The number of vertical tangency points. */ - CGAL_DEPRECATED int vertical_tangency_points(Point_2* vpts) const { + CGAL_DEPRECATED int vertical_tangency_points(Alg_point_2* vpts) const { // No vertical tangency points for line segments: if (m_orient == COLLINEAR) return 0; // Calculate the vertical tangency points of the supporting conic. - Point_2 ps[2]; + Alg_point_2 ps[2]; int n = _conic_vertical_tangency_points(ps); // Return only the points that are contained in the arc interior. @@ -802,12 +802,12 @@ protected: * \pre The hpts vector should be allocated at the size of 2. * \return The number of horizontal tangency points. */ - CGAL_DEPRECATED int horizontal_tangency_points(Point_2* hpts) const { + CGAL_DEPRECATED int horizontal_tangency_points(Alg_point_2* hpts) const { // No horizontal tangency points for line segments: if (m_orient == COLLINEAR) return 0; // Calculate the horizontal tangency points of the conic. - Point_2 ps[2]; + Alg_point_2 ps[2]; int n = _conic_horizontal_tangency_points(ps); // Return only the points that are contained in the arc interior. @@ -892,6 +892,134 @@ protected: } } + /*! Find the vertical tangency points of the undelying conic. + * \param ps The output points of vertical tangency. + * This area must be allocated at the size of 2. + * \return The number of vertical tangency points. + */ + CGAL_DEPRECATED + int _conic_vertical_tangency_points(Alg_point_2* ps) const { + const auto& cv = *this; + Nt_traits nt_traits; + + // In case the base conic is of degree 1 (and not 2), the arc has no + // vertical tangency points. + if (CGAL::sign(cv.s()) == ZERO) return 0; + + // We are interested in the x coordinates where the quadratic equation: + // s*y^2 + (t*x + v)*y + (r*x^2 + u*x + w) = 0 + // has a single solution (obviously if s = 0, there are no such points). + // We therefore demand that the discriminant of this equation is zero: + // (t*x + v)^2 - 4*s*(r*x^2 + u*x + w) = 0 + const Integer two(2); + const Integer four(4); + Algebraic xs[2]; + + auto r = cv.r(); + auto s = cv.s(); + auto t = cv.t(); + auto u = cv.u(); + auto v = cv.v(); + auto w = cv.w(); + Algebraic* xs_end = nt_traits.solve_quadratic_equation(t*t - four*r*s, + two*t*v - four*s*u, + v*v - four*s*w, + xs); + auto n_xs = static_cast(xs_end - xs); + + // Find the y-coordinates of the vertical tangency points. + Algebraic ys[2]; + Algebraic* ys_end; + int n_ys; + + if (CGAL::sign(cv.t()) == ZERO) { + // The two vertical tangency points have the same y coordinate: + ys[0] = nt_traits.convert(-v) / nt_traits.convert(two*s); + n_ys = 1; + } + else { + ys_end = nt_traits.solve_quadratic_equation(four*r*s*s - s*t*t, + four*r*s*v - two*s*t*u, + r*v*v - t*u*v + + t*t*w, + ys); + n_ys = static_cast(ys_end - ys); + } + + // Pair the x and y coordinates and obtain the vertical tangency points. + int n(0); + + for (int i = 0; i < n_xs; ++i) { + if (n_ys == 1) { + ps[n++] = Point_2(xs[i], ys[0]); + } + else { + for (int j = 0; j < n_ys; ++j) { + if (CGAL::compare(nt_traits.convert(two*s) * ys[j], + -(nt_traits.convert(t) * xs[i] + + nt_traits.convert(v))) == EQUAL) + { + ps[n++] = Point_2(xs[i], ys[j]); + break; + } + } + } + } + + CGAL_assertion(n <= 2); + return n; + } + + /*! Find the horizontal tangency points of the undelying conic. + * \param ps The output points of horizontal tangency. + * This area must be allocated at the size of 2. + * \return The number of horizontal tangency points. + */ + CGAL_DEPRECATED + size_t _conic_horizontal_tangency_points(Alg_point_2* ps) const { + const auto& cv = *this; + Nt_traits nt_traits; + + const Integer zero(0); + + // In case the base conic is of degree 1 (and not 2), the arc has no + // vertical tangency points. + if (CGAL::sign(cv.r()) == ZERO) return 0; + + // We are interested in the y coordinates were the quadratic equation: + // r*x^2 + (t*y + u)*x + (s*y^2 + v*y + w) = 0 + // has a single solution (obviously if r = 0, there are no such points). + // We therefore demand that the discriminant of this equation is zero: + // (t*y + u)^2 - 4*r*(s*y^2 + v*y + w) = 0 + const Integer two(2); + const Integer four(4); + Algebraic ys[2]; + + auto r = cv.r(); + auto s = cv.s(); + auto t = cv.t(); + auto u = cv.u(); + auto v = cv.v(); + auto w = cv.w(); + Algebraic* ys_end = nt_traits.solve_quadratic_equation(t*t - four*r*s, + two*t*u - four*r*v, + u*u - four*r*w, + ys); + auto n = static_cast(ys_end - ys); + + // Compute the x coordinates and construct the horizontal tangency points. + for (int i = 0; i < n; ++i) { + // Having computed y, x is the single solution to the quadratic equation + // above, and since its discriminant is 0, x is simply given by: + Algebraic x = -(nt_traits.convert(t)*ys[i] + nt_traits.convert(u)) / + nt_traits.convert(two*r); + ps[i] = Point_2(x, ys[i]); + } + + CGAL_assertion(n <= 2); + return n; + } + /*! Set the properties of a conic arc that is really a full curve * (that is, an ellipse). * \param rat_coeffs A vector of size 6, storing the rational coefficients diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h index fdc8d6c6ff6..811bba05525 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h @@ -476,6 +476,88 @@ public: } //@} + /*! Compute a point on an arc with the same \f$x\f$-coordiante as the given + * point. + * \param p The given point. + * \pre The arc is not vertical and `p` is in the \f$x\f$-range of the arc. + * \return A point on the arc with the same \f$x\f$-coordiante as `p`. + */ + CGAL_DEPRECATED + Point_2 point_at_x(const Point_2& p) const { + const auto& xcv = *this; + Alg_kernel alg_kernel; + + // Make sure that p is in the x-range of the arc. + CGAL_precondition(! xcv.is_vertical()); + + CGAL_precondition_code(auto cmp_x = alg_kernel.compare_x_2_object()); + CGAL_precondition((cmp_x(p, xcv.left()) != SMALLER) && + (cmp_x(p, xcv.right()) != LARGER)); + + if (xcv.is_special_segment()) { + // In case of a special segment, the equation of the supported line + // (a*x + b*y + c) = 0 is stored with the extra data field, and we + // simply have: + const auto& extra_data = xcv.extra_data(); + Algebraic y = -(extra_data->a*p.x() + extra_data->c) / extra_data->b; + + // Return the computed point. + return Point_2(p.x(), y); + } + + // Compute the y-coordinate according to the degree of the supporting + // conic curve. + typename Base::Nt_traits nt_traits; + Algebraic y; + + if (xcv.degree_mask() == Self::degree_1_mask()) { + // In case of a linear curve, the y-coordinate is a simple linear + // expression of x(p) (note that v is not 0 as the arc is not vertical): + // y = -(u*x(p) + w) / v + y = -(xcv.alg_u()*p.x() + xcv.alg_w()) / xcv.alg_v(); + } + else if (xcv.orientation() == COLLINEAR) { + const auto& extra_data = xcv.extra_data(); + CGAL_assertion(extra_data != nullptr); + + // In this case the equation of the supporting line is given by the + // extra data structure. + y = -(extra_data->a * p.x() + extra_data->c) / extra_data->b; + } + else { + CGAL_assertion(xcv.degree_mask() == Self::degree_2_mask()); + + // In this case the y-coordinate is one of solutions to the quadratic + // equation: + // s*y^2 + (t*x(p) + v)*y + (r*x(p)^2 + u*x(p) + w) = 0 + Algebraic A = xcv.alg_s(); + Algebraic B = xcv.alg_t()*p.x() + xcv.alg_v(); + Algebraic C = (xcv.alg_r()*p.x() + xcv.alg_u())*p.x() + xcv.alg_w(); + + if (CGAL::sign(xcv.s()) == ZERO) { + // In this case A is 0 and we have a linear equation. + CGAL_assertion(CGAL::sign(B) != ZERO); + + y = -C / B; + } + else { + // Solve the quadratic equation. + Algebraic disc = B*B - 4*A*C; + + CGAL_assertion(CGAL::sign(disc) != NEGATIVE); + + // We take either the root involving -sqrt(disc) or +sqrt(disc) + // based on the information flags. + y = (xcv.test_flag(Self::PLUS_SQRT_DISC_ROOT)) ? + (nt_traits.sqrt(disc) - B) / (2*A) : + -(B + nt_traits.sqrt(disc)) / (2*A); + } + } + + // Return the computed point. + return Point_2(p.x(), y); + } + /// \name Constructing points on the arc. //@{ @@ -568,8 +650,380 @@ public: return arc; } + + /*! Trim the arc given its new endpoints. + * \param ps The new source point. + * \param pt The new target point. + * \return The new trimmed arc. + * \pre Both ps and pt lies on the arc and must conform with the current + * direction of the arc. + */ + CGAL_DEPRECATED + Self trim(const Point_2& ps, const Point_2& pt) const { + auto& xcv = *this; + // Make sure that both ps and pt lie on the arc. + CGAL_precondition(contains_point(ps) && contains_point(pt)); + + // Make sure that the endpoints conform with the direction of the arc. + Alg_kernel alg_kernel; + Self res_xcv = xcv; + auto cmp_xy = alg_kernel.compare_xy_2_object(); + if (! ((xcv.test_flag(Self::IS_DIRECTED_RIGHT) && + (cmp_xy(ps, pt) == SMALLER)) || + (xcv.test_flag(Self::IS_DIRECTED_RIGHT) && + (cmp_xy(ps, pt) == LARGER)))) + { + // We are allowed to change the direction only in case of a segment. + CGAL_assertion(xcv.orientation() == COLLINEAR); + res_xcv.flip_flag(Self::IS_DIRECTED_RIGHT); + } + + // Make a copy of the current arc and assign its endpoints. + auto eq = alg_kernel.equal_2_object(); + if (! eq(ps, xcv.source())) { + res_xcv.set_source(ps); + + if (! ps.is_generating_conic(xcv.id())) + res_xcv.source().set_generating_conic(xcv.id()); + } + + if (! eq(pt, xcv.target())) { + res_xcv.set_target(pt); + + if (! pt.is_generating_conic(xcv.id())) + res_xcv.target().set_generating_conic(xcv.id()); + } + + return res_xcv; + } //@} + /*! Compare two arcs immediately to the leftt of their intersection point. + * \param xcv1 The first compared arc. + * \param xcv2 The second compared arc. + * \param p The reference intersection point. + * \return The relative position of the arcs to the left of `p`. + * \pre Both arcs we compare are not vertical segments. + */ + CGAL_DEPRECATED + Comparison_result compare_to_left(const Self& xcv2, const Point_2& p) const { + const auto& xcv1 = *this; + CGAL_precondition(! xcv1.is_vertical() && ! xcv2.is_vertical()); + + // In case one arc is facing upwards and another facing downwards, it is + // clear that the one facing upward is above the one facing downwards. + if (_has_same_supporting_conic(xcv2)) { + if (xcv1.test_flag(Self::FACING_UP) && + xcv2.test_flag(Self::FACING_DOWN)) + return LARGER; + else if (xcv1.test_flag(Self::FACING_DOWN) && + xcv2.test_flag(Self::FACING_UP)) + return SMALLER; + + // In this case the two arcs overlap. + CGAL_assertion(xcv1.facing_mask() == xcv2.facing_mask()); + + return EQUAL; + } + + // Compare the slopes of the two arcs at p, using their first-order + // partial derivatives. + Algebraic slope1_numer, slope1_denom; + Algebraic slope2_numer, slope2_denom; + + xcv1.derive_by_x_at(p, 1, slope1_numer, slope1_denom); + xcv2.derive_by_x_at(p, 1, slope2_numer, slope2_denom); + + // Check if any of the slopes is vertical. + const bool is_vertical_slope1 = (CGAL::sign (slope1_denom) == ZERO); + const bool is_vertical_slope2 = (CGAL::sign (slope2_denom) == ZERO); + + if (! is_vertical_slope1 && ! is_vertical_slope2) { + // The two derivatives at p are well-defined: use them to determine + // which arc is above the other (the one with a larger slope is below). + Comparison_result slope_res = CGAL::compare(slope2_numer*slope1_denom, + slope1_numer*slope2_denom); + + if (slope_res != EQUAL) return slope_res; + + // Use the second-order derivative. + xcv1.derive_by_x_at(p, 2, slope1_numer, slope1_denom); + xcv2.derive_by_x_at(p, 2, slope2_numer, slope2_denom); + + slope_res = CGAL::compare(slope1_numer*slope2_denom, + slope2_numer*slope1_denom); + + if (slope_res != EQUAL) return (slope_res); + + // Use the third-order derivative. + xcv1.derive_by_x_at(p, 3, slope1_numer, slope1_denom); + xcv2.derive_by_x_at(p, 3, slope2_numer, slope2_denom); + + slope_res = CGAL::compare(slope2_numer*slope1_denom, + slope1_numer*slope2_denom); + + // \todo Handle higher-order derivatives: + CGAL_assertion(slope_res != EQUAL); + + return slope_res; + } + else if (! is_vertical_slope2) { + // The first arc has a vertical slope at p: check whether it is + // facing upwards or downwards and decide accordingly. + CGAL_assertion(xcv1.facing_mask() != 0); + + return (xcv1.test_flag(Self::FACING_UP)) ? + LARGER : SMALLER; + } + else if (! is_vertical_slope1) { + // The second arc has a vertical slope at p_int: check whether it is + // facing upwards or downwards and decide accordingly. + CGAL_assertion(xcv2.facing_mask() != 0); + + return (xcv2.test_flag(Self::FACING_UP)) ? + SMALLER : LARGER; + } + + // The two arcs have vertical slopes at p_int: + // First check whether one is facing up and one down. In this case the + // comparison result is trivial. + if (xcv1.test_flag(Self::FACING_UP) && + xcv2.test_flag(Self::FACING_DOWN)) + return LARGER; + else if (xcv1.test_flag(Self::FACING_DOWN) && + xcv2.test_flag(Self::FACING_UP)) + return SMALLER; + + // Compute the second-order derivative by y and act according to it. + xcv1.derive_by_y_at(p, 2, slope1_numer, slope1_denom); + xcv2.derive_by_y_at(p, 2, slope2_numer, slope2_denom); + + Comparison_result slope_res = + CGAL::compare(slope2_numer*slope1_denom, slope1_numer*slope2_denom); + + // If necessary, use the third-order derivative by y. + if (slope_res == EQUAL) { + // \todo Check this! + xcv1.derive_by_y_at(p, 3, slope1_numer, slope1_denom); + xcv2.derive_by_y_at(p, 3, slope2_numer, slope2_denom); + + slope_res = + CGAL::compare(slope2_numer*slope1_denom, slope1_numer*slope2_denom); + } + + // \todo Handle higher-order derivatives: + CGAL_assertion(slope_res != EQUAL); + + // Check whether both are facing up. + if (xcv1.test_flag(Self::FACING_UP) && + xcv2.test_flag(Self::FACING_UP)) + return ((slope_res == LARGER) ? SMALLER : LARGER); + + // Both are facing down. + return slope_res; + } + + /*! Compare two arcs immediately to the right of their intersection point. + * \param xcv1 The first compared arc. + * \param xcv2 The second compared arc. + * \param p The reference intersection point. + * \return The relative position of the arcs to the right of `p`. + * \pre Both arcs we compare are not vertical segments. + */ + CGAL_DEPRECATED + Comparison_result compare_to_right(const Self& xcv2, const Point_2& p) const { + const auto& xcv1 = *this; + CGAL_precondition(! xcv1.is_vertical() && ! xcv2.is_vertical()); + + // In case one arc is facing upwards and another facing downwards, it is + // clear that the one facing upward is above the one facing downwards. + if (_has_same_supporting_conic(xcv2)) { + if (xcv1.test_flag(Self::FACING_UP) && + xcv2.test_flag(Self::FACING_DOWN)) + return LARGER; + else if (xcv1.test_flag(Self::FACING_DOWN) && + xcv2.test_flag(Self::FACING_UP)) + return SMALLER; + + // In this case the two arcs overlap. + CGAL_assertion(xcv1.facing_mask() == xcv2.facing_mask()); + return EQUAL; + } + + // Compare the slopes of the two arcs at p, using their first-order + // partial derivatives. + Algebraic slope1_numer, slope1_denom; + Algebraic slope2_numer, slope2_denom; + + xcv1.derive_by_x_at(p, 1, slope1_numer, slope1_denom); + xcv2.derive_by_x_at(p, 1, slope2_numer, slope2_denom); + + // Check if any of the slopes is vertical. + const bool is_vertical_slope1 = (CGAL::sign(slope1_denom) == ZERO); + const bool is_vertical_slope2 = (CGAL::sign(slope2_denom) == ZERO); + + if (! is_vertical_slope1 && ! is_vertical_slope2) { + // The two derivatives at p are well-defined: use them to determine + // which arc is above the other (the one with a larger slope is below). + Comparison_result slope_res = + CGAL::compare(slope1_numer*slope2_denom, slope2_numer*slope1_denom); + + if (slope_res != EQUAL) return (slope_res); + + // Use the second-order derivative. + xcv1.derive_by_x_at(p, 2, slope1_numer, slope1_denom); + xcv2.derive_by_x_at(p, 2, slope2_numer, slope2_denom); + + slope_res = + CGAL::compare(slope1_numer*slope2_denom, slope2_numer*slope1_denom); + + if (slope_res != EQUAL) return (slope_res); + + // Use the third-order derivative. + xcv1.derive_by_x_at(p, 3, slope1_numer, slope1_denom); + xcv2.derive_by_x_at(p, 3, slope2_numer, slope2_denom); + + slope_res = + CGAL::compare(slope1_numer*slope2_denom, slope2_numer*slope1_denom); + + // \todo Handle higher-order derivatives: + CGAL_assertion(slope_res != EQUAL); + + return slope_res; + } + else if (! is_vertical_slope2) { + // The first arc has a vertical slope at p: check whether it is + // facing upwards or downwards and decide accordingly. + CGAL_assertion(xcv1.facing_mask() != 0); + + return (xcv1.test_flag(Self::FACING_UP)) ? LARGER : SMALLER; + } + else if (! is_vertical_slope1) { + // The second arc has a vertical slope at p_int: check whether it is + // facing upwards or downwards and decide accordingly. + CGAL_assertion(xcv2.facing_mask() != 0); + + return (xcv2.test_flag(Self::FACING_UP)) ? SMALLER : LARGER; + } + + // The two arcs have vertical slopes at p_int: + // First check whether one is facing up and one down. In this case the + // comparison result is trivial. + if (xcv1.test_flag(Self::FACING_UP) && + xcv2.test_flag(Self::FACING_DOWN)) return LARGER; + else if (xcv1.test_flag(Self::FACING_DOWN) && + xcv2.test_flag(Self::FACING_UP)) return SMALLER; + + // Compute the second-order derivative by y and act according to it. + xcv1.derive_by_y_at(p, 2, slope1_numer, slope1_denom); + xcv2.derive_by_y_at(p, 2, slope2_numer, slope2_denom); + + Comparison_result slope_res = + CGAL::compare(slope1_numer*slope2_denom, slope2_numer*slope1_denom); + + // If necessary, use the third-order derivative by y. + if (slope_res == EQUAL) { + // \todo Check this! + xcv1.derive_by_y_at(p, 3, slope1_numer, slope1_denom); + xcv2.derive_by_y_at(p, 3, slope2_numer, slope2_denom); + + slope_res = + CGAL::compare(slope2_numer*slope1_denom, slope1_numer*slope2_denom); + } + + // \todo Handle higher-order derivatives: + CGAL_assertion(slope_res != EQUAL); + + if (xcv1.test_flag(Self::FACING_UP) && + xcv2.test_flag(Self::FACING_UP)) + return (slope_res == LARGER) ? SMALLER : LARGER; // both are facing up + return slope_res; // both are facing down + } + + /*! Check whether two arcs are equal (have the same graph). + * \param xcv1 The first compared arc. + * \param xcv2 The second compared arc. + * \return `true` if the two arcs have the same graph; `false` otherwise. + */ + CGAL_DEPRECATED + bool equals(const Self& xcv2) const { + const auto& xcv1 = *this; + Alg_kernel alg_kernel; + + // The two arc must have the same supporting conic curves. + if (! _has_same_supporting_conic(xcv2)) return false; + + auto eq = alg_kernel.equal_2_object(); + + // Check that the arc endpoints are the same. + if (xcv1.orientation() == COLLINEAR) { + CGAL_assertion(xcv2.orientation() == COLLINEAR); + return((eq(xcv1.source(), xcv2.source()) && + eq(xcv1.target(), xcv2.target())) || + (eq(xcv1.source(), xcv2.target()) && + eq(xcv1.target(), xcv2.source()))); + } + + if (xcv1.orientation() == xcv2.m_orient) { + // Same orientation - the source and target points must be the same. + return (eq(xcv1.source(), xcv2.source()) && + eq(xcv1.target(), xcv2.target())); + } + + // Reverse orientation - the source and target points must be swapped. + return (eq(xcv1.source(), xcv2.target()) && + eq(xcv1.target(), xcv2.source())); + } + + /*! Check whether it is possible to merge the arc with the given arc. + * \param xcv1 The first arc. + * \param xcv2 The second arc. + * \return `true` if it is possible to merge the two arcs; + * `false` otherwise. + */ + CGAL_DEPRECATED + bool can_merge_with(const Self& xcv2) const { + const auto& xcv1 = *this; + Alg_kernel alg_kernel; + + // In order to merge the two arcs, they should have the same supporting + // conic. + if (! _has_same_supporting_conic(xcv2)) return false; + + // Check if the left endpoint of one curve is the right endpoint of the + // other. + auto eq = alg_kernel.equal_2_object(); + return (eq(xcv1.right(), xcv2.left()) || eq(xcv1.left(), xcv2.right())); + } + + /*! Merge the current arc with the given arc. + * \param xcv1 The first arc to merge with. + * \param xcv2 The second arc to merge with. + * \pre The two arcs are mergeable. + */ + CGAL_DEPRECATED + void merge(const Self& xcv2) const { + const auto& xcv1 = *this; + Alg_kernel alg_kernel; + + // Check whether we should extend the arc to the left or to the right. + auto eq = alg_kernel.equal_2_object(); + if (eq(xcv1.right(), xcv2.left())) { + // Extend the arc to the right. + if (xcv1.test_flag(Self::IS_DIRECTED_RIGHT)) + xcv1.set_target(xcv2.right()); + else xcv1.set_source(xcv2.right()); + } + else { + CGAL_precondition(eq(xcv1.left(), xcv2.right())); + + // Extend the arc to the left. + if (xcv1.test_flag(Self::IS_DIRECTED_RIGHT)) + xcv1.set_source(xcv2.left()); + else xcv1.set_target(xcv2.left()); + } + } + private: /// \name Auxiliary (private) functions. //@{ From a99617aa09cff6a75cf903d8c55167a802782826 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Sat, 10 Sep 2022 12:59:24 +0300 Subject: [PATCH 077/105] Finished restating the code for backward compatibility. --- .../ArrangementGraphicsItem.cpp | 4 +- .../ArrangementPainterOstream.cpp | 52 +++++------ .../Conic_x_monotone_arc_2.h | 86 +++++++++++++------ 3 files changed, 87 insertions(+), 55 deletions(-) diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementGraphicsItem.cpp b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementGraphicsItem.cpp index 4ad1ba51251..5e37e2ab62a 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementGraphicsItem.cpp +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementGraphicsItem.cpp @@ -573,7 +573,7 @@ template template void ArrangementGraphicsItem::paintFace( Face_handle f, QPainter* painter, - const CGAL::Arr_conic_traits_2&) + const CGAL::Arr_conic_traits_2& traits) { if (!f->is_unbounded()) // f is not the unbounded face { @@ -643,7 +643,7 @@ void ArrangementGraphicsItem::paintFace( ker.compare_x_2_object()(curr_p, c.right()) != CGAL::LARGER)) { continue; } - auto px = c.point_at_x(curr_p); + auto px = traits.point_at_x(c, curr_p); double curr_y = CGAL::to_double(px.y()); QPointF curr(curr_x, curr_y); pts.push_back(curr); diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementPainterOstream.cpp b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementPainterOstream.cpp index bdc2c17f627..5ab229da8a8 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementPainterOstream.cpp +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementPainterOstream.cpp @@ -177,7 +177,7 @@ ArrangementPainterOstream< ArrangementPainterOstream>::operator<<(const X_monotone_curve_2& curve) { - CGAL::Bbox_2 bb = curve.bbox(); + CGAL::Bbox_2 bb = traits.construct_bbox_2_object()(curve); QRectF qbb = this->convert(bb); // quick cull @@ -185,47 +185,49 @@ ArrangementPainterOstreamscene->views().first(); - int xmin = view->mapFromScene(bb.xmin(), bb.ymin()).x(); - int xmax = view->mapFromScene(bb.xmax(), bb.ymin()).x(); - // can be negitive due to rotation trasnformation - size_t n = static_cast(std::abs(xmax - xmin)); - if (n == 0) { return *this; } - - auto paintCurve = [&](auto&& curve_) { - std::vector> app_pts; - app_pts.reserve(n + 1); - curve_.polyline_approximation(n, std::back_inserter(app_pts)); + // QGraphicsView* view = this->scene->views().first(); + // auto pmin = view->mapFromScene(bb.xmin(), bb.ymin()); + // auto pmax = view->mapFromScene(bb.xmax(), bb.ymax()); + // std::cout << "extreme: " + // << pmin.x() << ", " << pmin.y() << "," + // << pmax.x() << ", " << pmax.y() << std::endl; + // // can be negitive due to rotation trasnformation + // size_t n = static_cast(std::abs(xmax - xmin)); + // if (n == 0) { return *this; } + double error = 1; + auto paint_curve = [&](auto&& curve_) { + using Approximate_point_2 = typename Traits::Approximate_point_2; + std::vector app_pts; + // app_pts.reserve(n + 1); + // curve_.polyline_approximation(n, std::back_inserter(app_pts)); + auto aprox = traits.approximate_2_object(); + aprox(curve_, error, std::back_inserter(app_pts)); auto p_curr = app_pts.begin(); auto end_pts = app_pts.end(); auto p_next = p_curr + 1; - int count = 0; - do - { - QPointF p1(p_curr->first, p_curr->second); - QPointF p2(p_next->first, p_next->second); + do { + QPointF p1(p_curr->x(), p_curr->y()); + QPointF p2(p_next->x(), p_next->y()); this->qp->drawLine(p1, p2); p_curr++; p_next++; - ++count; } while (p_next != end_pts); }; - if (this->clippingRect.isValid()) - { + if (this->clippingRect.isValid()) { std::vector visibleParts; if (this->clippingRect.contains(qbb)) visibleParts.push_back(curve); else visibleParts = this->visibleParts(curve); - - for (auto& visiblePart : visibleParts) paintCurve(visiblePart); + for (auto& visiblePart : visibleParts) paint_curve(visiblePart); } - else - { // draw the whole curve - paintCurve(curve); + else { + // draw the whole curve + paint_curve(curve); } + // paint_curve(curve); return *this; } diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h index 811bba05525..122da7f7380 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h @@ -42,6 +42,7 @@ public: typedef typename Point_2::Conic_id Conic_id; using Conic_arc_2::sign_of_extra_data; + using Conic_arc_2::_is_between_endpoints; using Conic_arc_2::IS_VALID; using Conic_arc_2::IS_FULL_CONIC; @@ -445,6 +446,34 @@ public: */ Conic_id id() const { return m_id; } + /*! Check whether the given point lies on the arc. + * \param p The qury point. + * \param (true) if p lies on the arc; (false) otherwise. + */ + CGAL_DEPRECATED + bool contains_point(const Point_2& p) const { + const auto& xcv = *this; + // First check if p lies on the supporting conic. We first check whether + // it is one of p's generating conic curves. + bool p_on_conic(false); + if (p.is_generating_conic(xcv.id())) p_on_conic = true; + else { + // Check whether p satisfies the supporting conic equation. + p_on_conic = xcv.is_on_supporting_conic(p.x(), p.y()); + if (p_on_conic) { + // As p lies on the supporting conic of our arc, add its ID to + // the list of generating conics for p. + Point_2& p_non_const = const_cast(p); + p_non_const.set_generating_conic(xcv.id()); + } + } + + if (! p_on_conic) return false; + + // Check if p is between the endpoints of the arc. + return _is_between_endpoints(p); + } + /*! Obtain a bounding box for the conic arc. * \return The bounding box. */ @@ -667,35 +696,36 @@ public: // Make sure that the endpoints conform with the direction of the arc. Alg_kernel alg_kernel; Self res_xcv = xcv; - auto cmp_xy = alg_kernel.compare_xy_2_object(); - if (! ((xcv.test_flag(Self::IS_DIRECTED_RIGHT) && - (cmp_xy(ps, pt) == SMALLER)) || - (xcv.test_flag(Self::IS_DIRECTED_RIGHT) && - (cmp_xy(ps, pt) == LARGER)))) - { - // We are allowed to change the direction only in case of a segment. - CGAL_assertion(xcv.orientation() == COLLINEAR); - res_xcv.flip_flag(Self::IS_DIRECTED_RIGHT); - } - - // Make a copy of the current arc and assign its endpoints. - auto eq = alg_kernel.equal_2_object(); - if (! eq(ps, xcv.source())) { - res_xcv.set_source(ps); - - if (! ps.is_generating_conic(xcv.id())) - res_xcv.source().set_generating_conic(xcv.id()); - } - - if (! eq(pt, xcv.target())) { - res_xcv.set_target(pt); - - if (! pt.is_generating_conic(xcv.id())) - res_xcv.target().set_generating_conic(xcv.id()); - } - - return res_xcv; + auto cmp_xy = alg_kernel.compare_xy_2_object(); + if (! ((xcv.test_flag(Self::IS_DIRECTED_RIGHT) && + (cmp_xy(ps, pt) == SMALLER)) || + (xcv.test_flag(Self::IS_DIRECTED_RIGHT) && + (cmp_xy(ps, pt) == LARGER)))) + { + // We are allowed to change the direction only in case of a segment. + CGAL_assertion(xcv.orientation() == COLLINEAR); + res_xcv.flip_flag(Self::IS_DIRECTED_RIGHT); } + + // Make a copy of the current arc and assign its endpoints. + auto eq = alg_kernel.equal_2_object(); + if (! eq(ps, xcv.source())) { + res_xcv.set_source(ps); + + if (! ps.is_generating_conic(xcv.id())) + res_xcv.source().set_generating_conic(xcv.id()); + } + + if (! eq(pt, xcv.target())) { + res_xcv.set_target(pt); + + if (! pt.is_generating_conic(xcv.id())) + res_xcv.target().set_generating_conic(xcv.id()); + } + + return res_xcv; + } + //@} /*! Compare two arcs immediately to the leftt of their intersection point. From 49240991f67ab9ee549715cbb24fe233d4941851 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Sat, 10 Sep 2022 22:12:09 +0300 Subject: [PATCH 078/105] Fixed the conic-related code to use new code (instead of deprecated code). --- .../GraphicsViewCurveInput.cpp | 216 +++--- .../GraphicsViewCurveInputTyped.h | 31 +- .../MergeEdgeCallback.cpp | 165 ++--- .../Arrangement_on_surface_2/Utils/Utils.cpp | 449 ++++++------ .../Arrangement_on_surface_2/Utils/Utils.h | 639 +++++++++++------- 5 files changed, 815 insertions(+), 685 deletions(-) diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/GraphicsViewCurveInput.cpp b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/GraphicsViewCurveInput.cpp index 45efa1e73af..f8c84a575ee 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/GraphicsViewCurveInput.cpp +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/GraphicsViewCurveInput.cpp @@ -24,11 +24,10 @@ #include #include +// template inline typename std::enable_if::type -for_each(std::tuple&, FuncT) -{ -} +for_each(std::tuple&, FuncT) {} template inline typename std::enable_if < @@ -38,42 +37,36 @@ template for_each(t, f); } -namespace CGAL -{ -namespace Qt -{ +namespace CGAL { +namespace Qt { +// GraphicsViewCurveInputBase::GraphicsViewCurveInputBase( QObject* parent, QGraphicsScene* scene) : Callback(parent, scene), inputMethod(nullptr) -{ -} +{} +// void GraphicsViewCurveInputBase::setInputMethod(CurveInputMethod* inputMethod_) -{ - this->inputMethod = inputMethod_; -} +{ this->inputMethod = inputMethod_; } -void GraphicsViewCurveInputBase::reset() -{ - if (this->inputMethod) - { +void GraphicsViewCurveInputBase::reset() { + if (this->inputMethod) { this->inputMethod->reset(); this->inputMethod = nullptr; } } +// bool GraphicsViewCurveInputBase::eventFilter(QObject* obj, QEvent* event) -{ - return this->inputMethod->eventFilter(obj, event); -} +{ return this->inputMethod->eventFilter(obj, event); } +// void GraphicsViewCurveInputBase::setColor(QColor c) -{ - this->inputMethod->setColor(c); -} +{ this->inputMethod->setColor(c); } +// template GraphicsViewCurveInput::GraphicsViewCurveInput( Arrangement* arrangement_, QObject* parent, QGraphicsScene* scene) : @@ -90,9 +83,9 @@ GraphicsViewCurveInput::GraphicsViewCurveInput( curveGenerator.setTraits(this->arrangement->traits()); } +// template -void GraphicsViewCurveInput::setCurveType(CurveType type) -{ +void GraphicsViewCurveInput::setCurveType(CurveType type) { this->reset(); for_each(inputMethods, [&](auto&& it) { if (it.curveType() == type) @@ -100,41 +93,37 @@ void GraphicsViewCurveInput::setCurveType(CurveType type) }); } +// template void GraphicsViewCurveInput::setPointSnapper(PointSnapperBase* snapper_) -{ - for_each(inputMethods, [&](auto&& it) { it.setPointSnapper(snapper_); }); -} +{ for_each(inputMethods, [&](auto&& it) { it.setPointSnapper(snapper_); }); } +// template template void GraphicsViewCurveInput::setDefaultInputMethod(std::true_type) -{ - this->setInputMethod(&std::get<0>(inputMethods)); -} +{ this->setInputMethod(&std::get<0>(inputMethods)); } +// template void GraphicsViewCurveInput::setDefaultInputMethod(std::false_type) -{ -} +{} +// template -void GraphicsViewCurveInput::generate(CGAL::Object o) -{ - insertCurve( - demo_types::enumFromArrType(), - CGAL::make_object(this->arrangement), o); +void GraphicsViewCurveInput::generate(CGAL::Object o) { + insertCurve(demo_types::enumFromArrType(), + CGAL::make_object(this->arrangement), o); Q_EMIT CGAL::Qt::GraphicsViewCurveInputBase::modelChanged(); } +// template -void GraphicsViewCurveInput::curveInputDoneEvent( - const std::vector& clickedPoints, CurveType type) -{ +void GraphicsViewCurveInput:: +curveInputDoneEvent(const std::vector& clickedPoints, CurveType type) { boost::optional cv = this->curveGenerator.generate(clickedPoints, type); - if (cv) - { + if (cv) { Insert_curve{}(this->arrangement, *cv); Q_EMIT this->modelChanged(); } @@ -142,8 +131,8 @@ void GraphicsViewCurveInput::curveInputDoneEvent( // CurveGeneratorBase template -auto CurveGeneratorBase::generate( - const std::vector& clickedPoints, CurveType type) +auto CurveGeneratorBase:: +generate(const std::vector& clickedPoints, CurveType type) -> boost::optional { boost::optional res; @@ -171,7 +160,7 @@ auto CurveGeneratorBase::generate( res = generateThreePointCircularArc(clickedPoints); break; case CurveType::FivePointConicArc: - res = generateFivePointConicArc(clickedPoints); + res = generateFivePointConicArc(clickedPoints); break; case CurveType::Bezier: res = generateBezier(clickedPoints); @@ -181,11 +170,10 @@ auto CurveGeneratorBase::generate( return res; } +// template void CurveGeneratorBase::setTraits(const ArrTraits* traits_) -{ - this->traits = traits_; -} +{ this->traits = traits_; } // Curve Generator Segment Traits template @@ -211,25 +199,25 @@ auto CurveGenerator>:: // Curve Generator Linear Traits template -auto CurveGenerator>::generateSegment( - const std::vector& points) -> boost::optional +auto CurveGenerator>:: +generateSegment(const std::vector& points) -> boost::optional { Curve_2 res = Curve_2(Segment_2(points[0], points[1])); return res; } +// template -auto CurveGenerator>::generateRay( - const std::vector& points) -> boost::optional -{ +auto CurveGenerator>:: +generateRay(const std::vector& points) -> boost::optional { Curve_2 res = Curve_2(Ray_2(points[0], points[1])); return res; } +// template -auto CurveGenerator>::generateLine( - const std::vector& points) -> boost::optional -{ +auto CurveGenerator>:: +generateLine(const std::vector& points) -> boost::optional { Curve_2 res = Curve_2(Line_2(points[0], points[1])); return res; } @@ -237,28 +225,31 @@ auto CurveGenerator>::generateLine( // CurveGenerator Conic Traits template auto CurveGenerator>:: - generateSegment(const std::vector& points) - -> boost::optional +generateSegment(const std::vector& points) + -> boost::optional { - Curve_2 res = Curve_2(Rat_segment_2(points[0], points[1])); + auto ctr_cv = this->traits->construct_curve_2_object(); + Curve_2 res = ctr_cv(Rat_segment_2(points[0], points[1])); return res; } +// template auto CurveGenerator>:: - generateCircle(const std::vector& points) -> boost::optional -{ +generateCircle(const std::vector& points) -> boost::optional { auto sq_rad = (points[0].x() - points[1].x()) * (points[0].x() - points[1].x()) + (points[0].y() - points[1].y()) * (points[0].y() - points[1].y()); - Curve_2 res = Curve_2(Rat_circle_2(points[0], sq_rad)); + auto ctr_cv = this->traits->construct_curve_2_object(); + Curve_2 res = ctr_cv(Rat_circle_2(points[0], sq_rad)); return res; } +// template auto CurveGenerator>:: - generateEllipse(const std::vector& points) - -> boost::optional +generateEllipse(const std::vector& points) + -> boost::optional { auto x1 = (CGAL::min)(points[0].x(), points[1].x()); auto y1 = (CGAL::min)(points[0].y(), points[1].y()); @@ -279,14 +270,16 @@ auto CurveGenerator>:: Rat_FT v = -2 * y0 * a_sq; Rat_FT ww = x0 * x0 * b_sq + y0 * y0 * a_sq - a_sq * b_sq; - Curve_2 res = Curve_2(r, s, t, u, v, ww); + auto ctr_cv = this->traits->construct_curve_2_object(); + Curve_2 res = ctr_cv(r, s, t, u, v, ww); return res; } +// template auto CurveGenerator>:: - generateThreePointCircularArc(const std::vector& points) - -> boost::optional +generateThreePointCircularArc(const std::vector& points) + -> boost::optional { auto& qp1 = points[0]; auto& qp2 = points[1]; @@ -295,22 +288,22 @@ auto CurveGenerator>:: Rat_point_2 p2 = Rat_point_2(qp2.x(), qp2.y()); Rat_point_2 p3 = Rat_point_2(qp3.x(), qp3.y()); RatKernel ker; - if (!ker.collinear_2_object()(p1, p2, p3)) - { - Curve_2 res(p1, p2, p3); + if (! ker.collinear_2_object()(p1, p2, p3)) { + auto ctr_cv = this->traits->construct_curve_2_object(); + Curve_2 res = ctr_cv(p1, p2, p3); return res; } - else - { + else { std::cout << "Points don't specify a valid conic." << std::endl; return {}; } } +// template auto CurveGenerator>:: - generateFivePointConicArc(const std::vector& points) - -> boost::optional +generateFivePointConicArc(const std::vector& points) + -> boost::optional { auto& qp0 = points[0]; auto& qp1 = points[1]; @@ -322,17 +315,14 @@ auto CurveGenerator>:: Rat_point_2 p2 = Rat_point_2(qp2.x(), qp2.y()); Rat_point_2 p3 = Rat_point_2(qp3.x(), qp3.y()); Rat_point_2 p4 = Rat_point_2(qp4.x(), qp4.y()); - try - { - Curve_2 res(p0, p1, p2, p3, p4); - if (res.is_valid()) - return res; - else - std::cout << "Points don't specify a valid conic. Try again!" - << std::endl; + try { + auto ctr_cv = this->traits->construct_curve_2_object(); + Curve_2 res = ctr_cv(p0, p1, p2, p3, p4); + if (res.is_valid()) return res; + else std::cout << "Points don't specify a valid conic. Try again!" + << std::endl; } - catch (...) - { + catch (...) { std::cout << "Points don't specify a valid conic. Try again!" << std::endl; } return {}; @@ -341,7 +331,7 @@ auto CurveGenerator>:: // CurveGenerator Algebraic Traits template auto CurveGenerator>:: - generateLine(const std::vector& points) -> boost::optional +generateLine(const std::vector& points) -> boost::optional { RationalTraits ratTraits; @@ -351,8 +341,7 @@ auto CurveGenerator>:: Polynomial_2 y = CGAL::shift(Polynomial_2(1), 1, 1); Polynomial_2 poly; - if (dx != 0) - { + if (dx != 0) { Rational mRat = dy / dx; Rational cRat = points[0].y() - mRat * points[0].x(); // y = (a/b) x + (e/f) @@ -364,8 +353,7 @@ auto CurveGenerator>:: poly = b * f * y - f * a * x - b * e; } // vertical line - else - { + else { Rational xP = points[0].x(); auto a = ratTraits.numerator(xP); auto b = ratTraits.denominator(xP); @@ -377,9 +365,10 @@ auto CurveGenerator>:: return res; } +// template auto CurveGenerator>:: - generateCircle(const std::vector& points) -> boost::optional +generateCircle(const std::vector& points) -> boost::optional { auto sq_rad = (points[0].x() - points[1].x()) * (points[0].x() - points[1].x()) + @@ -401,10 +390,11 @@ auto CurveGenerator>:: return this->generateEllipse_(center, rx, ry); } +// template auto CurveGenerator>:: - generateEllipse_(const Point_2& center, Rational rxRat, Rational ryRat) - -> boost::optional +generateEllipse_(const Point_2& center, Rational rxRat, Rational ryRat) + -> boost::optional { RationalTraits ratTraits; @@ -432,26 +422,23 @@ auto CurveGenerator>:: return res; } -template < - typename RatKernel, typename AlgKernel, typename NtTraits, - typename BoundingTraits> -auto CurveGenerator< - Arr_Bezier_curve_traits_2>:: - generateBezier(const std::vector& clickedPoints) - -> boost::optional +// +template +auto CurveGenerator +>:: +generateBezier(const std::vector& clickedPoints) + -> boost::optional { if (clickedPoints.size() < 2) return {}; return Curve_2{clickedPoints.begin(), clickedPoints.end()}; } // msvc2015 doesn't play well with polymorphic lambdas -namespace -{ -struct ExplicitLambda -{ +namespace { +struct ExplicitLambda { template - void operator()(demo_types::TypeHolder) - { + void operator()(demo_types::TypeHolder) { Arrangement* arr = nullptr; CGAL::assign(arr, arr_obj); res = new GraphicsViewCurveInput(arr, parent, scene); @@ -464,6 +451,7 @@ struct ExplicitLambda }; } // anonymous namespace +// GraphicsViewCurveInputBase* GraphicsViewCurveInputBase::create( demo_types::TraitsType tt, CGAL::Object arr_obj, QObject* parent, QGraphicsScene* scene) @@ -478,8 +466,11 @@ GraphicsViewCurveInputBase* GraphicsViewCurveInputBase::create( } // namespace CGAL #ifdef CGAL_USE_CORE -CGAL::Object algebraicCurveFromExpression( - const CGAL::Object& arr_obj, const std::string& exp, bool& is_first_curve) + +// +CGAL::Object algebraicCurveFromExpression(const CGAL::Object& arr_obj, + const std::string& exp, + bool& is_first_curve) { using Polynomial_2 = demo_types::DemoTypes::Alg_seg_traits::Polynomial_2; using Alg_seg_arr = demo_types::DemoTypes::Alg_seg_arr; @@ -498,15 +489,17 @@ CGAL::Object algebraicCurveFromExpression( return CGAL::make_object(cv); } -CGAL::Object rationalCurveFromExpression( - const CGAL::Object& arr_obj, const std::string& numerator, - const std::string& denominator, bool& is_first_curve) +// +CGAL::Object rationalCurveFromExpression(const CGAL::Object& arr_obj, + const std::string& numerator, + const std::string& denominator, + bool& is_first_curve) { using Polynomial_1 = demo_types::DemoTypes::Rational_traits::Polynomial_1; using Rational_arr = demo_types::DemoTypes::Rational_arr; Rational_arr* arr; - if (!CGAL::assign(arr, arr_obj)) CGAL_error(); + if (! CGAL::assign(arr, arr_obj)) CGAL_error(); is_first_curve = (arr->number_of_edges() == 0); @@ -521,4 +514,5 @@ CGAL::Object rationalCurveFromExpression( return CGAL::make_object(cv); } + #endif diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/GraphicsViewCurveInputTyped.h b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/GraphicsViewCurveInputTyped.h index 1c8a1b94699..2b4a68457f8 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/GraphicsViewCurveInputTyped.h +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/GraphicsViewCurveInputTyped.h @@ -30,14 +30,11 @@ namespace demo_types enum class TraitsType : int; } -namespace CGAL -{ -namespace Qt -{ +namespace CGAL { +namespace Qt { template -class CurveGeneratorBase -{ +class CurveGeneratorBase { public: using ArrTraits = ArrTraits_; using Curve_2 = typename ArrTraits::Curve_2; @@ -50,31 +47,40 @@ public: virtual boost::optional generateSegment(const std::vector&) { return {}; } + virtual boost::optional generateRay(const std::vector&) { return {}; } + virtual boost::optional generateLine(const std::vector&) { return {}; } + virtual boost::optional generatePolyline(const std::vector&) { return {}; } + virtual boost::optional generateCircle(const std::vector&) { return {}; } + virtual boost::optional generateEllipse(const std::vector&) { return {}; } + virtual boost::optional generateThreePointCircularArc(const std::vector&) { return {}; } + virtual boost::optional generateFivePointConicArc(const std::vector&) { return {}; } + virtual boost::optional generateBezier(const std::vector&) { return {}; } const ArrTraits* traits; }; +// Generic implementation. template struct CurveGenerator : public CurveGeneratorBase -{ -}; +{}; +// Specialization for the segment traits. template struct CurveGenerator> : public CurveGeneratorBase> @@ -89,6 +95,7 @@ struct CurveGenerator> : generateSegment(const std::vector&) override; }; +// Specialization for the polyline traits. template struct CurveGenerator> : public CurveGeneratorBase> @@ -102,10 +109,10 @@ struct CurveGenerator> : generatePolyline(const std::vector&) override; }; +// Specialization for the conic traits. template struct CurveGenerator> : - public CurveGeneratorBase< - Arr_conic_traits_2> + public CurveGeneratorBase> { using ArrTraits = Arr_conic_traits_2; using Curve_2 = typename ArrTraits::Curve_2; @@ -120,11 +127,15 @@ struct CurveGenerator> : boost::optional generateSegment(const std::vector&) override; + boost::optional generateCircle(const std::vector&) override; + boost::optional generateEllipse(const std::vector&) override; + boost::optional generateThreePointCircularArc(const std::vector&) override; + boost::optional generateFivePointConicArc(const std::vector&) override; }; diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/MergeEdgeCallback.cpp b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/MergeEdgeCallback.cpp index 45651705ba2..6f1a5d14880 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/MergeEdgeCallback.cpp +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/MergeEdgeCallback.cpp @@ -21,15 +21,14 @@ #include template -class MergeEdgeCallback : public MergeEdgeCallbackBase -{ +class MergeEdgeCallback : public MergeEdgeCallbackBase { public: - typedef Arr_ Arrangement; - typedef typename Arrangement::Halfedge_handle Halfedge_handle; - typedef typename Arrangement::Halfedge_iterator Halfedge_iterator; - typedef typename Arrangement::Vertex_iterator Vertex_iterator; - typedef typename Arrangement::Geometry_traits_2 Traits; - typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; + typedef Arr_ Arrangement; + typedef typename Arrangement::Halfedge_handle Halfedge_handle; + typedef typename Arrangement::Halfedge_iterator Halfedge_iterator; + typedef typename Arrangement::Vertex_iterator Vertex_iterator; + typedef typename Arrangement::Geometry_traits_2 Traits; + typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; MergeEdgeCallback(Arrangement* arr_, QObject* parent_); void setScene(QGraphicsScene* scene_) override; @@ -51,13 +50,10 @@ protected: }; // class MergeEdgeCallback // msvc2015 doesn't play well with polymorphic lambdas -namespace -{ -struct ExplicitLambda -{ +namespace { +struct ExplicitLambda { template - void operator()(demo_types::TypeHolder) - { + void operator()(demo_types::TypeHolder) { Arrangement* arr = nullptr; CGAL::assign(arr, arr_obj); res = new MergeEdgeCallback(arr, parent); @@ -69,9 +65,10 @@ struct ExplicitLambda }; } // anonymous namespace -MergeEdgeCallbackBase* MergeEdgeCallbackBase::create( - demo_types::TraitsType tt, CGAL::Object arr_obj, QObject* parent) -{ +// +MergeEdgeCallbackBase* +MergeEdgeCallbackBase::create(demo_types::TraitsType tt, CGAL::Object arr_obj, + QObject* parent) { MergeEdgeCallbackBase* res; ExplicitLambda explicit_lambda{res, arr_obj, parent}; demo_types::visitArrangementType(tt, explicit_lambda); @@ -80,55 +77,52 @@ MergeEdgeCallbackBase* MergeEdgeCallbackBase::create( /*! Constructor */ template -MergeEdgeCallback::MergeEdgeCallback( - Arrangement* arr_, QObject* parent_) : - MergeEdgeCallbackBase(parent_), - highlightedCurve(new CGAL::Qt::CurveGraphicsItem()), - highlightedCurve2(new CGAL::Qt::CurveGraphicsItem()), arr(arr_), - isFirst(true) +MergeEdgeCallback::MergeEdgeCallback(Arrangement* arr_, + QObject* parent_) : + MergeEdgeCallbackBase(parent_), + highlightedCurve(new CGAL::Qt::CurveGraphicsItem()), + highlightedCurve2(new CGAL::Qt::CurveGraphicsItem()), arr(arr_), + isFirst(true) { - QObject::connect( - this, SIGNAL(modelChanged()), this->highlightedCurve, SLOT(modelChanged())); - QObject::connect( - this, SIGNAL(modelChanged()), this->highlightedCurve2, - SLOT(modelChanged())); + QObject::connect(this, SIGNAL(modelChanged()), this->highlightedCurve, + SLOT(modelChanged())); + QObject::connect(this, SIGNAL(modelChanged()), this->highlightedCurve2, + SLOT(modelChanged())); } +// template -void MergeEdgeCallback::setScene(QGraphicsScene* scene_) -{ +void MergeEdgeCallback::setScene(QGraphicsScene* scene_) { Callback::setScene(scene_); this->highlightedCurve->setScene(scene_); this->highlightedCurve2->setScene(scene_); - if (scene_) - { + if (scene_) { this->scene->addItem(this->highlightedCurve); this->scene->addItem(this->highlightedCurve2); } } +// template -void MergeEdgeCallback::reset() -{ +void MergeEdgeCallback::reset() { this->isFirst = true; this->highlightedCurve->clear(); this->highlightedCurve2->clear(); this->mergeableHalfedge = Halfedge_handle(); } +// template -void MergeEdgeCallback::mousePressEvent(QGraphicsSceneMouseEvent* event) -{ +void MergeEdgeCallback::mousePressEvent(QGraphicsSceneMouseEvent* event) { if (this->isFirst) { // save the first edge if mergeable Halfedge_handle halfedge = this->getNearestMergeableCurve(event); - if (halfedge == Halfedge_handle()) { return; } + if (halfedge == Halfedge_handle()) return; this->isFirst = false; this->mergeableHalfedge = halfedge; } - else - { + else { Halfedge_handle nextHalfedge = this->getNearestMergeableCurve(this->mergeableHalfedge, event); this->mergeEdge.mergeEdge(this->arr, this->mergeableHalfedge, nextHalfedge); @@ -138,24 +132,21 @@ void MergeEdgeCallback::mousePressEvent(QGraphicsSceneMouseEvent* event) Q_EMIT modelChanged(); } +// template -void MergeEdgeCallback::mouseMoveEvent(QGraphicsSceneMouseEvent* event) -{ - if (this->isFirst) - { +void MergeEdgeCallback::mouseMoveEvent(QGraphicsSceneMouseEvent* event) { + if (this->isFirst) { Halfedge_handle halfedge = this->getNearestMergeableCurve(event); if (halfedge == Halfedge_handle()) { return; } this->highlightedCurve->clear(); this->highlightedCurve->insert(halfedge->curve()); Q_EMIT modelChanged(); } - else - { + else { Halfedge_handle nextHalfedge = this->getNearestMergeableCurve(this->mergeableHalfedge, event); - if (nextHalfedge != Halfedge_handle()) - { + if (nextHalfedge != Halfedge_handle()) { this->highlightedCurve2->clear(); this->highlightedCurve2->insert(nextHalfedge->curve()); Q_EMIT modelChanged(); @@ -163,65 +154,60 @@ void MergeEdgeCallback::mouseMoveEvent(QGraphicsSceneMouseEvent* event) } } +// template typename MergeEdgeCallback::Halfedge_handle -MergeEdgeCallback::getNearestMergeableCurve( - QGraphicsSceneMouseEvent* event) -{ +MergeEdgeCallback:: +getNearestMergeableCurve(QGraphicsSceneMouseEvent* event) { // find the nearest curve to the cursor that is adjacent to a curve that // can be merged with it - typedef typename ArrTraitsAdaptor::Kernel Kernel; - typedef typename Kernel::Point_2 Kernel_point_2; + using Kernel = typename ArrTraitsAdaptor::Kernel; + using Kernel_point_2 = typename Kernel::Point_2; Kernel_point_2 p = CGAL::Qt::Converter{}(event->scenePos()); - double minDist = (std::numeric_limits::max)(); + double min_dist = (std::numeric_limits::max)(); Halfedge_iterator nearestHei; bool found = false; - for (Halfedge_iterator hei = this->arr->halfedges_begin(); + for (auto hei = this->arr->halfedges_begin(); hei != this->arr->halfedges_end(); ++hei) { Vertex_iterator source = hei->source(); Vertex_iterator target = hei->target(); - if (source->degree() != 2 && target->degree() != 2) - { // then this halfedge has no mergeable neighbors - continue; - } + // then this halfedge has no mergeable neighbors + if (source->degree() != 2 && target->degree() != 2) continue; Halfedge_handle h1 = hei->prev(); Halfedge_handle h2 = hei->next(); - if ( - (!this->mergeEdge.areMergeable(this->arr, hei, h1)) && - (!this->mergeEdge.areMergeable(this->arr, hei, h2))) + if ((!this->mergeEdge.areMergeable(this->arr, hei, h1)) && + (!this->mergeEdge.areMergeable(this->arr, hei, h2))) { continue; } X_monotone_curve_2 curve = hei->curve(); - Compute_squared_distance_2 squaredDistance; - squaredDistance.setScene(this->getScene()); - double dist = CGAL::to_double(squaredDistance(p, curve)); - if (!found || dist < minDist) - { + Compute_squared_distance_2 + squared_distance(*(arr->geometry_traits())); + squared_distance.setScene(this->getScene()); + double dist = CGAL::to_double(squared_distance(p, curve)); + if (!found || dist < min_dist) { found = true; - minDist = dist; + min_dist = dist; nearestHei = hei; } } - if (!found) - { // then we did not find a mergeable halfedge - return Halfedge_handle(); - } + // then we did not find a mergeable halfedge + if (! found) return Halfedge_handle(); return nearestHei; } +// template typename MergeEdgeCallback::Halfedge_handle -MergeEdgeCallback::getNearestMergeableCurve( - Halfedge_handle h, QGraphicsSceneMouseEvent* event) -{ +MergeEdgeCallback:: +getNearestMergeableCurve(Halfedge_handle h, QGraphicsSceneMouseEvent* event) { // find the nearest curve to the cursor that is adjacent to a curve that // can be merged with it - typedef typename ArrTraitsAdaptor::Kernel Kernel; - typedef typename Kernel::Point_2 Kernel_point_2; + using Kernel = typename ArrTraitsAdaptor::Kernel; + using Kernel_point_2 = typename Kernel::Point_2 ; Kernel_point_2 p = CGAL::Qt::Converter{}(event->scenePos()); Halfedge_handle h1 = h->prev(); @@ -229,29 +215,24 @@ MergeEdgeCallback::getNearestMergeableCurve( Vertex_iterator source = h->source(); Vertex_iterator target = h->target(); - if (source->degree() != 2 && target->degree() != 2) - return Halfedge_handle(); - else if (source->degree() != 2) - return h2; - else if (target->degree() != 2) - return h1; + if (source->degree() != 2 && target->degree() != 2) return Halfedge_handle(); + else if (source->degree() != 2) return h2; + else if (target->degree() != 2) return h1; else if ( this->mergeEdge.areMergeable(arr, h, h1) && this->mergeEdge.areMergeable(arr, h, h2)) { X_monotone_curve_2 c1 = h1->curve(); X_monotone_curve_2 c2 = h2->curve(); - Compute_squared_distance_2 squaredDistance; - squaredDistance.setScene(this->getScene()); - double d1 = CGAL::to_double(squaredDistance(p, c1)); - double d2 = CGAL::to_double(squaredDistance(p, c2)); + Compute_squared_distance_2 + squared_distance(*(arr->geometry_traits())); + squared_distance.setScene(this->getScene()); + double d1 = CGAL::to_double(squared_distance(p, c1)); + double d2 = CGAL::to_double(squared_distance(p, c2)); return (d1 < d2) ? h1 : h2; } - else if (this->mergeEdge.areMergeable(arr, h, h2)) - return h2; - else if (this->mergeEdge.areMergeable(arr, h, h1)) - return h1; - else - return Halfedge_handle(); + else if (this->mergeEdge.areMergeable(arr, h, h2)) return h2; + else if (this->mergeEdge.areMergeable(arr, h, h1)) return h1; + else return Halfedge_handle(); } diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/Utils/Utils.cpp b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/Utils/Utils.cpp index a8a2f336263..295336bc19f 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/Utils/Utils.cpp +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/Utils/Utils.cpp @@ -23,11 +23,11 @@ #include #include +// template double -Compute_squared_distance_2>::operator()( - const Point_2& p, const X_monotone_curve_2& c) const -{ +Compute_squared_distance_2>:: +operator()(const Point_2& p, const X_monotone_curve_2& c) const { Point_2 p1 = c.source(); Point_2 p2 = c.target(); Segment_2 seg(p1, p2); @@ -35,33 +35,31 @@ Compute_squared_distance_2>::operator()( return CGAL::to_double(CGAL::squared_distance(p, seg)); } +// template double -Compute_squared_distance_2>::operator()( - const Point_2& p, const X_monotone_curve_2& c) const -{ +Compute_squared_distance_2>:: +operator()(const Point_2& p, const X_monotone_curve_2& c) const { Segment_2 seg; Ray_2 ray; Line_2 line; FT res; - if (c.is_segment()) - { + if (c.is_segment()) { seg = c.segment(); res = CGAL::squared_distance(p, seg); } - else if (c.is_ray()) - { + else if (c.is_ray()) { ray = c.ray(); res = CGAL::squared_distance(p, ray); } - else // ( c.is_line( ) ) - { + else {// ( c.is_line( ) ) line = c.line(); res = CGAL::squared_distance(p, line); } return CGAL::to_double(res); } +// template double Compute_squared_distance_2>::operator()( @@ -72,13 +70,11 @@ Compute_squared_distance_2>::operator()( bool first = true; FT min_dist = 0; - while (seg_it_s != c.subcurves_end()) - { + while (seg_it_s != c.subcurves_end()) { Segment_2 seg = *seg_it_s; FT dist = CGAL::squared_distance(p, seg); - if (first || dist < min_dist) - { + if (first || dist < min_dist) { first = false; min_dist = dist; } @@ -88,19 +84,18 @@ Compute_squared_distance_2>::operator()( return CGAL::to_double(min_dist); } +// template -double Compute_squared_distance_2< - CGAL::Arr_conic_traits_2>:: -operator()(const Point_2& p, const X_monotone_curve_2& c) const -{ +double Compute_squared_distance_2 +>:: +operator()(const Point_2& p, const X_monotone_curve_2& c) const { // Get the co-ordinates of the curve's source and target. // double sx = CGAL::to_double( c.source( ).x( ) ); // double sy = CGAL::to_double( c.source( ).y( ) ); // double tx = CGAL::to_double( c.target( ).x( ) ); // double ty = CGAL::to_double( c.target( ).y( ) ); - if (c.orientation() == CGAL::COLLINEAR) - { + if (c.orientation() == CGAL::COLLINEAR) { Point_2 ps = c.source(); Point_2 pt = c.target(); Segment_2 seg(ps, pt); @@ -108,8 +103,7 @@ operator()(const Point_2& p, const X_monotone_curve_2& c) const FT res = CGAL::squared_distance(p, seg); return CGAL::to_double(res); } - else - { + else { // If the curve is monotone, than its source and its target has the // extreme x co-ordinates on this curve. // bool is_source_left = (sx < tx); @@ -126,10 +120,11 @@ operator()(const Point_2& p, const X_monotone_curve_2& c) const // AlgKernel ker; int n = 100; - if (this->scene != nullptr && this->scene->views().size() != 0) - { // use the scene to approximate the resolution of the curve + if (this->scene != nullptr && this->scene->views().size() != 0) { + // use the scene to approximate the resolution of the curve QGraphicsView* view = this->scene->views().first(); - CGAL::Bbox_2 bb = c.bbox(); // assumes bounded curve + // assumes bounded curve + CGAL::Bbox_2 bb = this->m_traits.construct_bbox_2_object()(c); int xmin = view->mapFromScene(bb.xmin(), bb.ymin()).x(); int xmax = view->mapFromScene(bb.xmax(), bb.ymin()).x(); n = xmax - xmin; @@ -142,34 +137,32 @@ operator()(const Point_2& p, const X_monotone_curve_2& c) const auto end_pts = app_pts.end(); auto p_curr = app_pts.begin(); auto p_next = p_curr + 1; - do - { + do { Point_2 p1(p_curr->first, p_curr->second); Point_2 p2(p_next->first, p_next->second); Segment_2 seg(p1, p2); FT dist = CGAL::squared_distance(p, seg); - if (first || dist < min_dist) - { + if (first || dist < min_dist) { first = false; min_dist = dist; } - p_curr++; - p_next++; + ++p_curr; + ++p_next; } while (p_next != end_pts); return CGAL::to_double(min_dist); } } -template < - typename RatKernel, typename AlgKernel, typename NtTraits, - typename BoundingTraits> -double Compute_squared_distance_2>:: -operator()(const Point_2& p, const X_monotone_curve_2& curve) const -{ +// +template +double Compute_squared_distance_2>:: +operator()(const Point_2& p, const X_monotone_curve_2& curve) const { // TODO: this should probably be cached! CGAL::Qt::ArrangementPainterOstream painterOstream{nullptr}; painterOstream.setScene(this->getScene()); @@ -177,23 +170,22 @@ operator()(const Point_2& p, const X_monotone_curve_2& curve) const std::pair p_pair = { CGAL::to_double(p.x()), CGAL::to_double(p.y())}; - double minDist = (std::numeric_limits::max)(); + double min_dist = (std::numeric_limits::max)(); auto points = painterOstream.getPoints(curve); - for (auto& vit : points) - { + for (auto& vit : points) { QPointF coord(vit.first, vit.second); - float curDist = (vit.first - p_pair.first) * (vit.first - p_pair.first) + - (vit.second - p_pair.second) * (vit.second - p_pair.second); - minDist = curDist < minDist ? curDist : minDist; + float cur_dist = (vit.first - p_pair.first) * (vit.first - p_pair.first) + + (vit.second - p_pair.second) * (vit.second - p_pair.second); + min_dist = cur_dist < min_dist ? cur_dist : min_dist; } - return minDist; + return min_dist; } +// template double Compute_squared_distance_2>:: -operator()(const Point_2& p, const X_monotone_curve_2& curve) const -{ +operator()(const Point_2& p, const X_monotone_curve_2& curve) const { // TODO: this should probably be cached! CGAL::Qt::ArrangementPainterOstream painterOstream{nullptr}; painterOstream.setScene(this->getScene()); @@ -212,78 +204,74 @@ operator()(const Point_2& p, const X_monotone_curve_2& curve) const QPoint p_viewport = view->mapFromScene(QPointF{p.x().doubleValue(), p.y().doubleValue()}); - double minDist = (std::numeric_limits::max)(); - for (auto& vec : points) - { - for (auto vit = vec.begin(); vit != vec.end(); ++vit) - { + double min_dist = (std::numeric_limits::max)(); + for (auto& vec : points) { + for (auto vit = vec.begin(); vit != vec.end(); ++vit) { QPoint coord(vit->first, vit->second); - float curDist = QLineF{facadeToViewport.map(coord), p_viewport}.length(); - minDist = curDist < minDist ? curDist : minDist; + float cur_dist = QLineF{facadeToViewport.map(coord), p_viewport}.length(); + min_dist = cur_dist < min_dist ? cur_dist : min_dist; } } - return minDist; + return min_dist; } +// template double Compute_squared_distance_2< CGAL::Arr_rational_function_traits_2>:: -operator()(const Point_2& p, const X_monotone_curve_2& curve) const -{ +operator()(const Point_2& p, const X_monotone_curve_2& curve) const { // TODO: this should probably be cached! - CGAL::Qt::ArrangementPainterOstream painterOstream{nullptr}; - painterOstream.setScene(this->getScene()); + CGAL::Qt::ArrangementPainterOstream painter_ostream{nullptr}; + painter_ostream.setScene(this->getScene()); std::pair p_pair = { - CGAL::to_double(p.x()), CGAL::to_double(p.y())}; + CGAL::to_double(p.x()), CGAL::to_double(p.y()) + }; - double minDist = (std::numeric_limits::max)(); - auto points_list = painterOstream.getPointsList(curve); - for (auto& points : points_list) - { - for (auto& vit : points) - { + double min_dist = (std::numeric_limits::max)(); + auto points_list = painter_ostream.getPointsList(curve); + for (auto& points : points_list) { + for (auto& vit : points) { QPointF coord(vit.first, vit.second); - float curDist = + float cur_dist = (vit.first - p_pair.first) * (vit.first - p_pair.first) + (vit.second - p_pair.second) * (vit.second - p_pair.second); - minDist = curDist < minDist ? curDist : minDist; + min_dist = cur_dist < min_dist ? cur_dist : min_dist; } } - return minDist; + return min_dist; } +// template -auto Arr_construct_point_2::operator()(const Kernel_point_2& pt) - -> Point_2 -{ - return (*this)(FT{pt.x()}, FT{pt.y()}, traits); -} +auto Arr_construct_point_2:: +operator()(const Kernel_point_2& pt) -> Point_2 +{ return (*this)(FT{pt.x()}, FT{pt.y()}, traits); } +// template -auto Arr_construct_point_2::operator()(const FT& x, const FT& y) - -> Point_2 -{ - return (*this)(x, y, traits); -} +auto Arr_construct_point_2:: +operator()(const FT& x, const FT& y) -> Point_2 +{ return (*this)(x, y, traits); } +// template template -auto Arr_construct_point_2::operator()( - const FT& x, const FT& y, const TTraits*) -> Point_2 -{ +auto Arr_construct_point_2:: +operator()(const FT& x, const FT& y, const TTraits*) -> Point_2 { CoordinateType xx(x); CoordinateType yy(y); Point_2 res(xx, yy); return res; } +// template template -auto Arr_construct_point_2::operator()( - const FT& x, const FT& y, - const CGAL::Arr_rational_function_traits_2*) +auto Arr_construct_point_2:: +operator()(const FT& x, const FT& y, + const CGAL::Arr_rational_function_traits_2*) -> Point_2 { using Rational = typename ArrTraits::Rational; @@ -304,46 +292,44 @@ auto Arr_construct_point_2::operator()( return res; } +// template -auto Find_nearest_edge::operator()(const Point_2& queryPt) +auto Find_nearest_edge::operator()(const Point_2& query_pt) -> Halfedge_const_handle { Face_const_handle face = - PointLocationFunctions{}.getFace(arr, queryPt); + PointLocationFunctions{}.getFace(arr, query_pt); bool first = 1; X_monotone_curve_2 closestCurve; Halfedge_const_handle closestEdge; - double minDist(0); + double min_dist(0); - if (!face->is_unbounded()) - { // it is an interior face so it has a ccb + const auto& traits = arr->geometry_traits(); + Point_curve_distance point_curve_distance(*traits); + if (! face->is_unbounded()) { + // it is an interior face so it has a ccb Ccb_halfedge_const_circulator cc = face->outer_ccb(); - do - { + do { X_monotone_curve_2 curve = cc->curve(); - double dist = this->pointCurveDistance(queryPt, curve); - if (first || dist < minDist) - { + double dist = point_curve_distance(query_pt, curve); + if (first || dist < min_dist) { first = 0; - minDist = dist; + min_dist = dist; closestEdge = cc; } } while (++cc != face->outer_ccb()); } - else if (face->has_outer_ccb()) - { + else if (face->has_outer_ccb()) { Ccb_halfedge_const_circulator cc = face->outer_ccb(); - do - { - if (cc->is_fictitious()) { continue; } + do { + if (cc->is_fictitious()) continue; X_monotone_curve_2 curve = cc->curve(); - double dist = this->pointCurveDistance(queryPt, curve); - if (first || dist < minDist) - { + double dist = point_curve_distance(query_pt, curve); + if (first || dist < min_dist) { first = 0; - minDist = dist; + min_dist = dist; closestEdge = cc; } } while (++cc != face->outer_ccb()); @@ -351,17 +337,15 @@ auto Find_nearest_edge::operator()(const Point_2& queryPt) Hole_const_iterator hit; Hole_const_iterator eit = face->holes_end(); // int counter = 0; - for (hit = face->holes_begin(); hit != eit; ++hit) - { // check any holes inside this face + for (hit = face->holes_begin(); hit != eit; ++hit) { + // check any holes inside this face Ccb_halfedge_const_circulator cc = *hit; - do - { + do { X_monotone_curve_2 curve = cc->curve(); - double dist = this->pointCurveDistance(queryPt, curve); - if (first || dist < minDist) - { + double dist = point_curve_distance(query_pt, curve); + if (first || dist < min_dist) { first = 0; - minDist = dist; + min_dist = dist; closestEdge = cc; } cc++; @@ -371,6 +355,7 @@ auto Find_nearest_edge::operator()(const Point_2& queryPt) return closestEdge; } +// template auto Find_nearest_edge::getFace(const CGAL::Object& obj) -> Face_const_handle @@ -389,6 +374,7 @@ auto Find_nearest_edge::getFace(const CGAL::Object& obj) return (eit->face()); } +// template Construct_x_monotone_subcurve_2::Construct_x_monotone_subcurve_2( const ArrTraits* traits_) : @@ -402,6 +388,7 @@ Construct_x_monotone_subcurve_2::Construct_x_monotone_subcurve_2( { } +// template auto Construct_x_monotone_subcurve_2::operator()( const X_monotone_curve_2& curve, const boost::optional& pLeft, @@ -424,47 +411,45 @@ auto Construct_x_monotone_subcurve_2::operator()( X_monotone_curve_2 subcurve; X_monotone_curve_2 unusedTrimmings; X_monotone_curve_2 finalSubcurve; - if ( - pLeft && (unbounded_min || this->compare_x_2(*pLeft, pMin) == CGAL::LARGER)) + if (pLeft && + (unbounded_min || this->compare_x_2(*pLeft, pMin) == CGAL::LARGER)) { auto y1 = this->compute_y_at_x(curve, pLeft->x()); Point_2 splitPoint = {pLeft->x(), y1}; this->split_2(curve, splitPoint, unusedTrimmings, subcurve); } - else - { + else { subcurve = curve; } - if ( - pRight && - (unbounded_max || this->compare_x_2(*pRight, pMax) == CGAL::SMALLER)) + if (pRight && + (unbounded_max || this->compare_x_2(*pRight, pMax) == CGAL::SMALLER)) { auto y2 = this->compute_y_at_x(subcurve, pRight->x()); Point_2 splitPoint = {pRight->x(), y2}; this->split_2(subcurve, splitPoint, finalSubcurve, unusedTrimmings); } - else - { + else { finalSubcurve = subcurve; } return finalSubcurve; } +// template -auto Construct_x_monotone_subcurve_2< - CGAL::Arr_conic_traits_2>:: -operator()( - const X_monotone_curve_2& curve, const boost::optional& pLeft, - const boost::optional& pRight) -> X_monotone_curve_2 +auto Construct_x_monotone_subcurve_2 +>:: +operator()(const X_monotone_curve_2& curve, + const boost::optional& pLeft, + const boost::optional& pRight) -> X_monotone_curve_2 { // TODO: handle when pLeft or pRight is null // find the points on the curve - Point_2 left = curve.point_at_x(*pLeft); - Point_2 right = curve.point_at_x(*pRight); + Point_2 left = m_traits.point_at_x(curve, *pLeft); + Point_2 right = m_traits.point_at_x(curve, *pRight); // make sure the points are oriented in the direction that the curve is // going @@ -475,16 +460,17 @@ operator()( ker.compare_xy_2_object()(left, right) == CGAL::LARGER))) { std::swap(left, right); } - X_monotone_curve_2 res = curve.trim(left, right); + X_monotone_curve_2 res = m_traits.trim_2_object()(curve, left, right); return res; } -template < - typename RatKernel, typename AlgKernel, typename NtTraits, - typename BoundingTraits> -Construct_x_monotone_subcurve_2>::Construct_x_monotone_subcurve_2(const ArrTraits* traits_) : +// +template +Construct_x_monotone_subcurve_2>:: +Construct_x_monotone_subcurve_2(const ArrTraits* traits_) : traits(traits_), split_2(this->traits->split_2_object()), compare_x_2(this->traits->compare_x_2_object()), @@ -494,9 +480,9 @@ Construct_x_monotone_subcurve_2 +// +template auto Construct_x_monotone_subcurve_2>:: operator()( @@ -516,40 +502,35 @@ operator()( // at algebraic "x", so we need to make it rational auto local_get_t = [&](auto&& point) { if (point.is_rational()) - return this->compute_y_at_x.get_t( - curve, ((typename Point_2::Rat_point_2)point).x()); + return this->compute_y_at_x.get_t(curve, ((typename Point_2::Rat_point_2)point).x()); else return this->compute_y_at_x.get_t(curve, point.approximate().first); }; - if (pLeft && this->compare_x_2(*pLeft, pMin) == CGAL::LARGER) - { + if (pLeft && this->compare_x_2(*pLeft, pMin) == CGAL::LARGER) { auto t = local_get_t(*pLeft); Point_2 splitPoint(curve.supporting_curve(), t); this->split_2(curve, splitPoint, unusedTrimmings, subcurve); } - else - { + else { subcurve = curve; } - if (pRight && this->compare_x_2(*pRight, pMax) == CGAL::SMALLER) - { + if (pRight && this->compare_x_2(*pRight, pMax) == CGAL::SMALLER) { auto t = local_get_t(*pRight); Point_2 splitPoint(curve.supporting_curve(), t); this->split_2(subcurve, splitPoint, finalSubcurve, unusedTrimmings); } - else - { + else { finalSubcurve = subcurve; } return finalSubcurve; } +// template Construct_x_monotone_subcurve_2>::Construct_x_monotone_subcurve_2(const Traits* - traits_) : + AlgebraicKernel_d_1>>::Construct_x_monotone_subcurve_2(const Traits* traits_) : traits(traits_), split_2(this->traits->split_2_object()), compare_x_2(this->traits->compare_x_2_object()), @@ -559,6 +540,7 @@ Construct_x_monotone_subcurve_2 auto Construct_x_monotone_subcurve_2< CGAL::Arr_rational_function_traits_2>:: @@ -577,95 +559,93 @@ operator()( X_monotone_curve_2 subcurve; X_monotone_curve_2 unusedTrimmings; X_monotone_curve_2 finalSubcurve; - if ( - pLeft && (unbounded_min || this->compare_x_2(*pLeft, pMin) == CGAL::LARGER)) + if (pLeft && + (unbounded_min || this->compare_x_2(*pLeft, pMin) == CGAL::LARGER)) { Point_2 splitPoint{curve._f, pLeft->x()}; this->split_2(curve, splitPoint, unusedTrimmings, subcurve); } - else - { + else { subcurve = curve; } - if ( - pRight && - (unbounded_max || this->compare_x_2(*pRight, pMax) == CGAL::SMALLER)) + if (pRight && + (unbounded_max || this->compare_x_2(*pRight, pMax) == CGAL::SMALLER)) { auto y2 = this->compute_y_at_x(subcurve, pRight->x()); Point_2 splitPoint{curve._f, pRight->x()}; this->split_2(subcurve, splitPoint, finalSubcurve, unusedTrimmings); } - else - { + else { finalSubcurve = subcurve; } return finalSubcurve; } +// template Arr_compute_y_at_x_2::Arr_compute_y_at_x_2(const Traits* traits_) : - traits(traits_), - intersectCurves(this->traits->intersect_2_object()) + traits(traits_), + intersectCurves(this->traits->intersect_2_object()) { } +// template -auto Arr_compute_y_at_x_2::operator()( - const X_monotone_curve_2& curve, const CoordinateType& x) -> CoordinateType +auto Arr_compute_y_at_x_2:: +operator()(const X_monotone_curve_2& curve, const CoordinateType& x) + -> CoordinateType { typename Traits::Left_side_category category; return this->operator()(curve, x, this->traits, category); } +// template -double Arr_compute_y_at_x_2::approx( - const X_monotone_curve_2& curve, const CoordinateType& x) +double Arr_compute_y_at_x_2:: +approx(const X_monotone_curve_2& curve, const CoordinateType& x) { return CGAL::to_double((*this)(curve, x)); } +// template template -auto Arr_compute_y_at_x_2::operator()( - const X_monotone_curve_2& curve, const CoordinateType& x, - const TTraits* traits_, CGAL::Arr_oblivious_side_tag) -> CoordinateType +auto Arr_compute_y_at_x_2:: +operator()(const X_monotone_curve_2& curve, const CoordinateType& x, + const TTraits* traits_, CGAL::Arr_oblivious_side_tag) + -> CoordinateType { - typedef - typename TTraits::Construct_x_monotone_curve_2 Construct_x_monotone_curve_2; - Construct_x_monotone_curve_2 construct_x_monotone_curve_2 = - traits_->construct_x_monotone_curve_2_object(); + auto ctr_xcv = traits_->construct_x_monotone_curve_2_object(); CoordinateType res(0); CGAL::Bbox_2 clipRect = curve.bbox(); Point_2 p1c1(x, CoordinateType(clipRect.ymin() - 1)); // clicked point // upper bounding box Point_2 p2c1(x, CoordinateType(clipRect.ymax() + 1)); - const X_monotone_curve_2 verticalLine = - construct_x_monotone_curve_2(p1c1, p2c1); + const X_monotone_curve_2 verticalLine = ctr_xcv(p1c1, p2c1); CGAL::Object o; CGAL::Oneset_iterator oi(o); this->intersectCurves(curve, verticalLine, oi); IntersectionResult pair; - if (CGAL::assign(pair, o)) - { + if (CGAL::assign(pair, o)) { Point_2 pt = pair.first; res = pt.y(); } return res; } +// template template -auto Arr_compute_y_at_x_2::operator()( - const X_monotone_curve_2& curve, const CoordinateType& x, - const TTraits* traits_, CGAL::Arr_open_side_tag) -> CoordinateType +auto Arr_compute_y_at_x_2:: +operator()(const X_monotone_curve_2& curve, const CoordinateType& x, + const TTraits* traits_, CGAL::Arr_open_side_tag) -> CoordinateType { - typename TTraits::Construct_x_monotone_curve_2 construct_x_monotone_curve_2 = - traits_->construct_x_monotone_curve_2_object(); + auto ctr_xcv = traits_->construct_x_monotone_curve_2_object(); CoordinateType res(0); // QRectF clipRect = this->viewportRect( ); Line_2 line = curve.supporting_line(); @@ -673,22 +653,56 @@ auto Arr_compute_y_at_x_2::operator()( Point_2 p1c1(x, CoordinateType(-10000000)); // clicked point Point_2 p2c1(x, CoordinateType(10000000)); // upper bounding box - const X_monotone_curve_2 verticalLine = - construct_x_monotone_curve_2(p1c1, p2c1); + const X_monotone_curve_2 verticalLine = ctr_xcv(p1c1, p2c1); CGAL::Object o; CGAL::Oneset_iterator oi(o); this->intersectCurves(curve, verticalLine, oi); IntersectionResult pair; - if (CGAL::assign(pair, o)) - { + if (CGAL::assign(pair, o)) { Point_2 pt = pair.first; res = pt.y(); } return res; } +// Specialization for the conic traits. +template +auto +Arr_compute_y_at_x_2>:: +operator()(const X_monotone_curve_2& curve, const Coordinate_type& x) + -> Coordinate_type +{ + auto ctr_xcv = m_traits.construct_x_monotone_curve_2_object(); + CGAL::Bbox_2 clip_rect = m_traits.construct_bbox_2_object()(curve); + Point_2 p1c1(x, Coordinate_type(clip_rect.ymin() - 1)); // clicked point + // upper bounding box + Point_2 p2c1(x, Coordinate_type(clip_rect.ymax() + 1)); + + const X_monotone_curve_2 vertical_line = ctr_xcv(p1c1, p2c1); + CGAL::Object o; + CGAL::Oneset_iterator oi(o); + + this->intersect_curves(curve, vertical_line, oi); + + Coordinate_type res(0); + IntersectionResult pair; + if (CGAL::assign(pair, o)) { + Point_2 pt = pair.first; + res = pt.y(); + } + return res; +} + +// Specialization for the conic traits. +template +double +Arr_compute_y_at_x_2>:: +approx(const X_monotone_curve_2& curve, const Coordinate_type& x) +{ return CGAL::to_double((*this)(curve, x)); } + +// Specialization for the algebraic traits. template auto Arr_compute_y_at_x_2>:: operator()(const X_monotone_curve_2& curve, const CoordinateType& x) @@ -700,19 +714,19 @@ operator()(const X_monotone_curve_2& curve, const CoordinateType& x) X_monotone_curve_2 c2 = this->makeVerticalLine(x); intersect(curve, c2, oi); std::pair res; - if (CGAL::assign(res, o)) // TODO: handle failure case - { + if (CGAL::assign(res, o)) { + // TODO: handle failure case const Point_2& p = res.first; CoordinateType coord = p.y(); return coord; } - else - { + else { std::cout << "Warning: vertical projection failed" << std::endl; return CoordinateType(0); } } +// Specialization for the algebraic traits. template double Arr_compute_y_at_x_2>:: @@ -721,6 +735,7 @@ Arr_compute_y_at_x_2>:: return CGAL::to_double(this->operator()(curve, x)); } +// Specialization for the algebraic traits. template auto Arr_compute_y_at_x_2>:: makeVerticalLine(const CoordinateType& x) -> X_monotone_curve_2 @@ -739,6 +754,7 @@ auto Arr_compute_y_at_x_2>:: return curves[0]; // by construction, there is one curve in curves } +// template static inline auto get_t_range(const Bezier_x_monotone_2& curve) { @@ -754,9 +770,9 @@ static inline auto get_t_range(const Bezier_x_monotone_2& curve) (pt_org->point_bound().t_min + pt_org->point_bound().t_max) / 2); } -template < - typename RatKernel, typename AlgKernel, typename NtTraits, - typename BoundingTraits> +// +template auto Arr_compute_y_at_x_2>:: operator()(const X_monotone_curve_2& curve, const Rational& x) -> Algebraic @@ -768,9 +784,9 @@ operator()(const X_monotone_curve_2& curve, const Rational& x) -> Algebraic nt_traits.convert(supp_curve.y_norm()); } -template < - typename RatKernel, typename AlgKernel, typename NtTraits, - typename BoundingTraits> +// +template auto Arr_compute_y_at_x_2>:: get_t(const X_monotone_curve_2& curve, const Rational& x) -> Algebraic @@ -782,8 +798,7 @@ auto Arr_compute_y_at_x_2 -double Arr_compute_y_at_x_2>::approx(const X_monotone_curve_2& curve, const Rational& x) -{ +// +template +double Arr_compute_y_at_x_2>:: +approx(const X_monotone_curve_2& curve, const Rational& x) { return CGAL::to_double((*this)(curve, x)); } +// template auto Arr_compute_y_at_x_2< CGAL::Arr_rational_function_traits_2>:: @@ -814,6 +830,7 @@ operator()(const X_monotone_curve_2& curve, const Algebraic_real_1& x) return Point_2{curve._f, x}.y(); } +// template auto Arr_compute_y_at_x_2< CGAL::Arr_rational_function_traits_2>:: @@ -822,6 +839,7 @@ operator()(const X_monotone_curve_2& curve, const Rational& x) -> Rational return curve._f.numer().evaluate(x) / curve._f.denom().evaluate(x); } +// template auto Arr_compute_y_at_x_2< CGAL::Arr_rational_function_traits_2>:: @@ -830,6 +848,7 @@ approx(const X_monotone_curve_2& curve, const Rational& x) -> double return CGAL::to_double((*this)(curve, x)); } +// CGAL::Object createArrangement(demo_types::TraitsType tt) { CGAL::Object res; @@ -858,18 +877,16 @@ void deleteArrangement(demo_types::TraitsType tt, const CGAL::Object& arr_obj) }); } -CGAL::Object makeOverlayArrangement(const std::vector& arrs) -{ +// +CGAL::Object makeOverlayArrangement(const std::vector& arrs) { CGAL::Object arr_obj; - if (arrs.size() == 2) - { + if (arrs.size() == 2) { demo_types::forEachArrangementType([&](auto type_holder) { using Arrangement = typename decltype(type_holder)::type; Arrangement* arr1; Arrangement* arr2; - if (CGAL::assign(arr1, arrs[0]) && CGAL::assign(arr2, arrs[1])) - { + if (CGAL::assign(arr1, arrs[0]) && CGAL::assign(arr2, arrs[1])) { auto overlay_arr = new Arrangement(); CGAL::Arr_default_overlay_traits overlay_traits; @@ -881,9 +898,9 @@ CGAL::Object makeOverlayArrangement(const std::vector& arrs) return arr_obj; } -void insertCurve( - demo_types::TraitsType tt, const CGAL::Object& arr_obj, - const CGAL::Object& curve_obj) +// +void insertCurve(demo_types::TraitsType tt, const CGAL::Object& arr_obj, + const CGAL::Object& curve_obj) { demo_types::visitArrangementType(tt, [&](auto type_holder) { using Arrangement = typename decltype(type_holder)::type; diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/Utils/Utils.h b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/Utils/Utils.h index 0713d63f1c0..7a633574301 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/Utils/Utils.h +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/Utils/Utils.h @@ -21,186 +21,282 @@ class QGraphicsScene; -template -class Arr_compute_y_at_x_2 : public GraphicsSceneMixin -{ +// Genereic `Arr_compute_y_at_x_2` +template +class Arr_compute_y_at_x_2 : public GraphicsSceneMixin { public: - typedef ArrTraits Traits; - typedef typename ArrTraitsAdaptor< Traits >::Kernel Kernel; - typedef typename ArrTraitsAdaptor< Traits >::CoordinateType CoordinateType; + typedef Traits_ Traits; + typedef typename ArrTraitsAdaptor::Kernel Kernel; + typedef typename ArrTraitsAdaptor::CoordinateType CoordinateType; // typedef typename Kernel::FT FT; typedef typename Kernel::Point_2 Point_2; typedef typename Kernel::Line_2 Line_2; typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; typedef typename Traits::Multiplicity Multiplicity; typedef typename Traits::Intersect_2 Intersect_2; - typedef std::pair< typename Traits::Point_2, Multiplicity > + typedef std::pair IntersectionResult; /*! Constructor */ - Arr_compute_y_at_x_2( const Traits* ); + Arr_compute_y_at_x_2(const Traits* traits); + // CoordinateType operator()(const X_monotone_curve_2& curve, const CoordinateType& x); + // double approx(const X_monotone_curve_2& curve, const CoordinateType& x); protected: + // template - CoordinateType operator()( - const X_monotone_curve_2& curve, const CoordinateType& x, - const TTraits* traits_, CGAL::Arr_oblivious_side_tag); + CoordinateType operator()(const X_monotone_curve_2& curve, + const CoordinateType& x, const TTraits* traits_, + CGAL::Arr_oblivious_side_tag); + // template - CoordinateType operator()( - const X_monotone_curve_2& curve, const CoordinateType& x, - const TTraits* traits_, CGAL::Arr_open_side_tag); + CoordinateType operator()(const X_monotone_curve_2& curve, + const CoordinateType& x, const TTraits* traits_, + CGAL::Arr_open_side_tag); protected: const Traits* traits; Intersect_2 intersectCurves; }; -template -class Arr_compute_y_at_x_2< CGAL::Arr_algebraic_segment_traits_2< - Coefficient_ > > : public GraphicsSceneMixin +// Specialization of `Arr_compute_y_at_x_2` for the conic traits. +template +class Arr_compute_y_at_x_2 + > : + public GraphicsSceneMixin { public: - typedef Coefficient_ Coefficient; - typedef CGAL::Arr_algebraic_segment_traits_2< Coefficient > Traits; - typedef typename Traits::Algebraic_real_1 CoordinateType; - typedef typename Traits::Point_2 Point_2; - typedef typename Traits::Intersect_2 Intersect_2; - typedef typename Traits::Multiplicity Multiplicity; - typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; + typedef CGAL::Arr_conic_traits_2 + Traits; + typedef typename Traits::Point_2 Point_2; + typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; + typedef typename ArrTraitsAdaptor::CoordinateType Coordinate_type; + typedef typename Traits::Intersect_2 Intersect_2; + typedef typename Traits::Multiplicity Multiplicity; + typedef std::pair IntersectionResult; + // Construct from traits. + Arr_compute_y_at_x_2(const Traits* traits) : + m_traits(*traits), + intersect_curves(m_traits.intersect_2_object()) + {} + + // Compute the y-coordinate at of the curve at a give x-coordinate. + Coordinate_type + operator()(const X_monotone_curve_2& curve, const Coordinate_type& x); + + // Compute an approximation of the y-coordinate at of the curve at a give + // x-coordinate. + double approx(const X_monotone_curve_2& curve, const Coordinate_type& x); + +private: + const Traits& m_traits; + Intersect_2 intersect_curves; +}; + +// Specialization of `Arr_compute_y_at_x_2` for the algebraic traits. +template +class Arr_compute_y_at_x_2> : + public GraphicsSceneMixin +{ +public: + typedef Coefficient_ Coefficient; + typedef CGAL::Arr_algebraic_segment_traits_2 Traits; + typedef typename Traits::Algebraic_real_1 CoordinateType; + typedef typename Traits::Point_2 Point_2; + typedef typename Traits::Intersect_2 Intersect_2; + typedef typename Traits::Multiplicity Multiplicity; + typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; + + // Arr_compute_y_at_x_2(const Traits* traits_) : traits(traits_) { } + // CoordinateType operator()(const X_monotone_curve_2& curve, const CoordinateType& x); + // double approx(const X_monotone_curve_2& curve, const CoordinateType& x); protected: + // X_monotone_curve_2 makeVerticalLine(const CoordinateType& x); + const Traits* traits; }; -template < - typename RatKernel, typename AlgKernel, typename NtTraits, - typename BoundingTraits> +// Specialization of `Arr_compute_y_at_x_2` for the Bezier traits. +template class Arr_compute_y_at_x_2> : public GraphicsSceneMixin { public: typedef CGAL::Arr_Bezier_curve_traits_2< - RatKernel, AlgKernel, NtTraits, BoundingTraits> Traits; - typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; - typedef typename Traits::Rational Rational; - typedef typename Traits::Algebraic Algebraic; - typedef typename Traits::Point_2 Point_2; + RatKernel, AlgKernel, NtTraits, BoundingTraits> Traits; + typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; + typedef typename Traits::Rational Rational; + typedef typename Traits::Algebraic Algebraic; + typedef typename Traits::Point_2 Point_2; + // Arr_compute_y_at_x_2(const Traits*) { } + // Algebraic operator()(const X_monotone_curve_2& curve, const Rational& x); + + // double approx(const X_monotone_curve_2& curve, const Rational& x); + + // Algebraic get_t(const X_monotone_curve_2& curve, const Rational& x); }; +// Specialization of `Arr_compute_y_at_x_2` for the rational-function traits. template -class Arr_compute_y_at_x_2< - CGAL::Arr_rational_function_traits_2> : +class Arr_compute_y_at_x_2> : public GraphicsSceneMixin { public: typedef CGAL::Arr_rational_function_traits_2 Traits; - typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; - typedef typename Traits::Algebraic_real_1 Algebraic_real_1; - typedef typename Traits::Point_2 Point_2; - typedef typename Traits::Rational Rational; + typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; + typedef typename Traits::Algebraic_real_1 Algebraic_real_1; + typedef typename Traits::Point_2 Point_2; + typedef typename Traits::Rational Rational; - Arr_compute_y_at_x_2(const Traits*) { } + // + Arr_compute_y_at_x_2(const Traits*) {} + // Algebraic_real_1 operator()(const X_monotone_curve_2& curve, const Algebraic_real_1& x); + + // Rational operator()(const X_monotone_curve_2& curve, const Rational& x); + + // double approx(const X_monotone_curve_2& curve, const Rational& x); }; -template -class Compute_squared_distance_2_base : public GraphicsSceneMixin -{ +// Common base class for all `Compute_squared_distance_2` +template +class Compute_squared_distance_2_base : public GraphicsSceneMixin { + using Traits = Traits_; + +public: + // Construct from traits. + Compute_squared_distance_2_base(const Traits& traits) : m_traits(traits) {} + +protected: + const Traits& m_traits; }; -template +// Generic `Compute_squared_distance_2` +template class Compute_squared_distance_2 : - public Compute_squared_distance_2_base< ArrTraits > -{ }; - -template -class Compute_squared_distance_2< CGAL::Arr_segment_traits_2< Kernel_ > > : - public Compute_squared_distance_2_base > + public Compute_squared_distance_2_base { -public: - typedef Kernel_ Kernel; - typedef CGAL::Arr_segment_traits_2< Kernel > Traits; - typedef Compute_squared_distance_2_base< Traits > Superclass; - typedef typename Kernel::FT FT; - typedef typename Kernel::Point_2 Point_2; - typedef typename Kernel::Segment_2 Segment_2; - typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; + using Traits = Traits_; + using Base = Compute_squared_distance_2_base; - double operator() ( const Point_2& p, const X_monotone_curve_2& c ) const; +public: + // Construct from traits. + Compute_squared_distance_2(const Traits& traits) : Base(traits) {} }; -template -class Compute_squared_distance_2< CGAL::Arr_linear_traits_2< Kernel_ > > : - public Compute_squared_distance_2_base > +// Specialization of `Compute_squared_distance_2` for the segment traits. +template +class Compute_squared_distance_2> : + public Compute_squared_distance_2_base> { public: - typedef Kernel_ Kernel; - typedef CGAL::Arr_linear_traits_2< Kernel > Traits; - typedef Compute_squared_distance_2_base< Traits > Superclass; - typedef typename Kernel::FT FT; - typedef typename Kernel::Point_2 Point_2; - typedef typename Kernel::Segment_2 Segment_2; - typedef typename Kernel::Ray_2 Ray_2; - typedef typename Kernel::Line_2 Line_2; - typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; + typedef Kernel_ Kernel; + typedef CGAL::Arr_segment_traits_2 Traits; + typedef Compute_squared_distance_2_base Superclass; + typedef typename Kernel::FT FT; + typedef typename Kernel::Point_2 Point_2; + typedef typename Kernel::Segment_2 Segment_2; + typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; - double operator() ( const Point_2& p, const X_monotone_curve_2& c ) const; + using Base = Compute_squared_distance_2_base; + + // Construct from traits. + Compute_squared_distance_2(const Traits& traits) : Base(traits) {} + + // + double operator() ( const Point_2& p, const X_monotone_curve_2& c) const; }; -template -class Compute_squared_distance_2< CGAL::Arr_polyline_traits_2< Kernel_ > > : - public Compute_squared_distance_2_base > +// Specialization of `Compute_squared_distance_2` for the linear traits. +template +class Compute_squared_distance_2< CGAL::Arr_linear_traits_2< Kernel_>> : + public Compute_squared_distance_2_base> { public: - typedef Kernel_ Kernel; - typedef CGAL::Arr_polyline_traits_2< Kernel > Traits; - typedef Compute_squared_distance_2_base< Traits > Superclass; - typedef typename Kernel::FT FT; - typedef typename Kernel::Point_2 Point_2; - typedef typename Kernel::Segment_2 Segment_2; - typedef typename Traits::Curve_2 Curve_2; - typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; - typedef typename Curve_2::Subcurve_const_iterator Seg_const_it; + typedef Kernel_ Kernel; + typedef CGAL::Arr_linear_traits_2 Traits; + typedef Compute_squared_distance_2_base Superclass; + typedef typename Kernel::FT FT; + typedef typename Kernel::Point_2 Point_2; + typedef typename Kernel::Segment_2 Segment_2; + typedef typename Kernel::Ray_2 Ray_2; + typedef typename Kernel::Line_2 Line_2; + typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; - double operator() ( const Point_2& p, const X_monotone_curve_2& c ) const; + using Base = Compute_squared_distance_2_base; + + // Construct from traits. + Compute_squared_distance_2(const Traits& traits) : Base(traits) {} + + // + double operator()(const Point_2& p, const X_monotone_curve_2& c) const; }; +// Specialization of `Compute_squared_distance_2` for the polyline traits. +template +class Compute_squared_distance_2< CGAL::Arr_polyline_traits_2< Kernel_>> : + public Compute_squared_distance_2_base> +{ +public: + typedef Kernel_ Kernel; + typedef CGAL::Arr_polyline_traits_2 Traits; + typedef Compute_squared_distance_2_base Superclass; + typedef typename Kernel::FT FT; + typedef typename Kernel::Point_2 Point_2; + typedef typename Kernel::Segment_2 Segment_2; + typedef typename Traits::Curve_2 Curve_2; + typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; + typedef typename Curve_2::Subcurve_const_iterator Seg_const_it; + + using Base = Compute_squared_distance_2_base; + + // Construct from traits. + Compute_squared_distance_2(const Traits& traits) : Base(traits) {} + + // + double operator()(const Point_2& p, const X_monotone_curve_2& c) const; +}; + +// Specialization of `Compute_squared_distance_2` for the conic traits. template -class Compute_squared_distance_2< CGAL::Arr_conic_traits_2< RatKernel, - AlgKernel, - NtTraits > > : - public Compute_squared_distance_2_base< CGAL::Arr_conic_traits_2< RatKernel, - AlgKernel, - NtTraits > > +class Compute_squared_distance_2> : + public Compute_squared_distance_2_base> { public: typedef AlgKernel Kernel; - typedef CGAL::Arr_conic_traits_2< RatKernel, AlgKernel, NtTraits > Traits; + typedef CGAL::Arr_conic_traits_2 Traits; typedef Compute_squared_distance_2_base< Traits > Superclass; // _Conic_point_2< AlgKernel > : public AlgKernel::Point_2 typedef typename Traits::Point_2 Conic_point_2; @@ -210,35 +306,48 @@ public: typedef typename Traits::Curve_2 Curve_2; typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; -public: // methods - double operator() ( const Point_2& p, const X_monotone_curve_2& c ) const; -}; + using Base = Compute_squared_distance_2_base; -template < - typename RatKernel, typename AlgKernel, typename NtTraits, - typename BoundingTraits> -class Compute_squared_distance_2> : - public Compute_squared_distance_2_base> -{ -public: - typedef CGAL::Arr_Bezier_curve_traits_2< - RatKernel, AlgKernel, NtTraits, BoundingTraits> - Traits; - typedef typename ArrTraitsAdaptor::Kernel Kernel; - typedef typename Kernel::Point_2 Point_2; - typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; + // Construct from traits. + Compute_squared_distance_2(const Traits& traits) : Base(traits) {} -public: // methods + // double operator()(const Point_2& p, const X_monotone_curve_2& c) const; }; +// Specialization of `Compute_squared_distance_2` for the Bezier traits. +template +class Compute_squared_distance_2 +> : + public Compute_squared_distance_2_base + > +{ +public: + typedef CGAL::Arr_Bezier_curve_traits_2 Traits; + typedef typename ArrTraitsAdaptor::Kernel Kernel; + typedef typename Kernel::Point_2 Point_2; + typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; + + using Base = Compute_squared_distance_2_base; + + // Construct from traits. + Compute_squared_distance_2(const Traits& traits) : Base(traits) {} + + // + double operator()(const Point_2& p, const X_monotone_curve_2& c) const; +}; + +// Specialization of `Compute_squared_distance_2` for the rational-function +// traits. template -class Compute_squared_distance_2< - CGAL::Arr_rational_function_traits_2> : - public Compute_squared_distance_2_base< - CGAL::Arr_rational_function_traits_2> +class Compute_squared_distance_2 + > : + public Compute_squared_distance_2_base + > { public: typedef CGAL::Arr_rational_function_traits_2 Traits; @@ -246,15 +355,21 @@ public: typedef typename Kernel::Point_2 Point_2; typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; -public: + using Base = Compute_squared_distance_2_base; + + // Construct from traits. + Compute_squared_distance_2(const Traits& traits) : Base(traits) {} + + // double operator()(const Point_2& p, const X_monotone_curve_2& c) const; }; -template -class Compute_squared_distance_2< CGAL::Arr_algebraic_segment_traits_2< - Coefficient_ > > : - public Compute_squared_distance_2_base< CGAL::Arr_algebraic_segment_traits_2< - Coefficient_ > > +// Specialization of `Compute_squared_distance_2` for the algebraic traits. +template +class Compute_squared_distance_2 + > : + public Compute_squared_distance_2_base + > { public: typedef Coefficient_ Coefficient; @@ -265,8 +380,8 @@ public: typedef typename Kernel::Point_2 Point_2; typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; typedef typename Traits::CKvA_2 CKvA_2; - typedef std::pair< double, double > Coord_2; - typedef std::vector< Coord_2 > Coord_vec_2; + typedef std::pair Coord_2; + typedef std::vector Coord_vec_2; typedef typename X_monotone_curve_2::Curve_analysis_2 Curve; typedef typename Curve::Polynomial_traits_2 Polynomial_traits_2; typedef typename Curve::Polynomial_2 Polynomial_2; @@ -277,69 +392,75 @@ public: Construct_innermost_coefficient_const_iterator_range ConstructInnerCoeffIter; -public: + using Base = Compute_squared_distance_2_base; + + // Construct from traits. + Compute_squared_distance_2(const Traits& traits) : Base(traits) {} + + // double operator()(const Point_2& p, const X_monotone_curve_2& c) const; }; // chcek if arrangement is a model of the concept ArrangementOpenBoundaryTraits_2 template struct IsOpenBoundaryArrangement : - public CGAL::Boolean_tag< - std::is_convertible< - typename ArrTraits::Left_side_category, - CGAL::Arr_open_side_tag>::value && - std::is_convertible< - typename ArrTraits::Bottom_side_category, - CGAL::Arr_open_side_tag>::value && - std::is_convertible< - typename ArrTraits::Top_side_category, - CGAL::Arr_open_side_tag>::value && - std::is_convertible< - typename ArrTraits::Right_side_category, - CGAL::Arr_open_side_tag>::value> -{ -}; + public CGAL::Boolean_tag< + std::is_convertible< + typename ArrTraits::Left_side_category, + CGAL::Arr_open_side_tag>::value && + std::is_convertible< + typename ArrTraits::Bottom_side_category, + CGAL::Arr_open_side_tag>::value && + std::is_convertible< + typename ArrTraits::Top_side_category, + CGAL::Arr_open_side_tag>::value && + std::is_convertible< + typename ArrTraits::Right_side_category, + CGAL::Arr_open_side_tag>::value> +{}; +// template -class Param_space_in_x_2 -{ +class Param_space_in_x_2 { public: typedef typename ArrTraits::X_monotone_curve_2 X_monotone_curve_2; + // Param_space_in_x_2(const ArrTraits*) {} + + // CGAL::Arr_parameter_space operator()(const X_monotone_curve_2&, CGAL::Arr_curve_end) - { - return CGAL::INTERIOR; - } + { return CGAL::INTERIOR; } }; +// template -class Param_space_in_x_2< - ArrTraits, std::enable_if_t::value>> +class Param_space_in_x_2:: + value>> { public: typedef typename ArrTraits::X_monotone_curve_2 X_monotone_curve_2; typedef typename ArrTraits::Parameter_space_in_x_2 Parameter_space_in_x_2; + // Param_space_in_x_2(const ArrTraits* traits) : parameter_space_in_x_2(traits->parameter_space_in_x_2_object()) - { - } + {} + // CGAL::Arr_parameter_space operator()(const X_monotone_curve_2& curve, CGAL::Arr_curve_end curve_end) - { - return this->parameter_space_in_x_2(curve, curve_end); - } + { return this->parameter_space_in_x_2(curve, curve_end); } private: Parameter_space_in_x_2 parameter_space_in_x_2; }; +// template -class Construct_x_monotone_subcurve_2 -{ +class Construct_x_monotone_subcurve_2 { public: typedef typename ArrTraits::X_monotone_curve_2 X_monotone_curve_2; typedef typename ArrTraits::Split_2 Split_2; @@ -349,77 +470,77 @@ public: typedef Param_space_in_x_2 Parameter_space_in_x_2; typedef typename ArrTraits::Point_2 Point_2; - Construct_x_monotone_subcurve_2( const ArrTraits* traits_ ); + // + Construct_x_monotone_subcurve_2(const ArrTraits* traits_); - /* - Return the subcurve of curve bracketed by pLeft and pRight. - - We assume pLeft and pRight don't lie on the curve and always do a vertical - projection. - */ - X_monotone_curve_2 operator() ( const X_monotone_curve_2& curve, - const boost::optional& pLeft, - const boost::optional& pRight ); + /* Return the subcurve of curve bracketed by pLeft and pRight. + * + * We assume pLeft and pRight don't lie on the curve and always do a vertical + * projection. + */ + X_monotone_curve_2 operator()(const X_monotone_curve_2& curve, + const boost::optional& pLeft, + const boost::optional& pRight); protected: const ArrTraits* traits; Split_2 split_2; Compare_x_2 compare_x_2; - Arr_compute_y_at_x_2< ArrTraits > compute_y_at_x; + Arr_compute_y_at_x_2 compute_y_at_x; Construct_min_vertex_2 construct_min_vertex_2; Construct_max_vertex_2 construct_max_vertex_2; Parameter_space_in_x_2 parameter_space_in_x_2; }; // class Construct_x_monotone_subcurve_2 -/* - * This specialization for conic traits makes use of X_monotone_curve_2::trim, +/* This specialization for conic traits makes use of X_monotone_curve_2::trim, * which is not necessarily available. */ template -class Construct_x_monotone_subcurve_2< CGAL::Arr_conic_traits_2< RatKernel, - AlgKernel, - NtTraits > > +class Construct_x_monotone_subcurve_2> { public: typedef CGAL::Arr_conic_traits_2 - ArrTraits; - typedef typename ArrTraitsAdaptor::Kernel Kernel; - typedef typename ArrTraits::X_monotone_curve_2 X_monotone_curve_2; - typedef typename ArrTraits::Split_2 Split_2; - typedef typename ArrTraits::Intersect_2 Intersect_2; - typedef typename ArrTraits::Multiplicity Multiplicity; - typedef typename ArrTraits::Construct_min_vertex_2 Construct_min_vertex_2; - typedef typename ArrTraits::Construct_max_vertex_2 Construct_max_vertex_2; - typedef typename ArrTraits::Compare_x_2 Compare_x_2; + Traits; + typedef typename ArrTraitsAdaptor::Kernel Kernel; + typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; + typedef typename Traits::Split_2 Split_2; + typedef typename Traits::Intersect_2 Intersect_2; + typedef typename Traits::Multiplicity Multiplicity; + typedef typename Traits::Construct_min_vertex_2 Construct_min_vertex_2; + typedef typename Traits::Construct_max_vertex_2 Construct_max_vertex_2; + typedef typename Traits::Compare_x_2 Compare_x_2; typedef typename Kernel::FT FT; - typedef typename ArrTraitsAdaptor< ArrTraits >::CoordinateType + typedef typename ArrTraitsAdaptor::CoordinateType CoordinateType; - typedef typename ArrTraits::Point_2 Point_2; + typedef typename Traits::Point_2 Point_2; typedef typename Kernel::Point_2 Kernel_point_2; - Construct_x_monotone_subcurve_2( const ArrTraits* ) - { - } + // Construct from traits. + Construct_x_monotone_subcurve_2(const Traits* traits) : m_traits(*traits) {} - /* - Return the subcurve of curve bracketed by pLeft and pRight. - */ - X_monotone_curve_2 operator() ( const X_monotone_curve_2& curve, - const boost::optional& pLeft, - const boost::optional& pRight ); + /* Return the subcurve of curve bracketed by pLeft and pRight. + */ + X_monotone_curve_2 operator()(const X_monotone_curve_2& curve, + const boost::optional& pLeft, + const boost::optional& pRight ); -}; // class Construct_x_monotone_subcurve_2 for Arr_conic_traits_2 +private: + const Traits& m_traits; +}; -template < - typename RatKernel, typename AlgKernel, typename NtTraits, - typename BoundingTraits> -class Construct_x_monotone_subcurve_2> +// +template +class Construct_x_monotone_subcurve_2 +> { public: - typedef CGAL::Arr_Bezier_curve_traits_2< - RatKernel, AlgKernel, NtTraits, BoundingTraits> + typedef CGAL::Arr_Bezier_curve_traits_2 ArrTraits; typedef typename ArrTraits::X_monotone_curve_2 X_monotone_curve_2; typedef typename ArrTraits::Split_2 Split_2; @@ -430,14 +551,15 @@ public: typedef typename ArrTraits::Compare_x_2 Compare_x_2; typedef typename ArrTraits::Point_2 Point_2; + // Construct_x_monotone_subcurve_2(const ArrTraits* traits_); /* Return the subcurve of curve bracketed by pLeft and pRight. */ - X_monotone_curve_2 operator()( - const X_monotone_curve_2& curve, const boost::optional& pLeft, - const boost::optional& pRight); + X_monotone_curve_2 operator()(const X_monotone_curve_2& curve, + const boost::optional& pLeft, + const boost::optional& pRight); protected: const ArrTraits* traits; @@ -446,8 +568,9 @@ protected: Arr_compute_y_at_x_2< ArrTraits > compute_y_at_x; Construct_min_vertex_2 construct_min_vertex_2; Construct_max_vertex_2 construct_max_vertex_2; -}; // class Construct_x_monotone_subcurve_2 for Arr_conic_traits_2 +}; +// template class Construct_x_monotone_subcurve_2< CGAL::Arr_rational_function_traits_2> @@ -471,33 +594,30 @@ public: Construct_x_monotone_subcurve_2( const Traits* traits_ ); - /* - Return the subcurve of curve bracketed by pLeft and pRight. - - We assume pLeft and pRight don't lie on the curve and always do a vertical - projection. - */ - X_monotone_curve_2 operator() ( const X_monotone_curve_2& curve, - const boost::optional& pLeft, - const boost::optional& pRight ); + /* Return the subcurve of curve bracketed by pLeft and pRight. + * + * We assume pLeft and pRight don't lie on the curve and always do a vertical + * projection. + */ + X_monotone_curve_2 operator()(const X_monotone_curve_2& curve, + const boost::optional& pLeft, + const boost::optional& pRight); protected: const Traits* traits; Split_2 split_2; Compare_x_2 compare_x_2; - Arr_compute_y_at_x_2< Traits > compute_y_at_x; + Arr_compute_y_at_x_2 compute_y_at_x; Construct_min_vertex_2 construct_min_vertex_2; Construct_max_vertex_2 construct_max_vertex_2; }; // class Construct_x_monotone_subcurve_2 -/** - Converts between Kernel points and Arrangement points. - - The conversion is not necessarily exact. -*/ +/* Converts between Kernel points and Arrangement points. + * + * The conversion is not necessarily exact. + */ template -class Arr_construct_point_2 -{ +class Arr_construct_point_2 { typedef ArrTraits Traits; typedef typename ArrTraits::Point_2 Point_2; typedef typename ArrTraitsAdaptor< ArrTraits >::CoordinateType CoordinateType; @@ -506,50 +626,53 @@ class Arr_construct_point_2 typedef typename Kernel::FT FT; public: + // Arr_construct_point_2(const Traits* traits_) : traits(traits_) { } + // template - Point_2 operator()(const P& p) - { - return this->operator()(p.x(), p.y()); - } + Point_2 operator()(const P& p) { return this->operator()(p.x(), p.y()); } + // template Point_2 operator()(const T& x, const U& y) - { - return this->operator()(FT{x}, FT{y}); - } + { return this->operator()(FT{x}, FT{y}); } + // Point_2 operator()(const Kernel_point_2& pt); + + // Point_2 operator()(const FT& x, const FT& y); protected: + // template Point_2 operator()(const FT& x, const FT& y, const TTraits*); + // template - Point_2 operator()( - const FT& x, const FT& y, - const CGAL::Arr_rational_function_traits_2*); + Point_2 + operator()(const FT& x, const FT& y, + const CGAL::Arr_rational_function_traits_2*); const Traits* traits; }; -class Find_nearest_edge_base : public GraphicsSceneMixin -{ +// +class Find_nearest_edge_base : public GraphicsSceneMixin { public: - /*! Destructor (virtual) */ + /*! Destructor */ virtual ~Find_nearest_edge_base() {} }; +// template -class Find_nearest_edge : public Find_nearest_edge_base -{ -public: // typedefs - typedef Arr_ Arrangement; - typedef typename Arrangement::Geometry_traits_2 ArrTraits; - typedef Compute_squared_distance_2< ArrTraits > Point_curve_distance; - typedef typename ArrTraits::X_monotone_curve_2 X_monotone_curve_2; +class Find_nearest_edge : public Find_nearest_edge_base { +public: + typedef Arr_ Arrangement; + typedef typename Arrangement::Geometry_traits_2 ArrTraits; + typedef Compute_squared_distance_2 Point_curve_distance; + typedef typename ArrTraits::X_monotone_curve_2 X_monotone_curve_2; typedef typename ArrTraitsAdaptor::Kernel Kernel; typedef typename Kernel::Point_2 Point_2; typedef typename Arrangement::Face_const_handle Face_const_handle; @@ -561,49 +684,53 @@ public: // typedefs public: /*! constructor */ - Find_nearest_edge( Arrangement* arr_ ) : - Find_nearest_edge_base( ), - arr( arr_ ) - { } + Find_nearest_edge(Arrangement* arr_) : + Find_nearest_edge_base(), + arr(arr_) + {} /*! Destructor (virtual) */ virtual ~Find_nearest_edge() {} public: // member methods - Halfedge_const_handle operator()( const Point_2& queryPt ); + // + Halfedge_const_handle operator()(const Point_2& queryPt); - virtual void setScene( QGraphicsScene* scene_ ) - { - this->pointCurveDistance.setScene( scene_ ); - Find_nearest_edge_base::setScene( scene_ ); + // + virtual void setScene(QGraphicsScene* scene_) { + // this->pointCurveDistance.setScene(scene_); + Find_nearest_edge_base::setScene(scene_); } -protected: // member methods - Face_const_handle getFace( const CGAL::Object& obj ); +protected: + // + Face_const_handle getFace(const CGAL::Object& obj); -protected: // member fields +protected: Arrangement* arr; - Point_curve_distance pointCurveDistance; - -}; // class Find_nearest_edge +}; +// template -class Insert_curve -{ +class Insert_curve { public: typedef Arr_ Arrangement; typedef typename Arrangement::Geometry_traits_2 ArrTraits; typedef typename ArrTraits::Curve_2 Curve_2; + // void operator()(Arrangement*, const Curve_2&); }; // free functions gathered here to speed up compilation of other files // specializing once in one file is better than in multiple files CGAL::Object createArrangement(demo_types::TraitsType); + void deleteArrangement(demo_types::TraitsType, const CGAL::Object&); + CGAL::Object makeOverlayArrangement(const std::vector&); -void insertCurve( - demo_types::TraitsType, const CGAL::Object& arr, const CGAL::Object& curve); + +void insertCurve(demo_types::TraitsType, const CGAL::Object& arr, + const CGAL::Object& curve); #endif // CGAL_ARRANGEMENTS_DEMO_UTILS_H From 2856bf77ed21606b6b026b98fe3c4279f557f226 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Sat, 10 Sep 2022 22:35:35 +0300 Subject: [PATCH 079/105] Fixed the conic-related code some emore to use new code (instead of deprecated code). --- .../ArrangementIO.cpp | 82 +++++------ .../Arrangement_on_surface_2/Conic_reader.h | 129 ++++++++---------- .../GraphicsViewCurveInput.cpp | 56 ++++---- 3 files changed, 123 insertions(+), 144 deletions(-) diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementIO.cpp b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementIO.cpp index 5a9be364d6f..a6c573a9b4b 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementIO.cpp +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementIO.cpp @@ -19,13 +19,10 @@ #include #include -template < - typename Arrangement, - typename Traits = typename Arrangement::Geometry_traits_2> -struct ArrReader -{ - Arrangement* operator()(std::ifstream& ifs) - { +template +struct ArrReader { + Arrangement* operator()(std::ifstream& ifs) { using Text_formatter = CGAL::Arr_text_formatter; using ArrFormatter = CGAL::Arr_with_history_text_formatter; @@ -37,33 +34,34 @@ struct ArrReader }; #ifdef CGAL_USE_CORE -template < - typename Arrangement, typename Rat_kernel_, typename Alg_kernel_, - typename Nt_traits_> -struct ArrReader< - Arrangement, CGAL::Arr_conic_traits_2> + +// Specialization of `ArrReader` for the conic traits. +template +struct ArrReader> { using Traits = typename Arrangement::Geometry_traits_2; using Curve_2 = typename Arrangement::Curve_2; - Arrangement* operator()(std::ifstream& ifs) - { - Conic_reader conicReader; + Arrangement* operator()(std::ifstream& ifs) { + Traits* traits = new Traits; + Conic_reader conicReader(*traits);; std::vector curve_list; CGAL::Bbox_2 bbox; conicReader.read_data(ifs, std::back_inserter(curve_list), bbox); - auto arr = new Arrangement(); + auto arr = new Arrangement(traits); CGAL::insert(*arr, curve_list.begin(), curve_list.end()); return arr; } }; -template < - typename Arrangement, typename Rat_kernel_, typename Alg_kernel_, - typename Nt_traits_, typename Bounding_traits_> -struct ArrReader< - Arrangement, CGAL::Arr_Bezier_curve_traits_2< - Rat_kernel_, Alg_kernel_, Nt_traits_, Bounding_traits_>> +// Specialization of `ArrReader` for the Bezier traits. +template +struct ArrReader> { Arrangement* operator()(std::ifstream&) { return nullptr; } }; @@ -77,8 +75,7 @@ struct ArrReader< #endif std::pair -ArrangementIO::read(std::ifstream& ifs) -{ +ArrangementIO::read(std::ifstream& ifs) { // read type info while (ifs.peek() == '#' || std::isspace(ifs.peek())) ifs.get(); @@ -95,13 +92,10 @@ ArrangementIO::read(std::ifstream& ifs) return res; } -template < - typename Arrangement, - typename Traits = typename Arrangement::Geometry_traits_2> -struct ArrWriter -{ - void operator()(Arrangement* arr, std::ofstream& ofs) - { +template +struct ArrWriter { + void operator()(Arrangement* arr, std::ofstream& ofs) { using TextFormatter = CGAL::Arr_text_formatter; using ArrFormatter = CGAL::Arr_with_history_text_formatter; @@ -111,19 +105,18 @@ struct ArrWriter }; #ifdef CGAL_USE_CORE -template < - typename Arrangement, typename Rat_kernel_, typename Alg_kernel_, - typename Nt_traits_> -struct ArrWriter< - Arrangement, CGAL::Arr_conic_traits_2> + +template +struct ArrWriter> { using Traits = typename Arrangement::Geometry_traits_2; using Curve_2 = typename Arrangement::Curve_2; - void operator()(Arrangement* arr, std::ofstream& ofs) - { - Conic_reader conicReader; - conicReader.write_data(ofs, arr->curves_begin(), arr->curves_end()); + void operator()(Arrangement* arr, std::ofstream& ofs) { + Conic_reader conic_reader(*(arr->geometry_traits())); + conic_reader.write_data(ofs, arr->curves_begin(), arr->curves_end()); } }; @@ -145,9 +138,9 @@ struct ArrWriter< }; #endif -bool ArrangementIO::write( - const std::pair& arr_pair, - std::ofstream& ofs) +bool ArrangementIO::write(const std::pair& arr_pair, + std::ofstream& ofs) { auto tt = arr_pair.second; auto arr_obj = arr_pair.first; @@ -159,8 +152,7 @@ bool ArrangementIO::write( demo_types::visitArrangementType(tt, [&](auto type_holder) { using Arrangement = typename decltype(type_holder)::type; Arrangement* arr; - if (CGAL::assign(arr, arr_obj)) - { + if (CGAL::assign(arr, arr_obj)) { ArrWriter{}(arr, ofs); result = true; } diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/Conic_reader.h b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/Conic_reader.h index ada4f896c4d..6d16a471b40 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/Conic_reader.h +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/Conic_reader.h @@ -18,8 +18,10 @@ #include template -class Conic_reader -{ +class Conic_reader { +private: + const Traits& m_traits; + public: typedef typename Traits::Curve_2 Curve_2; typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; @@ -31,9 +33,13 @@ public: typedef typename Traits::Rat_segment_2 Rat_segment_2; typedef typename Traits::Rat_circle_2 Rat_circle_2; - template - int read_data(std::ifstream & inp, OutputIterator curves_out, - CGAL::Bbox_2 & bbox) + // Cnstruct from traits. + Conic_reader(const Traits& traits) : m_traits(traits) {} + + // + template + int read_data(std::ifstream& inp, OutputIterator curves_out, + CGAL::Bbox_2& bbox) { Curve_2 cv; @@ -49,7 +55,7 @@ public: for (int i = 0; i < count; i++) { if (read_curve(inp, cv)) { ++curves_out = cv; - CGAL::Bbox_2 curve_bbox = cv.bbox(); + CGAL::Bbox_2 curve_bbox = m_traits.construct_bbox_2_object()(cv); if (i == 0) bbox = curve_bbox; else bbox = bbox + curve_bbox; } @@ -58,8 +64,9 @@ public: } /*! */ - bool read_curve(std::ifstream & is, Curve_2 & cv) - { + bool read_curve(std::ifstream& is, Curve_2& cv) { + auto ctr_cv = m_traits.construct_curve_2_object(); + // Read a line from the input file. char one_line[128]; @@ -67,12 +74,11 @@ public: std::istringstream str_line (one_line); // Read the arc type and act accordingly. - char type; + char type; str_line >> type; - if (type == 's' || type == 'S') - { + if (type == 's' || type == 'S') { // Construct a line segment. The line should have the format: // s // where (x1, y1), (x2, y2) are the endpoints of a segment. @@ -81,49 +87,46 @@ public: //str_line >> x1 >> y1 >> x2 >> y2; str_line >> buf; - x1 = Algebraic( buf ).BigRatValue( ); + x1 = Algebraic( buf ).BigRatValue(); str_line >> buf; - y1 = Algebraic( buf ).BigRatValue( ); + y1 = Algebraic( buf ).BigRatValue(); str_line >> buf; - x2 = Algebraic( buf ).BigRatValue( ); + x2 = Algebraic( buf ).BigRatValue(); str_line >> buf; - y2 = Algebraic( buf ).BigRatValue( ); + y2 = Algebraic( buf ).BigRatValue(); - Rat_point_2 p1(x1, y1), p2(x2, y2); - Rat_segment_2 seg (p1, p2); + Rat_point_2 p1(x1, y1), p2(x2, y2); + Rat_segment_2 seg(p1, p2); - cv = Curve_2 (seg); + cv = ctr_cv(seg); } - else if (type == 'c' || type == 'C') - { + else if (type == 'c' || type == 'C') { // Construct a full circle. The line should have the format: // c // where (x0, y0) is the center of the circle and R_sq is its squared // radius. - Rational x0, y0, R_sq; + Rational x0, y0, R_sq; str_line >> x0 >> y0 >> R_sq; - Rat_point_2 p0(x0, y0); - Rat_circle_2 circ(p0, R_sq); + Rat_point_2 p0(x0, y0); + Rat_circle_2 circ(p0, R_sq); - cv = Curve_2 (circ); + cv = ctr_cv(circ); } - else if (type == 't' || type == 'T') - { + else if (type == 't' || type == 'T') { // Construct a circular arc. The line should have the format: // t // where (x1, y1), (x2, y2) and (x3, y3) define the arc. - Rational x1, y1, x2, y2, x3, y3; + Rational x1, y1, x2, y2, x3, y3; str_line >> x1 >> y1 >> x2 >> y2 >> x3 >> y3; - Rat_point_2 p1(x1, y1), p2(x2, y2), p3(x3, y3); + Rat_point_2 p1(x1, y1), p2(x2, y2), p3(x3, y3); - cv = Curve_2 (p1, p2, p3); + cv = ctr_cv(p1, p2, p3); } - else if (type == 'f' || type == 'F') - { + else if (type == 'f' || type == 'F') { // Construct a full conic curve. The line should have the format: // c // where r, s, t, u, v, w define the conic equation. @@ -131,10 +134,9 @@ public: str_line >> r >> s >> t >> u >> v >> w; - cv = Curve_2 (r, s, t, u, v, w); + cv = ctr_cv(r, s, t, u, v, w); } - else if (type == 'a' || type == 'A') - { + else if (type == 'a' || type == 'A') { // Construct a conic arc. The line should have the format: // c // where r, s, t, u, v, w define the conic equation, while (x1, y1) @@ -144,16 +146,13 @@ public: str_line >> r >> s >> t >> u >> v >> w; // Read the orientation. - int i_orient; + int i_orient; CGAL::Orientation orient; str_line >> i_orient; - if (i_orient > 0) - orient = CGAL::COUNTERCLOCKWISE; - else if (i_orient < 0) - orient = CGAL::CLOCKWISE; - else - orient = CGAL::COLLINEAR; + if (i_orient > 0) orient = CGAL::COUNTERCLOCKWISE; + else if (i_orient < 0) orient = CGAL::CLOCKWISE; + else orient = CGAL::COLLINEAR; // Read the end points of the arc and create it. // Notice we read the coordinates as strings, then we convert them to @@ -175,10 +174,9 @@ public: Point_2 ps (x1, y1); Point_2 pt (x2, y2); - cv = Curve_2 (r, s, t, u, v, w, orient, ps ,pt); + cv = ctr_cv(r, s, t, u, v, w, orient, ps ,pt); } - else if (type == 'q' || type == 'Q') - { + else if (type == 'q' || type == 'Q') { // Construct a circular arc. The line should have the format: // t // where (x1, y1), (x2, y2), (x3, y3), (x4, y4) and (x5, y5) define the @@ -189,16 +187,15 @@ public: Rat_point_2 p1(x1, y1), p2(x2, y2), p3(x3, y3), p4(x4, y4), p5(x5, y5); - cv = Curve_2 (p1, p2, p3, p4, p5); + cv = ctr_cv(p1, p2, p3, p4, p5); } - else if(type == 'e' || type == 'E') - { + else if(type == 'e' || type == 'E') { // Construct a full ellipse. The line should have the format: // e // raddi and center of ellipse - int x0, y0, r1, r2; - Rational sqr_r1, sqr_r2; - Rational R, S, T, U, V, W; + int x0, y0, r1, r2; + Rational sqr_r1, sqr_r2; + Rational R, S, T, U, V, W; str_line >> r1 >> r2 >> x0 >> y0; @@ -211,10 +208,9 @@ public: V = -2 * sqr_r1 * y0; W = sqr_r2*x0*x0 + sqr_r1*y0*y0 - sqr_r1*sqr_r2; - cv = Curve_2 (R, S, T, U, V, W); + cv = ctr_cv(R, S, T, U, V, W); } - else - { + else { std::cerr << "Illegal conic type specification: " << type << "." << std::endl; return false; @@ -224,8 +220,7 @@ public: } /*! */ - void skip_comments( std::ifstream& is, char* one_line ) - { + void skip_comments(std::ifstream& is, char* one_line) { while (!is.eof()) { is.getline(one_line, 128); if (one_line[0] != '#') break; @@ -234,13 +229,10 @@ public: // should probably change class name since it reads and writes template - int write_data(std::ofstream & ofs, InputIterator begin_, InputIterator end_) - { + int write_data(std::ofstream& ofs, InputIterator begin_, InputIterator end_) { ofs << std::distance(begin_, end_) << std::endl; - for (auto it = begin_; it != end_; ++it) - { - if (it->is_full_conic()) - { + for (auto it = begin_; it != end_; ++it) { + if (it->is_full_conic()) { ofs << "F "; ofs << it->r() << " "; ofs << it->s() << " "; @@ -250,15 +242,13 @@ public: ofs << it->w() << " "; ofs << std::endl; } - else if (it->orientation() == CGAL::COLLINEAR) - { + else if (it->orientation() == CGAL::COLLINEAR) { ofs << "S "; ofs << it->source() << " "; ofs << it->target() << " "; ofs << std::endl; } - else - { + else { ofs << "A "; ofs << it->r() << " "; ofs << it->s() << " "; @@ -266,12 +256,9 @@ public: ofs << it->u() << " "; ofs << it->v() << " "; ofs << it->w() << " "; - if (it->orientation() == CGAL::COUNTERCLOCKWISE) - ofs << "1 "; - else if (it->orientation() == CGAL::CLOCKWISE) - ofs << "-1 "; - else - ofs << "0 "; + if (it->orientation() == CGAL::COUNTERCLOCKWISE) ofs << "1 "; + else if (it->orientation() == CGAL::CLOCKWISE) ofs << "-1 "; + else ofs << "0 "; ofs << it->source() << " "; ofs << it->target() << " "; ofs << std::endl; diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/GraphicsViewCurveInput.cpp b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/GraphicsViewCurveInput.cpp index f8c84a575ee..efb267ee55f 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/GraphicsViewCurveInput.cpp +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/GraphicsViewCurveInput.cpp @@ -41,16 +41,17 @@ namespace CGAL { namespace Qt { // -GraphicsViewCurveInputBase::GraphicsViewCurveInputBase( - QObject* parent, QGraphicsScene* scene) : - Callback(parent, scene), - inputMethod(nullptr) +GraphicsViewCurveInputBase:: +GraphicsViewCurveInputBase(QObject* parent, QGraphicsScene* scene) : + Callback(parent, scene), + inputMethod(nullptr) {} // void GraphicsViewCurveInputBase::setInputMethod(CurveInputMethod* inputMethod_) { this->inputMethod = inputMethod_; } +// void GraphicsViewCurveInputBase::reset() { if (this->inputMethod) { this->inputMethod->reset(); @@ -68,18 +69,18 @@ void GraphicsViewCurveInputBase::setColor(QColor c) // template -GraphicsViewCurveInput::GraphicsViewCurveInput( - Arrangement* arrangement_, QObject* parent, QGraphicsScene* scene) : - GraphicsViewCurveInputBase(parent, scene), - arrangement(arrangement_) +GraphicsViewCurveInput:: +GraphicsViewCurveInput(Arrangement* arrangement_, QObject* parent, + QGraphicsScene* scene) : + GraphicsViewCurveInputBase(parent, scene), + arrangement(arrangement_) { - this->setDefaultInputMethod( - std::integral_constant< - bool, std::tuple_size::value != 0>{}); + this->setDefaultInputMethod(std::integral_constant::value != 0>{}); for_each(inputMethods, [&](auto&& it) { - it.setScene(scene); - it.setCallback(this); - }); + it.setScene(scene); + it.setCallback(this); + }); curveGenerator.setTraits(this->arrangement->traits()); } @@ -87,10 +88,11 @@ GraphicsViewCurveInput::GraphicsViewCurveInput( template void GraphicsViewCurveInput::setCurveType(CurveType type) { this->reset(); - for_each(inputMethods, [&](auto&& it) { - if (it.curveType() == type) - this->setInputMethod(static_cast(&it)); - }); + for_each(inputMethods, + [&](auto&& it) { + if (it.curveType() == type) + this->setInputMethod(static_cast(&it)); + }); } // @@ -136,8 +138,7 @@ generate(const std::vector& clickedPoints, CurveType type) -> boost::optional { boost::optional res; - switch (type) - { + switch (type) { case CurveType::Segment: res = generateSegment(clickedPoints); break; @@ -177,8 +178,9 @@ void CurveGeneratorBase::setTraits(const ArrTraits* traits_) // Curve Generator Segment Traits template -auto CurveGenerator>::generateSegment( - const std::vector& clickedPoints) -> boost::optional +auto CurveGenerator>:: +generateSegment(const std::vector& clickedPoints) + -> boost::optional { Curve_2 res{clickedPoints[0], clickedPoints[1]}; return res; @@ -331,8 +333,7 @@ generateFivePointConicArc(const std::vector& points) // CurveGenerator Algebraic Traits template auto CurveGenerator>:: -generateLine(const std::vector& points) -> boost::optional -{ +generateLine(const std::vector& points) -> boost::optional { RationalTraits ratTraits; Rational dx = points[1].x() - points[0].x(); @@ -368,8 +369,7 @@ generateLine(const std::vector& points) -> boost::optional // template auto CurveGenerator>:: -generateCircle(const std::vector& points) -> boost::optional -{ +generateCircle(const std::vector& points) -> boost::optional { auto sq_rad = (points[0].x() - points[1].x()) * (points[0].x() - points[1].x()) + (points[0].y() - points[1].y()) * (points[0].y() - points[1].y()); @@ -378,8 +378,8 @@ generateCircle(const std::vector& points) -> boost::optional template auto CurveGenerator>:: - generateEllipse(const std::vector& points) - -> boost::optional +generateEllipse(const std::vector& points) + -> boost::optional { auto rx = (points[0].x() - points[1].x()) * (points[0].x() - points[1].x()) / 4.; From 6f103e4de153e1942601a95f24292250360cc0e0 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Sun, 11 Sep 2022 00:30:15 +0300 Subject: [PATCH 080/105] Fixed the conic-related code even more to use new code (instead of deprecated code). --- .../ArrangementGraphicsItem.cpp | 585 ++++++++---------- .../ArrangementTypesUtils.h | 8 +- .../CurveGraphicsItem.cpp | 122 ++-- .../CurveGraphicsItem.h | 57 +- .../DeleteCurveCallback.cpp | 62 +- .../EnvelopeCallback.cpp | 14 +- .../MergeEdgeCallback.cpp | 19 +- .../PointLocationCallback.cpp | 72 +-- .../Utils/ConstructBoundingBox.cpp | 247 ++++---- .../Utils/ConstructBoundingBox.h | 12 +- .../VerticalRayShootCallback.cpp | 128 ++-- 11 files changed, 651 insertions(+), 675 deletions(-) diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementGraphicsItem.cpp b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementGraphicsItem.cpp index 5e37e2ab62a..2b9d8b46a64 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementGraphicsItem.cpp +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementGraphicsItem.cpp @@ -27,6 +27,7 @@ namespace Qt { static constexpr int margin = 2; +// ArrangementGraphicsItemBase::ArrangementGraphicsItemBase() : verticesPen(QPen(::Qt::blue, 3.)), edgesPen(QPen(::Qt::blue, 1.)) { @@ -38,13 +39,10 @@ ArrangementGraphicsItemBase::ArrangementGraphicsItemBase() : } // msvc2015 doesn't play well with polymorphic lambdas -namespace -{ -struct ExplicitLambda -{ +namespace { +struct ExplicitLambda { template - void operator()(demo_types::TypeHolder) - { + void operator()(demo_types::TypeHolder) { Arrangement* arr = nullptr; CGAL::assign(arr, arr_obj); agi = new ArrangementGraphicsItem(arr); @@ -53,10 +51,13 @@ struct ExplicitLambda ArrangementGraphicsItemBase*& agi; CGAL::Object& arr_obj; }; + } // anonymous namespace -ArrangementGraphicsItemBase* ArrangementGraphicsItemBase::create( - demo_types::TraitsType tt, CGAL::Object arr_obj) +// +ArrangementGraphicsItemBase* +ArrangementGraphicsItemBase::create(demo_types::TraitsType tt, + CGAL::Object arr_obj) { ArrangementGraphicsItemBase* agi; ExplicitLambda explicit_lambda{agi, arr_obj}; @@ -64,39 +65,35 @@ ArrangementGraphicsItemBase* ArrangementGraphicsItemBase::create( return agi; } +// const QPen& ArrangementGraphicsItemBase::getVerticesPen() const -{ - return this->verticesPen; -} +{ return this->verticesPen; } +// const QPen& ArrangementGraphicsItemBase::getEdgesPen() const -{ - return this->edgesPen; -} +{ return this->edgesPen; } +// void ArrangementGraphicsItemBase::setVerticesPen(const QPen& pen) -{ - this->verticesPen = pen; -} +{ this->verticesPen = pen; } +// void ArrangementGraphicsItemBase::setEdgesPen(const QPen& pen) -{ - this->edgesPen = pen; -} +{ this->edgesPen = pen; } +// template ArrangementGraphicsItem::ArrangementGraphicsItem(Arrangement* arr_) : - arr(arr_), pointsGraphicsItem(new PointsGraphicsItem(this)) + arr(arr_), + pointsGraphicsItem(new PointsGraphicsItem(this)) { this->updatePointsItem(); this->updateBoundingBox(); } +// template < typename Arr_ > -QRectF -ArrangementGraphicsItem< Arr_ >:: -boundingRect( ) const -{ +QRectF ArrangementGraphicsItem< Arr_ >::boundingRect() const { qreal xmin = -(std::numeric_limits::max)() / 4; qreal ymin = -(std::numeric_limits::max)() / 4; qreal xmax = (std::numeric_limits::max)() / 4; @@ -115,48 +112,47 @@ boundingRect( ) const return {QPointF{xmin, ymin}, QPointF{xmax, ymax}}; } +// template < typename Arr_ > void ArrangementGraphicsItem< Arr_ >:: paint(QPainter* painter, const QStyleOptionGraphicsItem* /* option */, QWidget* /*widget*/) -{ - this->paint(painter, *(arr->traits())); -} +{ this->paint(painter, *(arr->traits())); } +// template template -void ArrangementGraphicsItem::paint( - QPainter* painter, const TTraits& traits) -{ +void ArrangementGraphicsItem::paint(QPainter* painter, + const TTraits& traits) { this->paintFaces(painter); this->paintEdges(painter, traits); } +// template template -void ArrangementGraphicsItem::paint( - QPainter* painter, - const CGAL::Arr_algebraic_segment_traits_2& traits) -{ +void ArrangementGraphicsItem:: +paint(QPainter* painter, + const CGAL::Arr_algebraic_segment_traits_2& traits) { this->paintWithFloodFill(painter, traits); } +// template template -void ArrangementGraphicsItem::paint( - QPainter* painter, - const CGAL::Arr_rational_function_traits_2& traits) -{ +void ArrangementGraphicsItem:: +paint(QPainter* painter, + const CGAL::Arr_rational_function_traits_2& traits) { this->paintWithFloodFill(painter, traits); } +// template template -void ArrangementGraphicsItem::paintWithFloodFill( - QPainter* painter, const TTraits& traits) -{ +void ArrangementGraphicsItem:: +paintWithFloodFill(QPainter* painter, const TTraits& traits) { auto windowRect = painter->window(); auto width = windowRect.width(); auto height = windowRect.height(); @@ -171,15 +167,12 @@ void ArrangementGraphicsItem::paintWithFloodFill( // also useful with algebraic curves as sometimes pixels on the borders // aren't painted, and the flood algorithm 'leaks' static constexpr QRgb white = 0xFFFFFFFF; - for (uint16_t i = 0; i < margin; i++) - { - for (uint16_t j = 0; j < width; j++) - { + for (uint16_t i = 0; i < margin; i++) { + for (uint16_t j = 0; j < width; j++) { st[i * width + j] = white; st[(height - 1 - i) * width + j] = white; } - for (uint16_t j = 0; j < height; j++) - { + for (uint16_t j = 0; j < height; j++) { st[j * width + i] = white; st[j * width + (width - 1 - i)] = white; } @@ -204,11 +197,11 @@ void ArrangementGraphicsItem::paintWithFloodFill( painter->setTransform(painterTransform); } +// template template -void ArrangementGraphicsItem::paintEdges( - QPainter* painter, const TTraits&) -{ +void ArrangementGraphicsItem::paintEdges(QPainter* painter, + const TTraits&) { auto painterOstream = ArrangementPainterOstream(painter, this->boundingRect()); @@ -223,11 +216,12 @@ void ArrangementGraphicsItem::paintEdges( } } +// template template -void ArrangementGraphicsItem::paintEdges( - QPainter* painter, const CGAL::Arr_algebraic_segment_traits_2&) -{ +void ArrangementGraphicsItem:: +paintEdges(QPainter* painter, + const CGAL::Arr_algebraic_segment_traits_2&) { using TTraits = CGAL::Arr_algebraic_segment_traits_2; auto painterOstream = @@ -240,10 +234,10 @@ void ArrangementGraphicsItem::paintEdges( painterOstream.paintEdges(arr->edges_begin(), arr->edges_end()); } +// template -void ArrangementGraphicsItem::paintFacesFloodFill( - QPainter* painter, QImage& image) -{ +void ArrangementGraphicsItem::paintFacesFloodFill(QPainter* painter, + QImage& image) { static constexpr QRgb invalid_rgb = 0; QRgb* raw_img = reinterpret_cast(image.bits()); @@ -267,10 +261,8 @@ void ArrangementGraphicsItem::paintFacesFloodFill( static constexpr int tot_margin = margin + 2; auto cur_img_line = raw_img + tot_margin * width; - for (uint16_t y = tot_margin; y + 1 + tot_margin < height; y++) - { - for (uint16_t x = tot_margin; x + 1 + tot_margin < width; x++) - { + for (uint16_t y = tot_margin; y + 1 + tot_margin < height; y++) { + for (uint16_t x = tot_margin; x + 1 + tot_margin < width; x++) { // just to account for rendering errors // make sure the pixel falls in the right face if ( @@ -305,24 +297,24 @@ void ArrangementGraphicsItem::paintFacesFloodFill( } } -template < typename Arr_ > -void ArrangementGraphicsItem< Arr_ >::updateBoundingBox( ) -{ +// +template +void ArrangementGraphicsItem::updateBoundingBox() { this->prepareGeometryChange(); this->bb = {}; - ConstructBoundingBox construct_bounding_box; + ConstructBoundingBox ctr_bbox(*(this->arr->geometry_traits())); for (auto it = this->arr->edges_begin(); it != this->arr->edges_end(); ++it) - this->bb += construct_bounding_box(it->curve()); + this->bb += ctr_bbox(it->curve()); for (auto it = this->arr->vertices_begin(); it != this->arr->vertices_end(); ++it) - this->bb += construct_bounding_box(it->point()); + this->bb += ctr_bbox(it->point()); } +// template -void ArrangementGraphicsItem::updatePointsItem() -{ +void ArrangementGraphicsItem::updatePointsItem() { this->pointsGraphicsItem->clear(); for (auto it = this->arr->vertices_begin(); it != this->arr->vertices_end(); ++it) @@ -332,31 +324,27 @@ void ArrangementGraphicsItem::updatePointsItem() } } -template < typename Arr_ > -void ArrangementGraphicsItem< Arr_ >::modelChanged( ) -{ +// +template +void ArrangementGraphicsItem::modelChanged() { this->updatePointsItem(); - this->updateBoundingBox( ); - this->update( ); + this->updateBoundingBox(); + this->update(); } template < typename Arr_ > void -ArrangementGraphicsItem< Arr_ >:: -paintFace( Face_handle f, QPainter* painter ) -{ +ArrangementGraphicsItem::paintFace( Face_handle f, QPainter* painter) { if (f->visited()) return; Hole_iterator hit; // holes iterator this->paintFace(f, painter, *(arr->traits())); f->set_visited(true); - for (hit = f->holes_begin(); hit != f->holes_end(); ++hit) - { + for (hit = f->holes_begin(); hit != f->holes_end(); ++hit) { // Traverse in clockwise order Ccb_halfedge_circulator cc = *hit; - do - { + do { Halfedge_handle he = cc; Halfedge_handle he2 = he->twin(); Face_handle inner_face = he2->face(); @@ -367,13 +355,14 @@ paintFace( Face_handle f, QPainter* painter ) } } +// template template -void ArrangementGraphicsItem::paintFace( - Face_handle f, QPainter* painter, const CGAL::Arr_segment_traits_2&) -{ - if (!f->is_unbounded()) // f is not the unbounded face - { +void ArrangementGraphicsItem:: +paintFace(Face_handle f, QPainter* painter, + const CGAL::Arr_segment_traits_2&) { + if (!f->is_unbounded()) { + // f is not the unbounded face QVector< QPointF > pts; // holds the points of the polygon /* running with around the outer of the face and generate from it @@ -403,13 +392,13 @@ void ArrangementGraphicsItem::paintFace( } } +// template template -void ArrangementGraphicsItem::paintFace( - Face_handle f, QPainter* painter, const CGAL::Arr_polyline_traits_2&) -{ - if (!f->is_unbounded()) - { +void ArrangementGraphicsItem:: +paintFace(Face_handle f, QPainter* painter, + const CGAL::Arr_polyline_traits_2&) { + if (!f->is_unbounded()) { QVector< QPointF > pts; // holds the points of the polygon CGAL::Qt::Converter convert; @@ -433,8 +422,7 @@ void ArrangementGraphicsItem::paintFace( auto first_subcurve = curve.subcurves_begin(); QPointF src_first = convert(first_subcurve->source()); - if (src_first == src) - { + if (src_first == src) { for (auto it = curve.subcurves_begin(); it != curve.subcurves_end(); ++it) { @@ -442,8 +430,7 @@ void ArrangementGraphicsItem::paintFace( pts.push_back(convert(it->target())); } } - else - { + else { QVector pts_tmp; for (auto it = curve.subcurves_begin(); it != curve.subcurves_end(); ++it) @@ -461,19 +448,19 @@ void ArrangementGraphicsItem::paintFace( painter->setBrush(f->color()); painter->drawPolygon( pgn ); } - else - { + else { QRectF rect = this->viewportRect( ); QColor color = f->color(); painter->fillRect(rect, color); } } +// template template -void ArrangementGraphicsItem::paintFace( - Face_handle f, QPainter* painter, - const CGAL::Arr_algebraic_segment_traits_2& /* traits */) +void ArrangementGraphicsItem:: +paintFace(Face_handle f, QPainter* painter, + const CGAL::Arr_algebraic_segment_traits_2& /* traits */) { if (f->is_unbounded()) return; @@ -489,8 +476,7 @@ void ArrangementGraphicsItem::paintFace( * polygon */ Ccb_halfedge_circulator cc = f->outer_ccb(); - do - { + do { if (this->antenna(cc)) continue; auto points = painterOstream.getPointsList(cc->curve()); @@ -499,14 +485,12 @@ void ArrangementGraphicsItem::paintFace( double src_x = CGAL::to_double(cc->source()->point().x()); double tgt_x = CGAL::to_double(cc->target()->point().x()); - if (src_x < tgt_x) - { + if (src_x < tgt_x) { for (auto& vec : points) for(auto& vit : vec) pts.push_back({vit.first, vit.second}); } - else - { + else { for (auto vecit = points.rbegin(); vecit != points.rend(); ++vecit) for (auto vit = vecit->rbegin(); vit != vecit->rend(); ++vit) pts.push_back({vit->first, vit->second}); @@ -521,9 +505,9 @@ void ArrangementGraphicsItem::paintFace( painter->restore(); } +// template -void ArrangementGraphicsItem::paintFaces(QPainter* painter) -{ +void ArrangementGraphicsItem::paintFaces(QPainter* painter) { QPen pen = painter->pen(); painter->setPen(this->facesPen); @@ -537,18 +521,16 @@ void ArrangementGraphicsItem::paintFaces(QPainter* painter) painter->setPen(pen); } +// template -void ArrangementGraphicsItem::visit_ccb_faces( - Face_handle& fh, QPainter* painter) -{ +void ArrangementGraphicsItem::visit_ccb_faces(Face_handle& fh, + QPainter* painter) { this->paintFace(fh, painter); Ccb_halfedge_circulator cc = fh->outer_ccb(); - do - { + do { Halfedge he = *cc; - if (!he.twin()->face()->visited()) - { + if (!he.twin()->face()->visited()) { Face_handle nei = he.twin()->face(); this->visit_ccb_faces(nei, painter); } @@ -556,34 +538,34 @@ void ArrangementGraphicsItem::visit_ccb_faces( } while (++cc != fh->outer_ccb()); } +// template -bool ArrangementGraphicsItem::antenna(Halfedge_handle h) -{ +bool ArrangementGraphicsItem::antenna(Halfedge_handle h) { Halfedge_handle twin = h->twin(); return (twin->face() == h->face()); } +// template template void ArrangementGraphicsItem::paintFace(Face_handle, QPainter*, ArrTraits) -{ -} +{} +// template template -void ArrangementGraphicsItem::paintFace( - Face_handle f, QPainter* painter, - const CGAL::Arr_conic_traits_2& traits) +void ArrangementGraphicsItem:: +paintFace(Face_handle f, QPainter* painter, + const CGAL::Arr_conic_traits_2& traits) { - if (!f->is_unbounded()) // f is not the unbounded face - { + if (!f->is_unbounded()) { + // f is not the unbounded face QVector pts; // holds the points of the polygon /* running with around the outer of the face and generate from it * polygon */ Ccb_halfedge_circulator cc = f->outer_ccb(); - do - { + do { if (this->antenna(cc)) { continue; } Halfedge_handle he = cc; @@ -603,8 +585,7 @@ void ArrangementGraphicsItem::paintFace( QPoint coord_target_viewport = this->fromScene(coord_target); if (c.orientation() == CGAL::COLLINEAR) { pts.push_back(coord_source); } - else - { + else { // If the curve is monotone, than its source and its target has the // extreme x co-ordinates on this curve. bool is_source_left = (sx < tx); @@ -620,20 +601,17 @@ void ArrangementGraphicsItem::paintFace( int start; int end; int step; - if (is_source_left) - { + if (is_source_left) { start = x_min + DRAW_FACTOR; end = x_max; step = DRAW_FACTOR; } - else - { + else { start = x_max; end = x_min; step = -DRAW_FACTOR; } - for (int x = start; x < end; x += step) - { + for (int x = start; x < end; x += step) { double curr_x = this->toScene(QPoint{x, 0}).x(); AlgKernel ker; Point_2 curr_p(curr_x, 0); @@ -656,33 +634,30 @@ void ArrangementGraphicsItem::paintFace( painter->setBrush(f->color()); painter->drawPolygon(pgn); } - else - { + else { QRectF rect = this->viewportRect(); QColor color = f->color(); painter->fillRect(rect, color); } } +// template -template < - typename RatKernel, typename AlgKernel, typename NtTraits, - typename BoundingTraits> -void ArrangementGraphicsItem::paintFace( - Face_handle f, QPainter* painter, - const CGAL::Arr_Bezier_curve_traits_2< - RatKernel, AlgKernel, NtTraits, BoundingTraits>&) +template +void ArrangementGraphicsItem:: +paintFace(Face_handle f, QPainter* painter, + const CGAL::Arr_Bezier_curve_traits_2 + &) { - if (!f->is_unbounded()) - { + if (!f->is_unbounded()) { ArrangementPainterOstream painterOstream{ painter, this->boundingRect()}; painterOstream.setScene(this->getScene()); QVector pts; Ccb_halfedge_circulator cc = f->outer_ccb(); - do - { + do { if (this->antenna(cc)) continue; const X_monotone_curve_2& curve = cc->curve(); @@ -702,31 +677,29 @@ void ArrangementGraphicsItem::paintFace( painter->setBrush(color); painter->drawPolygon(pgn); } - else - { + else { QRectF rect = this->viewportRect(); QColor color = f->color(); painter->fillRect(rect, color); } } +// template template -void ArrangementGraphicsItem::paintFace( - Face_handle f, QPainter* painter, - const CGAL::Arr_linear_traits_2& /* traits */) +void ArrangementGraphicsItem:: +paintFace(Face_handle f, QPainter* painter, + const CGAL::Arr_linear_traits_2& /* traits */) { QVector pts; // holds the points of the polygon QColor color = f->color(); painter->setBrush(color); - if (!f->is_unbounded()) - { + if (!f->is_unbounded()) { /* running with around the outer of the face and generate from it * polygon */ Ccb_halfedge_circulator cc = f->outer_ccb(); - do - { + do { Halfedge_handle hh = cc; if (this->antenna(hh)) continue; @@ -738,12 +711,10 @@ void ArrangementGraphicsItem::paintFace( painter->drawPolygon(QPolygonF{pts}); } - else - { + else { std::vector halfedges; Ccb_halfedge_circulator cc = f->outer_ccb(); - do - { + do { Halfedge_handle hh = cc; if (cc->is_fictitious() || this->antenna(hh)) continue; @@ -753,8 +724,7 @@ void ArrangementGraphicsItem::paintFace( QRectF rect = this->viewportRect(); - switch (halfedges.size()) - { + switch (halfedges.size()) { // one unbounded face case 0: { painter->fillRect(rect, color); @@ -766,39 +736,33 @@ void ArrangementGraphicsItem::paintFace( auto&& line = curve.line(); // horizontal or mostly horizontal - if (CGAL::abs(line.b()) > CGAL::abs(line.a())) - { + if (CGAL::abs(line.b()) > CGAL::abs(line.a())) { qreal left_y = CGAL::to_double(line.y_at_x(rect.left())); qreal right_y = CGAL::to_double(line.y_at_x(rect.right())); pts.push_back({rect.left(), left_y}); pts.push_back({rect.right(), right_y}); - if (cc->direction() == ARR_LEFT_TO_RIGHT) - { + if (cc->direction() == ARR_LEFT_TO_RIGHT) { pts.push_back(rect.bottomRight()); pts.push_back(rect.bottomLeft()); } - else - { + else { pts.push_back(rect.topRight()); pts.push_back(rect.topLeft()); } } // vertical or mostly vertical - else - { + else { qreal top_x = CGAL::to_double(line.x_at_y(rect.top())); qreal bottom_x = CGAL::to_double(line.x_at_y(rect.bottom())); pts.push_back({top_x, rect.top()}); pts.push_back({bottom_x, rect.bottom()}); - if (cc->direction() == ARR_LEFT_TO_RIGHT) - { + if (cc->direction() == ARR_LEFT_TO_RIGHT) { pts.push_back(rect.bottomLeft()); pts.push_back(rect.topLeft()); } - else - { + else { pts.push_back(rect.bottomRight()); pts.push_back(rect.topRight()); } @@ -806,121 +770,111 @@ void ArrangementGraphicsItem::paintFace( painter->drawPolygon(QPolygonF{pts}); break; - } - // general case - default: { - using Vertex_handle = typename Arrangement::Vertex_handle; + } + // general case + default: { + using Vertex_handle = typename Arrangement::Vertex_handle; - auto handle_vertex = [&](Halfedge_handle halfedge, Vertex_handle vertex) - { - // dx * y = dy * x + c - typename Kernel_::RT dx, dy, c; + auto handle_vertex = [&](Halfedge_handle halfedge, Vertex_handle vertex) + { + // dx * y = dy * x + c + typename Kernel_::RT dx, dy, c; - auto&& curve = halfedge->curve(); - if (curve.is_segment()) - { - auto&& src = halfedge->source()->point(); - auto&& tgt = halfedge->target()->point(); - dy = tgt.y() - src.y(); - dx = tgt.x() - src.x(); - c = dx * src.y() - dy * src.x(); - } - else if(curve.is_ray()) - { - auto&& ray = curve.ray(); - auto&& dir = ray.direction(); - auto&& src = ray.source(); - dy = dir.dy(); - dx = dir.dx(); - c = dx * src.y() - dy * src.x(); - } - // halfedge can be a line in case of a face between two parallel lines - else - { - auto&& line = curve.line(); - auto param_in_x = vertex->parameter_space_in_x(); - auto param_in_y = vertex->parameter_space_in_y(); - dy = line.a(); - dx = -line.b(); - c = line.c(); + auto&& curve = halfedge->curve(); + if (curve.is_segment()) { + auto&& src = halfedge->source()->point(); + auto&& tgt = halfedge->target()->point(); + dy = tgt.y() - src.y(); + dx = tgt.x() - src.x(); + c = dx * src.y() - dy * src.x(); + } + else if(curve.is_ray()) { + auto&& ray = curve.ray(); + auto&& dir = ray.direction(); + auto&& src = ray.source(); + dy = dir.dy(); + dx = dir.dx(); + c = dx * src.y() - dy * src.x(); + } + // halfedge can be a line in case of a face between two parallel lines + else { + auto&& line = curve.line(); + auto param_in_x = vertex->parameter_space_in_x(); + auto param_in_y = vertex->parameter_space_in_y(); + dy = line.a(); + dx = -line.b(); + c = line.c(); - if ( - (param_in_x == LEFT_BOUNDARY && CGAL::is_positive(dx)) || - (param_in_x == RIGHT_BOUNDARY && CGAL::is_negative(dx)) || - (param_in_y == BOTTOM_BOUNDARY && CGAL::is_positive(dy)) || - (param_in_y == TOP_BOUNDARY && CGAL::is_negative(dy))) - { - dx = -dx; - dy = -dy; - c = -c; - } - } - // horizontal or mostly horizontal - if (CGAL::abs(dx) > CGAL::abs(dy)) - { - qreal x = CGAL::is_positive(dx) ? rect.right() + rect.width() - : rect.left() - rect.width(); - // in case vertex is a finite point - if (!vertex->is_at_open_boundary()) - { - auto p = vertex->point(); - // check not far away - if ( - (CGAL::is_positive(dx) && p.x() < x) || - (CGAL::is_negative(dx) && p.x() > x)) - { - pts.push_back({CGAL::to_double(p.x()), CGAL::to_double(p.y())}); - return; - } - } - // in case vertex is far away (finite or at infinity), get a nearer - // point on the line - // i.e. in case farther than twice the width of the viewport - qreal y = CGAL::to_double((dy / dx) * x + (c / dx)); - pts.push_back({x, y}); - } - // vertical or mostly vertical - else - { - qreal y = CGAL::is_positive(dy) ? rect.bottom() + rect.height() - : rect.top() - rect.height(); - // in case vertex is a finite point - if (!vertex->is_at_open_boundary()) - { - auto p = vertex->point(); - // check not far away - if ( - (CGAL::is_positive(dy) && p.y() < y) || - (CGAL::is_negative(dy) && p.y() > y)) - { - pts.push_back({CGAL::to_double(p.x()), CGAL::to_double(p.y())}); - return; - } - } - // in case vertex is far away (finite or at infinity), get a nearer - // point on the line - // i.e. in case farther than twice the height of the viewport - qreal x = CGAL::to_double((dx / dy) * y - (c / dy)); - pts.push_back({x, y}); - } - }; + if ((param_in_x == LEFT_BOUNDARY && CGAL::is_positive(dx)) || + (param_in_x == RIGHT_BOUNDARY && CGAL::is_negative(dx)) || + (param_in_y == BOTTOM_BOUNDARY && CGAL::is_positive(dy)) || + (param_in_y == TOP_BOUNDARY && CGAL::is_negative(dy))) + { + dx = -dx; + dy = -dy; + c = -c; + } + } + // horizontal or mostly horizontal + if (CGAL::abs(dx) > CGAL::abs(dy)) { + qreal x = CGAL::is_positive(dx) ? + rect.right() + rect.width() : rect.left() - rect.width(); + // in case vertex is a finite point + if (!vertex->is_at_open_boundary()) { + auto p = vertex->point(); + // check not far away + if ((CGAL::is_positive(dx) && p.x() < x) || + (CGAL::is_negative(dx) && p.x() > x)) + { + pts.push_back({CGAL::to_double(p.x()), CGAL::to_double(p.y())}); + return; + } + } + // in case vertex is far away (finite or at infinity), get a nearer + // point on the line + // i.e. in case farther than twice the width of the viewport + qreal y = CGAL::to_double((dy / dx) * x + (c / dx)); + pts.push_back({x, y}); + } + // vertical or mostly vertical + else { + qreal y = CGAL::is_positive(dy) ? + rect.bottom() + rect.height() : rect.top() - rect.height(); + // in case vertex is a finite point + if (!vertex->is_at_open_boundary()) { + auto p = vertex->point(); + // check not far away + if ((CGAL::is_positive(dy) && p.y() < y) || + (CGAL::is_negative(dy) && p.y() > y)) + { + pts.push_back({CGAL::to_double(p.x()), CGAL::to_double(p.y())}); + return; + } + } + // in case vertex is far away (finite or at infinity), get a nearer + // point on the line + // i.e. in case farther than twice the height of the viewport + qreal x = CGAL::to_double((dx / dy) * y - (c / dy)); + pts.push_back({x, y}); + } + }; - for (auto hh : halfedges) - { - handle_vertex(hh, hh->source()); - handle_vertex(hh, hh->target()); - } + for (auto hh : halfedges) { + handle_vertex(hh, hh->source()); + handle_vertex(hh, hh->target()); + } - painter->drawPolygon(QPolygonF{pts}); - break; - } + painter->drawPolygon(QPolygonF{pts}); + break; + } } } } // TODO: clean all this portion up (move it somewhere?), it's ugly! -static CGAL::Bbox_2 reject_not_in_allowable_range( - const CGAL::Bbox_2& box, const CGAL::Bbox_2& allowable_range) +static CGAL::Bbox_2 +reject_not_in_allowable_range(const CGAL::Bbox_2& box, + const CGAL::Bbox_2& allowable_range) { double xmin = std::numeric_limits::infinity(); double ymin = std::numeric_limits::infinity(); @@ -934,25 +888,23 @@ static CGAL::Bbox_2 reject_not_in_allowable_range( return {xmin, ymin, xmax, ymax}; } -static bool isFinite(const CGAL::Bbox_2& box) -{ - return !std::isinf(box.xmin()) && !std::isinf(box.xmax()) && - !std::isinf(box.ymin()) && !std::isinf(box.ymax()); +// +static bool isFinite(const CGAL::Bbox_2& box) { + return ! std::isinf(box.xmin()) && !std::isinf(box.xmax()) && + ! std::isinf(box.ymin()) && !std::isinf(box.ymax()); } -static CGAL::Bbox_2 addMargins(const CGAL::Bbox_2& box) -{ +// +static CGAL::Bbox_2 addMargins(const CGAL::Bbox_2& box) { // add margin to bounding box double x_margin; double y_margin; - if (box.xmin() == box.xmax() || box.ymin() == box.ymax()) - { + if (box.xmin() == box.xmax() || box.ymin() == box.ymax()) { static constexpr float const_margin = 50; x_margin = const_margin; y_margin = const_margin; } - else - { + else { static constexpr double prop_margin = 0.10; x_margin = (box.xmax() - box.xmin()) * prop_margin; y_margin = (box.ymax() - box.ymin()) * prop_margin; @@ -962,25 +914,23 @@ static CGAL::Bbox_2 addMargins(const CGAL::Bbox_2& box) box.ymax() + y_margin}; } +// template CGAL::Bbox_2 -findOtherInterestingPoints(const Arr_*, const CGAL::Bbox_2&) -{ - return {}; -} +findOtherInterestingPoints(const Arr_*, const CGAL::Bbox_2&) { return {}; } #ifdef CGAL_USE_CORE + +// template static const auto& -getXyCurves(const CGAL::Arr_algebraic_segment_traits_2* traits) -{ +getXyCurves(const CGAL::Arr_algebraic_segment_traits_2* traits) { // the traits object is only needed the first time // this assumes that X_monotone_curves created from the first traits object // will work with arrangements with a different object using Traits = CGAL::Arr_algebraic_segment_traits_2; static std::vector xy_curves; - if (xy_curves.empty()) - { + if (xy_curves.empty()) { typedef typename Traits::Polynomial_2 Polynomial_2; auto construct_curve = traits->construct_curve_2_object(); auto make_x_monotone = traits->make_x_monotone_2_object(); @@ -1003,27 +953,25 @@ getXyCurves(const CGAL::Arr_algebraic_segment_traits_2* traits) return xy_curves; } +// template <> -CGAL::Bbox_2 findOtherInterestingPoints( - const demo_types::DemoTypes::Alg_seg_arr* arr, - const CGAL::Bbox_2& allowable_range) -{ +CGAL::Bbox_2 +findOtherInterestingPoints +(const demo_types::DemoTypes::Alg_seg_arr* arr, + const CGAL::Bbox_2& allowable_range) { using Traits = demo_types::DemoTypes::Alg_seg_traits; CGAL::Bbox_2 bb = {}; std::vector intersections; - for (auto it = arr->edges_begin(); it != arr->edges_end(); ++it) - { + for (auto it = arr->edges_begin(); it != arr->edges_end(); ++it) { for (auto& arc : getXyCurves(arr->traits())) if (arc.is_vertical() != it->curve().is_vertical()) it->curve().intersections(arc, std::back_inserter(intersections)); } - for (auto it = intersections.begin(); it != intersections.end(); it++) - { + for (auto it = intersections.begin(); it != intersections.end(); it++) { std::pair point_multiplicity; CGAL::assign(point_multiplicity, *it); auto& point = point_multiplicity.first; - if (point.location() == CGAL::ARR_INTERIOR) - { + if (point.location() == CGAL::ARR_INTERIOR) { auto xy = point.to_double(); bb += reject_not_in_allowable_range( {xy.first, xy.second, xy.first, xy.second}, allowable_range); @@ -1031,30 +979,28 @@ CGAL::Bbox_2 findOtherInterestingPoints( } return bb; } + #endif // CGAL_USE_CORE - +// template -QRectF ArrangementGraphicsItem::getInterestingViewport() const -{ +QRectF ArrangementGraphicsItem::getInterestingViewport() const { QRectF scene_rect = this->getScene()->sceneRect(); CGAL::Bbox_2 scene_bbox = { scene_rect.left(), scene_rect.top(), scene_rect.right(), scene_rect.bottom()}; - ConstructBoundingBox construct_bounding_box; + ConstructBoundingBox ctr_bbox(*(this->arr->geometry_traits())); CGAL::Bbox_2 bounding_box = {}; - for (auto it = this->arr->edges_begin(); - it != this->arr->edges_end(); ++it) - { + for (auto it = this->arr->edges_begin(); it != this->arr->edges_end(); ++it) { bounding_box += reject_not_in_allowable_range( - construct_bounding_box(it->curve()), scene_bbox); + ctr_bbox(it->curve()), scene_bbox); } for (auto it = this->arr->vertices_begin(); it != this->arr->vertices_end(); ++it) { bounding_box += reject_not_in_allowable_range( - construct_bounding_box(it->point()), scene_bbox); + ctr_bbox(it->point()), scene_bbox); } if (!isFinite(bounding_box)) @@ -1066,10 +1012,9 @@ QRectF ArrangementGraphicsItem::getInterestingViewport() const bounding_box = addMargins(bounding_box); - return QRectF( - bounding_box.xmin(), bounding_box.ymin(), - bounding_box.xmax() - bounding_box.xmin(), - bounding_box.ymax() - bounding_box.ymin()); + return QRectF(bounding_box.xmin(), bounding_box.ymin(), + bounding_box.xmax() - bounding_box.xmin(), + bounding_box.ymax() - bounding_box.ymin()); } } // namespace QT diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementTypesUtils.h b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementTypesUtils.h index af97be31ca0..dfe56a74c6f 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementTypesUtils.h +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementTypesUtils.h @@ -100,11 +100,9 @@ static constexpr TraitsType enumFromArrType() return details::EnumFromTraits::value; } -template -static void visitArrangementType(TraitsType tt, Lambda&& lambda) -{ - switch (tt) - { +template +static void visitArrangementType(TraitsType tt, Lambda&& lambda) { + switch (tt) { case TraitsType::SEGMENT_TRAITS: lambda(TypeHolder{}); break; diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/CurveGraphicsItem.cpp b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/CurveGraphicsItem.cpp index 863f7945cbd..ad8f7f7b7e9 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/CurveGraphicsItem.cpp +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/CurveGraphicsItem.cpp @@ -18,25 +18,29 @@ #include -namespace CGAL -{ -namespace Qt -{ +namespace CGAL { +namespace Qt { -template -CurveGraphicsItem::CurveGraphicsItem() : - bb(), m_edgeColor(::Qt::red), m_edgeWidth(2), - m_vertexColor(::Qt::red), m_vertexRadius(1) +// +template +CurveGraphicsItem::CurveGraphicsItem(const Traits& traits) : + m_traits(traits), + bb(), + m_edgeColor(::Qt::red), + m_edgeWidth(2), + m_vertexColor(::Qt::red), + m_vertexRadius(1) { this->setZValue(4); this->pointsGraphicsItem.setParentItem(this); } -template -void CurveGraphicsItem::paint( - QPainter* painter, const QStyleOptionGraphicsItem* /* option */, - QWidget* /* widget */) -{ +// +template +void CurveGraphicsItem:: +paint(QPainter* painter, + const QStyleOptionGraphicsItem* /* option */, + QWidget* /* widget */) { // draw the curves QPen edgesPen(this->m_edgeColor, this->m_edgeWidth); edgesPen.setCosmetic(true); @@ -48,9 +52,9 @@ void CurveGraphicsItem::paint( for (auto& curve : this->curves) { painterOstream << curve; } } -template -QRectF CurveGraphicsItem::boundingRect() const -{ +// +template +QRectF CurveGraphicsItem::boundingRect() const { auto viewport = this->viewportRect(); qreal xmin = viewport.left(); qreal ymin = viewport.top(); @@ -60,8 +64,7 @@ QRectF CurveGraphicsItem::boundingRect() const if (this->bb.ymin() > ymin) ymin = this->bb.ymin(); if (this->bb.xmax() < xmax) xmax = this->bb.xmax(); if (this->bb.ymax() < ymax) ymax = this->bb.ymax(); - if (xmin > xmax || ymin > ymax) - { + if (xmin > xmax || ymin > ymax) { xmin = 0; xmax = 0; ymin = 0; @@ -70,93 +73,92 @@ QRectF CurveGraphicsItem::boundingRect() const return {QPointF{xmin, ymin}, QPointF{xmax, ymax}}; } -template -void CurveGraphicsItem::insert(const X_monotone_curve_2& curve) -{ +// +template +void CurveGraphicsItem::insert(const X_monotone_curve_2& curve) { this->curves.push_back(curve); this->updateBoundingBox(); } -template -void CurveGraphicsItem::insert(const Point_2& point) -{ +// +template +void CurveGraphicsItem::insert(const Point_2& point) { this->pointsGraphicsItem.insert(point); this->updateBoundingBox(); } -template -void CurveGraphicsItem::clear() -{ +// +template +void CurveGraphicsItem::clear() { this->curves.clear(); this->pointsGraphicsItem.clear(); this->updateBoundingBox(); } -template -void CurveGraphicsItem::modelChanged() -{ +// +template +void CurveGraphicsItem::modelChanged() { this->updateBoundingBox(); this->update(); } -template -const QColor& CurveGraphicsItem::edgeColor() const -{ +// +template +const QColor& CurveGraphicsItem::edgeColor() const { return this->m_edgeColor; } -template -void CurveGraphicsItem::setEdgeColor(const QColor& color) -{ +// +template +void CurveGraphicsItem::setEdgeColor(const QColor& color) { this->m_edgeColor = color; } -template -int CurveGraphicsItem::edgeWidth() const -{ +// +template +int CurveGraphicsItem::edgeWidth() const { return this->m_edgeWidth; } -template -void CurveGraphicsItem::setEdgeWidth(int width) -{ +// +template +void CurveGraphicsItem::setEdgeWidth(int width) { this->m_edgeWidth = width; } -template -const QColor& CurveGraphicsItem::vertexColor() const -{ +// +template +const QColor& CurveGraphicsItem::vertexColor() const { return this->m_vertexColor; } -template -void CurveGraphicsItem::setVertexColor(const QColor& color) -{ +// +template +void CurveGraphicsItem::setVertexColor(const QColor& color) { this->m_vertexColor = color; } -template -int CurveGraphicsItem::vertexRadius() const -{ +// +template +int CurveGraphicsItem::vertexRadius() const { return this->m_vertexRadius; } -template -void CurveGraphicsItem::setVertexRadius(int radius) -{ +// +template +void CurveGraphicsItem::setVertexRadius(int radius) { this->m_vertexRadius = radius; } -template -void CurveGraphicsItem::updateBoundingBox() -{ +// +template +void CurveGraphicsItem::updateBoundingBox() { this->prepareGeometryChange(); this->bb = {}; - ConstructBoundingBox construct_bounding_box; - for (auto& curve : curves) - this->bb += construct_bounding_box(curve); + ConstructBoundingBox ctr_bbox(m_traits); + for (auto& curve : curves) this->bb += ctr_bbox(curve); } ARRANGEMENT_DEMO_SPECIALIZE_TRAITS(CurveGraphicsItem) diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/CurveGraphicsItem.h b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/CurveGraphicsItem.h index ce0fd6414f7..2478a567dac 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/CurveGraphicsItem.h +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/CurveGraphicsItem.h @@ -23,48 +23,47 @@ namespace CGAL { namespace Qt { -/** - Draws selected curves and vertices of an arrangement. -*/ +/* Draws selected curves and vertices of an arrangement. + */ // TODO: ArrangementGraphicsItem should probably use this class -template < class ArrTraits > -class CurveGraphicsItem : public GraphicsItem, public GraphicsSceneMixin -{ +template +class CurveGraphicsItem : public GraphicsItem, public GraphicsSceneMixin { public: // known curve types - typedef ArrTraits Traits; - typedef typename Traits::Curve_2 Curve_2; - typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; - typedef typename Traits::Point_2 Point_2; + typedef GeometryTraits Traits; + typedef typename Traits::Curve_2 Curve_2; + typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; + typedef typename Traits::Point_2 Point_2; -public: // ctors - CurveGraphicsItem( ); +public: + // Construct from traits. + CurveGraphicsItem(const Traits& traits); public: // methods - void paint( - QPainter* painter, const QStyleOptionGraphicsItem* /* option */, - QWidget* /* widget */) override; - QRectF boundingRect( ) const override; - void insert( const X_monotone_curve_2& curve ); - void insert( const Point_2& point ); - void clear( ); + void paint(QPainter* painter, const QStyleOptionGraphicsItem* /* option */, + QWidget* /* widget */) override; + QRectF boundingRect() const override; + void insert(const X_monotone_curve_2& curve); + void insert(const Point_2& point); + void clear(); public Q_SLOTS: - void modelChanged( ) override; - const QColor& edgeColor( ) const; - void setEdgeColor( const QColor& color ); - int edgeWidth( ) const; - void setEdgeWidth( int width ); - const QColor& vertexColor( ) const; - void setVertexColor( const QColor& color ); - int vertexRadius( ) const; - void setVertexRadius( int radius ); + void modelChanged() override; + const QColor& edgeColor() const; + void setEdgeColor(const QColor& color); + int edgeWidth() const; + void setEdgeWidth(int width); + const QColor& vertexColor() const; + void setVertexColor(const QColor& color); + int vertexRadius() const; + void setVertexRadius(int radius); protected: // methods void updateBoundingBox( ); protected: // fields - std::vector< X_monotone_curve_2 > curves; + const Traits& m_traits; + std::vector curves; PointsGraphicsItem pointsGraphicsItem; CGAL::Bbox_2 bb; diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/DeleteCurveCallback.cpp b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/DeleteCurveCallback.cpp index d30c5493d14..4e548644e3e 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/DeleteCurveCallback.cpp +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/DeleteCurveCallback.cpp @@ -20,8 +20,7 @@ #include "Utils/Utils.h" template -class DeleteCurveCallback : public DeleteCurveCallbackBase -{ +class DeleteCurveCallback : public DeleteCurveCallbackBase { public: typedef Arr_ Arrangement; typedef typename Arrangement::Halfedge_handle Halfedge_handle; @@ -62,11 +61,12 @@ struct ExplicitLambda CGAL::Object& arr_obj; QObject* parent; }; + } // anonymous namespace +// DeleteCurveCallbackBase* DeleteCurveCallbackBase::create( - demo_types::TraitsType tt, CGAL::Object arr_obj, QObject* parent) -{ + demo_types::TraitsType tt, CGAL::Object arr_obj, QObject* parent) { DeleteCurveCallbackBase* res; ExplicitLambda explicit_lambda{res, arr_obj, parent}; demo_types::visitArrangementType(tt, explicit_lambda); @@ -75,13 +75,14 @@ DeleteCurveCallbackBase* DeleteCurveCallbackBase::create( /*! Constructor */ template -DeleteCurveCallback::DeleteCurveCallback( - Arrangement* arr_, QObject* parent_) : - DeleteCurveCallbackBase(parent_), - highlightedCurve(new CGAL::Qt::CurveGraphicsItem()), arr(arr_) +DeleteCurveCallback::DeleteCurveCallback(Arrangement* arr_, + QObject* parent_) : + DeleteCurveCallbackBase(parent_), + highlightedCurve(new CGAL::Qt::CurveGraphicsItem(*(arr_->geometry_traits()))), + arr(arr_) { - QObject::connect( - this, SIGNAL(modelChanged()), this->highlightedCurve, SLOT(modelChanged())); + QObject::connect(this, SIGNAL(modelChanged()), + this->highlightedCurve, SLOT(modelChanged())); this->setDeleteMode(DeleteMode::DeleteOriginatingCuve); } @@ -91,13 +92,13 @@ DeleteCurveCallback::DeleteCurveCallback( sets the current scene of the viewport */ template -void DeleteCurveCallback::setScene(QGraphicsScene* scene_) -{ +void DeleteCurveCallback::setScene(QGraphicsScene* scene_) { CGAL::Qt::Callback::setScene(scene_); this->highlightedCurve->setScene(scene_); if (this->scene) { this->scene->addItem(this->highlightedCurve); } } +// template void DeleteCurveCallback::reset() { @@ -105,28 +106,25 @@ void DeleteCurveCallback::reset() this->removableHalfedge = Halfedge_handle(); } +// template -void DeleteCurveCallback::mousePressEvent( - QGraphicsSceneMouseEvent* /* event */) -{ +void DeleteCurveCallback:: +mousePressEvent(QGraphicsSceneMouseEvent* /* event */) { if (this->removableHalfedge == Halfedge_handle()) { return; } - if (this->deleteMode == DeleteMode::DeleteOriginatingCuve) - { + if (this->deleteMode == DeleteMode::DeleteOriginatingCuve) { Originating_curve_iterator it = this->arr->originating_curves_begin(this->removableHalfedge); Originating_curve_iterator it_end = this->arr->originating_curves_end(this->removableHalfedge); - while (it != it_end) - { + while (it != it_end) { Originating_curve_iterator temp = it; ++temp; CGAL::remove_curve(*(this->arr), it); it = temp; } } - else - { + else { // CGAL::remove_edge( *(this->arr), this->removableHalfedge->curve( ) ); this->arr->remove_edge(this->removableHalfedge); } @@ -134,16 +132,15 @@ void DeleteCurveCallback::mousePressEvent( Q_EMIT modelChanged(); } +// template void DeleteCurveCallback::mouseMoveEvent(QGraphicsSceneMouseEvent* event) -{ - this->highlightNearestCurve(event); -} +{ this->highlightNearestCurve(event); } +// template -void DeleteCurveCallback::highlightNearestCurve( - QGraphicsSceneMouseEvent* event) -{ +void DeleteCurveCallback:: +highlightNearestCurve(QGraphicsSceneMouseEvent* event) { typedef typename ArrTraitsAdaptor::Kernel Kernel; typedef typename Kernel::Point_2 Point; @@ -164,12 +161,11 @@ void DeleteCurveCallback::highlightNearestCurve( // create a curve graphics item and add it to the scene this->highlightedCurve->clear(); - if (this->deleteMode == DeleteMode::DeleteOriginatingCuve) - { // highlight the originating curve + if (this->deleteMode == DeleteMode::DeleteOriginatingCuve) { + // highlight the originating curve Originating_curve_iterator ocit, temp; ocit = this->arr->originating_curves_begin(this->removableHalfedge); - while (ocit != this->arr->originating_curves_end(this->removableHalfedge)) - { + while (ocit != this->arr->originating_curves_end(this->removableHalfedge)) { temp = ocit; ++temp; @@ -184,8 +180,8 @@ void DeleteCurveCallback::highlightNearestCurve( ocit = temp; } } - else - { // highlight just the edge + else { + // highlight just the edge this->highlightedCurve->insert(this->removableHalfedge->curve()); } diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/EnvelopeCallback.cpp b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/EnvelopeCallback.cpp index 71bb0f1d3c9..4e3cf4cd47a 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/EnvelopeCallback.cpp +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/EnvelopeCallback.cpp @@ -84,10 +84,13 @@ struct ExplicitLambda CGAL::Object& arr_obj; QObject* parent; }; + } // anonymous namespace -EnvelopeCallbackBase* EnvelopeCallbackBase::create( - demo_types::TraitsType tt, CGAL::Object arr_obj, QObject* parent) +// +EnvelopeCallbackBase* +EnvelopeCallbackBase::create(demo_types::TraitsType tt, CGAL::Object arr_obj, + QObject* parent) { EnvelopeCallbackBase* res; ExplicitLambda explicit_lambda{res, arr_obj, parent}; @@ -95,11 +98,12 @@ EnvelopeCallbackBase* EnvelopeCallbackBase::create( return res; } +// template EnvelopeCallback::EnvelopeCallback(Arrangement* arr_, QObject* parent) : EnvelopeCallbackBase(parent), arr(arr_), - lowerEnvelope(new CGAL::Qt::CurveGraphicsItem()), - upperEnvelope(new CGAL::Qt::CurveGraphicsItem()), showLower(false), + lowerEnvelope(new CGAL::Qt::CurveGraphicsItem(*(arr_->geometry_traits()))), + upperEnvelope(new CGAL::Qt::CurveGraphicsItem(*(arr_->geometry_traits()))), showLower(false), showUpper(false) { this->lowerEnvelope->hide(); @@ -107,7 +111,7 @@ EnvelopeCallback::EnvelopeCallback(Arrangement* arr_, QObject* parent) : } template < typename Arr_ > -void EnvelopeCallback::setEnvelopeEdgeColor( const QColor& color ) +void EnvelopeCallback::setEnvelopeEdgeColor(const QColor& color) { this->lowerEnvelope->setEdgeColor( color ); this->upperEnvelope->setEdgeColor( color ); diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/MergeEdgeCallback.cpp b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/MergeEdgeCallback.cpp index 6f1a5d14880..0729852bcbe 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/MergeEdgeCallback.cpp +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/MergeEdgeCallback.cpp @@ -51,10 +51,11 @@ protected: // msvc2015 doesn't play well with polymorphic lambdas namespace { + struct ExplicitLambda { template void operator()(demo_types::TypeHolder) { - Arrangement* arr = nullptr; + Arrangement* arr(nullptr); CGAL::assign(arr, arr_obj); res = new MergeEdgeCallback(arr, parent); } @@ -63,6 +64,7 @@ struct ExplicitLambda { CGAL::Object& arr_obj; QObject* parent; }; + } // anonymous namespace // @@ -80,8 +82,8 @@ template MergeEdgeCallback::MergeEdgeCallback(Arrangement* arr_, QObject* parent_) : MergeEdgeCallbackBase(parent_), - highlightedCurve(new CGAL::Qt::CurveGraphicsItem()), - highlightedCurve2(new CGAL::Qt::CurveGraphicsItem()), arr(arr_), + highlightedCurve(new CGAL::Qt::CurveGraphicsItem(*(arr_->geometry_traits()))), + highlightedCurve2(new CGAL::Qt::CurveGraphicsItem(*(arr_->geometry_traits()))), arr(arr_), isFirst(true) { QObject::connect(this, SIGNAL(modelChanged()), this->highlightedCurve, @@ -115,8 +117,8 @@ void MergeEdgeCallback::reset() { // template void MergeEdgeCallback::mousePressEvent(QGraphicsSceneMouseEvent* event) { - if (this->isFirst) - { // save the first edge if mergeable + if (this->isFirst) { + // save the first edge if mergeable Halfedge_handle halfedge = this->getNearestMergeableCurve(event); if (halfedge == Halfedge_handle()) return; this->isFirst = false; @@ -187,7 +189,7 @@ getNearestMergeableCurve(QGraphicsSceneMouseEvent* event) { squared_distance(*(arr->geometry_traits())); squared_distance.setScene(this->getScene()); double dist = CGAL::to_double(squared_distance(p, curve)); - if (!found || dist < min_dist) { + if (! found || dist < min_dist) { found = true; min_dist = dist; nearestHei = hei; @@ -218,9 +220,8 @@ getNearestMergeableCurve(Halfedge_handle h, QGraphicsSceneMouseEvent* event) { if (source->degree() != 2 && target->degree() != 2) return Halfedge_handle(); else if (source->degree() != 2) return h2; else if (target->degree() != 2) return h1; - else if ( - this->mergeEdge.areMergeable(arr, h, h1) && - this->mergeEdge.areMergeable(arr, h, h2)) + else if (this->mergeEdge.areMergeable(arr, h, h1) && + this->mergeEdge.areMergeable(arr, h, h2)) { X_monotone_curve_2 c1 = h1->curve(); X_monotone_curve_2 c2 = h2->curve(); diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/PointLocationCallback.cpp b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/PointLocationCallback.cpp index 6e2763f02fc..4baf3436435 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/PointLocationCallback.cpp +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/PointLocationCallback.cpp @@ -96,54 +96,55 @@ PointLocationCallbackBase* PointLocationCallbackBase::create( /*! Constructor */ template -PointLocationCallback::PointLocationCallback( - Arrangement* arr_, QObject* parent_) : - PointLocationCallbackBase(parent_), - arr(arr_), highlightedCurves(new CGAL::Qt::CurveGraphicsItem()) +PointLocationCallback::PointLocationCallback(Arrangement* arr_, + QObject* parent_) : + PointLocationCallbackBase(parent_), + arr(arr_), + highlightedCurves(new CGAL::Qt::CurveGraphicsItem(*(arr_->geometry_traits()))) { - QObject::connect( - this, SIGNAL(modelChanged()), this->highlightedCurves, - SLOT(modelChanged())); + QObject::connect(this, SIGNAL(modelChanged()), this->highlightedCurves, + SLOT(modelChanged())); } +// template -void PointLocationCallback::setScene(QGraphicsScene* scene_) -{ +void PointLocationCallback::setScene(QGraphicsScene* scene_) { this->scene = scene_; this->highlightedCurves->setScene(scene_); if (this->scene) { this->scene->addItem(this->highlightedCurves); } } +// template -void PointLocationCallback::reset() -{ +void PointLocationCallback::reset() { this->highlightedCurves->clear(); Q_EMIT modelChanged(); } +// template -void PointLocationCallback::mousePressEvent( - QGraphicsSceneMouseEvent* event) -{ +void PointLocationCallback:: +mousePressEvent(QGraphicsSceneMouseEvent* event) { this->highlightPointLocation(event); } +// template -void PointLocationCallback::mouseMoveEvent( - QGraphicsSceneMouseEvent* /* event */) -{ +void PointLocationCallback:: +mouseMoveEvent(QGraphicsSceneMouseEvent* /* event */) { } +// template -void PointLocationCallback::highlightPointLocation( - QGraphicsSceneMouseEvent* event) -{ +void PointLocationCallback:: +highlightPointLocation(QGraphicsSceneMouseEvent* event) { typename Traits::Left_side_category category; this->highlightPointLocation(event, category); Q_EMIT modelChanged(); } +// template void PointLocationCallback::highlightPointLocation( QGraphicsSceneMouseEvent* event, CGAL::Arr_oblivious_side_tag) @@ -152,22 +153,19 @@ void PointLocationCallback::highlightPointLocation( PointLocationFunctions{}.getFace(this->arr, event->scenePos()); this->highlightedCurves->clear(); - if (!face->is_unbounded()) - { // it is an interior face; highlight its border + if (!face->is_unbounded()) { // it is an interior face; highlight its border Ccb_halfedge_const_circulator cc = face->outer_ccb(); - do - { + do { X_monotone_curve_2 curve = cc->curve(); this->highlightedCurves->insert(curve); } while (++cc != face->outer_ccb()); } Hole_const_iterator hit; Hole_const_iterator eit = face->holes_end(); - for (hit = face->holes_begin(); hit != eit; ++hit) - { // highlight any holes inside this face + for (hit = face->holes_begin(); hit != eit; ++hit) { + // highlight any holes inside this face Ccb_halfedge_const_circulator cc = *hit; - do - { + do { X_monotone_curve_2 curve = cc->curve(); this->highlightedCurves->insert(curve); cc++; @@ -175,30 +173,28 @@ void PointLocationCallback::highlightPointLocation( } } +// template -void PointLocationCallback::highlightPointLocation( - QGraphicsSceneMouseEvent* event, CGAL::Arr_open_side_tag) +void PointLocationCallback:: +highlightPointLocation(QGraphicsSceneMouseEvent* event, CGAL::Arr_open_side_tag) { Face_const_handle face = PointLocationFunctions{}.getFace(this->arr, event->scenePos()); this->highlightedCurves->clear(); Ccb_halfedge_const_circulator cc = face->outer_ccb(); - do - { - if (!cc->is_fictitious()) - { + do { + if (!cc->is_fictitious()) { X_monotone_curve_2 curve = cc->curve(); this->highlightedCurves->insert(curve); } } while (++cc != face->outer_ccb()); Hole_const_iterator hit; Hole_const_iterator eit = face->holes_end(); - for (hit = face->holes_begin(); hit != eit; ++hit) - { // highlight any holes inside this face + for (hit = face->holes_begin(); hit != eit; ++hit) { + // highlight any holes inside this face Ccb_halfedge_const_circulator cc = *hit; - do - { + do { X_monotone_curve_2 curve = cc->curve(); this->highlightedCurves->insert(curve); cc++; diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/Utils/ConstructBoundingBox.cpp b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/Utils/ConstructBoundingBox.cpp index 9c1c8fbc83d..2d5422fa9ec 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/Utils/ConstructBoundingBox.cpp +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/Utils/ConstructBoundingBox.cpp @@ -16,6 +16,7 @@ #include #include +// static const CGAL::Bbox_2 inf_bbox = { -std::numeric_limits::infinity(), -std::numeric_limits::infinity(), @@ -24,25 +25,27 @@ static const CGAL::Bbox_2 inf_bbox = { static constexpr double inf_double = std::numeric_limits::infinity(); -template -struct ConstructBoundingBox_impl -{ - using Traits = Traits_; +// +template +class ConstructBoundingBox_impl { + using Traits = GeometryTraits; using X_monotone_curve_2 = typename Traits::X_monotone_curve_2; using Curve_2 = typename Traits::Curve_2; using Point_2 = typename Traits::Point_2; - CGAL::Bbox_2 - operator()(const X_monotone_curve_2& curve) - { +public: + // Construct from traits; + ConstructBoundingBox_impl(const Traits& traits) : m_traits(traits) {} + + // + CGAL::Bbox_2 operator()(const X_monotone_curve_2& curve) { #ifdef CGAL_USE_CORE using Zero_resultant_exception = CGAL::internal::Zero_resultant_exception< typename demo_types::DemoTypes::Alg_seg_traits::Polynomial_2>; #endif CGAL::Bbox_2 bbox; - try - { + try { bbox = curve.bbox(); } // algebraic traits sometimes crash when calling bbox @@ -70,13 +73,15 @@ struct ConstructBoundingBox_impl return bbox; } - CGAL::Bbox_2 - operator()(const Point_2& point) - { + // + CGAL::Bbox_2 operator()(const Point_2& point) { double x = CGAL::to_double(point.x()); double y = CGAL::to_double(point.y()); return {x, y, x, y}; } + +private: + const Traits& m_traits; }; // We currently avoid using bbox function in Arr_sgegment_2 because it creates @@ -84,21 +89,22 @@ struct ConstructBoundingBox_impl // TODO: remove this class and the polyline one once it's fixed // and use bbox directly template -struct ConstructBoundingBox_impl> -{ +class ConstructBoundingBox_impl> { using Traits = CGAL::Arr_segment_traits_2; using X_monotone_curve_2 = typename Traits::X_monotone_curve_2; using Curve_2 = typename Traits::Curve_2; using Point_2 = typename Traits::Point_2; - CGAL::Bbox_2 - operator()(const X_monotone_curve_2& curve) - { - return this->operator()(curve.source(), curve.target()); - } +public: + // Construct from traits; + ConstructBoundingBox_impl(const Traits& traits) : m_traits(traits) {} - CGAL::Bbox_2 operator()(const Point_2& p1, const Point_2& p2) - { + // + CGAL::Bbox_2 operator()(const X_monotone_curve_2& curve) + { return this->operator()(curve.source(), curve.target()); } + + // + CGAL::Bbox_2 operator()(const Point_2& p1, const Point_2& p2) { CGAL::Bbox_2 bbox; double x1 = CGAL::to_double(p1.x()); double y1 = CGAL::to_double(p1.y()); @@ -106,40 +112,39 @@ struct ConstructBoundingBox_impl> double y2 = CGAL::to_double(p2.y()); double min_x, max_x, min_y, max_y; - if (x1 < x2) - { + if (x1 < x2) { min_x = x1; max_x = x2; } - else - { + else { min_x = x2; max_x = x1; } - if (y1 < y2) - { + if (y1 < y2) { min_y = y1; max_y = y2; } - else - { + else { min_y = y2; max_y = y1; } return {min_x, min_y, max_x, max_y}; } - CGAL::Bbox_2 - operator()(const Point_2& point) - { + // + CGAL::Bbox_2 operator()(const Point_2& point) { double x = CGAL::to_double(point.x()); double y = CGAL::to_double(point.y()); return {x, y, x, y}; } + +private: + const Traits& m_traits; }; +// template -struct ConstructBoundingBox_impl> +class ConstructBoundingBox_impl> { using Traits = CGAL::Arr_polyline_traits_2; using SegmentTraits_2 = SegmentTraits_2_; @@ -147,21 +152,22 @@ struct ConstructBoundingBox_impl> using Curve_2 = typename Traits::Curve_2; using Point_2 = typename Traits::Point_2; - CGAL::Bbox_2 - operator()(const X_monotone_curve_2& curve) - { - ConstructBoundingBox_impl construct_bounding_box; +public: + // Construct from traits; + ConstructBoundingBox_impl(const Traits& traits) : m_traits(traits) {} + // + CGAL::Bbox_2 operator()(const X_monotone_curve_2& curve) { + const auto* sub_traits = m_traits.subcurve_traits_2(); + ConstructBoundingBox_impl ctr_bbox(*sub_traits); auto n = curve.number_of_subcurves(); CGAL::Bbox_2 bbox; - for (std::size_t i = 0; i < n; ++i) - bbox += construct_bounding_box(curve[i]); - + for (std::size_t i = 0; i < n; ++i) bbox += ctr_bbox(curve[i]); return bbox; } - CGAL::Bbox_2 operator()(const Point_2& p1, const Point_2& p2) - { + // + CGAL::Bbox_2 operator()(const Point_2& p1, const Point_2& p2) { CGAL::Bbox_2 bbox; double x1 = CGAL::to_double(p1.x()); double y1 = CGAL::to_double(p1.y()); @@ -169,61 +175,57 @@ struct ConstructBoundingBox_impl> double y2 = CGAL::to_double(p2.y()); double min_x, max_x, min_y, max_y; - if (x1 < x2) - { + if (x1 < x2) { min_x = x1; max_x = x2; } - else - { + else { min_x = x2; max_x = x1; } - if (y1 < y2) - { + if (y1 < y2) { min_y = y1; max_y = y2; } - else - { + else { min_y = y2; max_y = y1; } return {min_x, min_y, max_x, max_y}; } - CGAL::Bbox_2 - operator()(const Point_2& point) - { + // + CGAL::Bbox_2 operator()(const Point_2& point) { double x = CGAL::to_double(point.x()); double y = CGAL::to_double(point.y()); return {x, y, x, y}; } + +private: + const Traits& m_traits; }; +// template -struct ConstructBoundingBox_impl> -{ +class ConstructBoundingBox_impl> { using Traits = CGAL::Arr_linear_traits_2; using X_monotone_curve_2 = typename Traits::X_monotone_curve_2; using Curve_2 = typename Traits::Curve_2; using Point_2 = typename Traits::Point_2; - CGAL::Bbox_2 - operator()(const X_monotone_curve_2& curve) - { - if (curve.is_segment()) - { - return ConstructBoundingBox_impl>{}( - curve.source(), curve.target()); - } - else if (curve.is_line()) - { - return inf_bbox; +public: + // Construct from traits; + ConstructBoundingBox_impl(const Traits& traits) : m_traits(traits) {} + + // + CGAL::Bbox_2 operator()(const X_monotone_curve_2& curve) { + if (curve.is_segment()) { + auto&& seg = curve.segment(); + return operator()(seg.source()) + operator()(seg.target()); } + else if (curve.is_line()) return inf_bbox; // ray - else - { + else { auto&& ray = curve.ray(); auto&& src = ray.source(); double src_x = CGAL::to_double(src.x()); @@ -232,65 +234,101 @@ struct ConstructBoundingBox_impl> bool dx = CGAL::is_positive(dir.dx()); bool dy = CGAL::is_positive(dir.dy()); - if (dx && dy) - return {src_x, src_y, inf_double, inf_double}; - else if (!dx && dy) - return {-inf_double, src_y, src_x, inf_double}; - else if (!dx && !dy) - return {-inf_double, -inf_double, src_x, src_y}; + if (dx && dy) return {src_x, src_y, inf_double, inf_double}; + else if (!dx && dy) return {-inf_double, src_y, src_x, inf_double}; + else if (!dx && !dy) return {-inf_double, -inf_double, src_x, src_y}; else // if (dx && !dy) return {src_x, -inf_double, inf_double, src_y}; } } - CGAL::Bbox_2 operator()(const Point_2& point) - { + // + CGAL::Bbox_2 operator()(const Point_2& point) { double x = CGAL::to_double(point.x()); double y = CGAL::to_double(point.y()); return {x, y, x, y}; } + +private: + const Traits& m_traits; }; +// Specialization of `ConstructBoundingBox_impl` for the conic traits. +template +class ConstructBoundingBox_impl +> { + using Traits = CGAL::Arr_conic_traits_2; + using Point_2 = typename Traits::Point_2; + using X_monotone_curve_2 = typename Traits::X_monotone_curve_2; -template < - typename RatKernel_, typename AlgKernel_, typename NtTraits_, - typename BoundingTraits_> -struct ConstructBoundingBox_impl> +public: + // Construct from traits; + ConstructBoundingBox_impl(const Traits& traits) : m_traits(traits) {} + + // Obtain the bounding box for an x-monotone conic curve. + CGAL::Bbox_2 operator()(const X_monotone_curve_2& xcv) + { return m_traits.construct_bbox_2_object()(xcv); } + + // Obtain the bounding box for an conic point. + CGAL::Bbox_2 operator()(const Point_2& point) { + double x = CGAL::to_double(point.x()); + double y = CGAL::to_double(point.y()); + return {x, y, x, y}; + } + +private: + const Traits& m_traits; +}; + +// Specialization of `ConstructBoundingBox_impl` for the Bezier traits. +template +class ConstructBoundingBox_impl> { - using Traits = typename CGAL::Arr_Bezier_curve_traits_2< - RatKernel_, AlgKernel_, NtTraits_, BoundingTraits_>; + using Traits = typename CGAL::Arr_Bezier_curve_traits_2 + ; using X_monotone_curve_2 = typename Traits::X_monotone_curve_2; using Curve_2 = typename Traits::Curve_2; using Point_2 = typename Traits::Point_2; - CGAL::Bbox_2 - operator()(const X_monotone_curve_2& curve) - { +public: + // Construct from traits; + ConstructBoundingBox_impl(const Traits& traits) : m_traits(traits) {} + + // + CGAL::Bbox_2 operator()(const X_monotone_curve_2& curve) { // TODO: find a way to find the bounding box of a bezier X_monotone_curve return curve.supporting_curve().bbox(); } - CGAL::Bbox_2 - operator()(const Point_2& point) - { + // + CGAL::Bbox_2 operator()(const Point_2& point) { std::pair p = point.approximate(); return {p.first, p.second, p.first, p.second}; } + +private: + const Traits& m_traits; }; +// Specialization of `ConstructBoundingBox_impl` for the rational-function +// traits. template -struct ConstructBoundingBox_impl< - CGAL::Arr_rational_function_traits_2> -{ +class ConstructBoundingBox_impl> { using Traits = CGAL::Arr_rational_function_traits_2; using X_monotone_curve_2 = typename Traits::X_monotone_curve_2; using Curve_2 = typename Traits::Curve_2; using Point_2 = typename Traits::Point_2; - CGAL::Bbox_2 - operator()(const X_monotone_curve_2& curve) - { +public: + // Construct from traits; + ConstructBoundingBox_impl(const Traits& traits) : m_traits(traits) {} + + // + CGAL::Bbox_2 operator()(const X_monotone_curve_2& curve) { double min_x, max_x, min_y, max_y; if (curve.left_parameter_space_in_x() == CGAL::ARR_INTERIOR) min_x = CGAL::to_double(curve.left_x()); @@ -313,25 +351,26 @@ struct ConstructBoundingBox_impl< return {min_x, min_y, max_x, max_y}; } - CGAL::Bbox_2 - operator()(const Point_2& point) - { + // + CGAL::Bbox_2 operator()(const Point_2& point) { double x = CGAL::to_double(point.x()); double y = CGAL::to_double(point.y()); return {x, y, x, y}; } + +private: + const Traits& m_traits; }; +// template CGAL::Bbox_2 ConstructBoundingBox::operator()(const X_monotone_curve_2& curve) -{ - return ConstructBoundingBox_impl{}(curve); -} +{ return ConstructBoundingBox_impl(m_traits)(curve); } + +// template CGAL::Bbox_2 ConstructBoundingBox::operator()(const Point_2& point) -{ - return ConstructBoundingBox_impl{}(point); -} +{ return ConstructBoundingBox_impl(m_traits)(point); } ARRANGEMENT_DEMO_SPECIALIZE_TRAITS(ConstructBoundingBox) diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/Utils/ConstructBoundingBox.h b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/Utils/ConstructBoundingBox.h index 83b6e712f1b..ccd4511cac3 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/Utils/ConstructBoundingBox.h +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/Utils/ConstructBoundingBox.h @@ -17,15 +17,23 @@ // bounding box utility for arrangements // doesn't have to be exact, only good enough for rendering template -class ConstructBoundingBox -{ +class ConstructBoundingBox { public: using Traits = Traits_; using X_monotone_curve_2 = typename Traits::X_monotone_curve_2; using Point_2 = typename Traits::Point_2; + // Construct from traits. + ConstructBoundingBox(const Traits& traits) : m_traits(traits) {} + + // CGAL::Bbox_2 operator()(const X_monotone_curve_2& curve); + + // CGAL::Bbox_2 operator()(const Point_2& point); + +private: + const Traits& m_traits; }; #endif diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/VerticalRayShootCallback.cpp b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/VerticalRayShootCallback.cpp index 2738e18edce..69bfebf8495 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/VerticalRayShootCallback.cpp +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/VerticalRayShootCallback.cpp @@ -22,8 +22,7 @@ #include template -class VerticalRayShootCallback : public VerticalRayShootCallbackBase -{ +class VerticalRayShootCallback : public VerticalRayShootCallbackBase { public: typedef VerticalRayShootCallbackBase Superclass; typedef Arr_ Arrangement; @@ -57,13 +56,12 @@ VerticalRayShootCallbackBase::VerticalRayShootCallbackBase(QObject* parent_) : } // msvc2015 doesn't play well with polymorphic lambdas -namespace -{ -struct ExplicitLambda -{ +namespace { + + // +struct ExplicitLambda { template - void operator()(demo_types::TypeHolder) - { + void operator()(demo_types::TypeHolder) { Arrangement* arr = nullptr; CGAL::assign(arr, arr_obj); res = new VerticalRayShootCallback(arr, parent); @@ -73,28 +71,30 @@ struct ExplicitLambda CGAL::Object& arr_obj; QObject* parent; }; + } // anonymous namespace -VerticalRayShootCallbackBase* VerticalRayShootCallbackBase::create( - demo_types::TraitsType tt, CGAL::Object arr_obj, QObject* parent) -{ +// +VerticalRayShootCallbackBase* +VerticalRayShootCallbackBase::create(demo_types::TraitsType tt, + CGAL::Object arr_obj, QObject* parent) { VerticalRayShootCallbackBase* res; ExplicitLambda explicit_lambda{res, arr_obj, parent}; demo_types::visitArrangementType(tt, explicit_lambda); return res; } +// void VerticalRayShootCallbackBase::setShootingUp(bool isShootingUp) -{ - this->shootingUp = isShootingUp; -} +{ this->shootingUp = isShootingUp; } +// template -VerticalRayShootCallback::VerticalRayShootCallback( - Arrangement* arr_, QObject* parent_) : - VerticalRayShootCallbackBase(parent_), - arr(arr_), - highlightedCurves(new CGAL::Qt::CurveGraphicsItem()) +VerticalRayShootCallback:: +VerticalRayShootCallback(Arrangement* arr_, QObject* parent_) : + VerticalRayShootCallbackBase(parent_), + arr(arr_), + highlightedCurves(new CGAL::Qt::CurveGraphicsItem(*(arr->geometry_traits()))) { this->rayGraphicsItem.setZValue(100); @@ -102,81 +102,75 @@ VerticalRayShootCallback::VerticalRayShootCallback( this->highlightedCurves->setVertexColor(this->rayGraphicsItem.color()); this->highlightedCurves->setZValue(100); - QObject::connect( - this, SIGNAL(modelChanged()), this->highlightedCurves, - SLOT(modelChanged())); - QObject::connect( - this, SIGNAL(modelChanged()), this, SLOT(slotModelChanged())); + QObject::connect(this, SIGNAL(modelChanged()), this->highlightedCurves, + SLOT(modelChanged())); + QObject::connect(this, SIGNAL(modelChanged()), this, SLOT(slotModelChanged())); } +// template -void VerticalRayShootCallback::setEdgeWidth( int width ) -{ - this->highlightedCurves->setEdgeWidth( width ); - this->rayGraphicsItem.setWidth( width ); +void VerticalRayShootCallback::setEdgeWidth(int width) { + this->highlightedCurves->setEdgeWidth(width); + this->rayGraphicsItem.setWidth(width); } +// template -void VerticalRayShootCallback::setEdgeColor( const QColor& color ) -{ - this->highlightedCurves->setEdgeColor( color ); - this->rayGraphicsItem.setColor( color ); +void VerticalRayShootCallback::setEdgeColor(const QColor& color) { + this->highlightedCurves->setEdgeColor(color); + this->rayGraphicsItem.setColor(color); } +// template -const QColor& VerticalRayShootCallback::edgeColor( ) const -{ - return this->highlightedCurves->edgeColor( ); -} +const QColor& VerticalRayShootCallback::edgeColor() const +{ return this->highlightedCurves->edgeColor(); } +// template -int VerticalRayShootCallback::edgeWidth( ) const -{ - return this->highlightedCurves->edgeWidth( ); -} +int VerticalRayShootCallback::edgeWidth() const +{ return this->highlightedCurves->edgeWidth(); } +// template -void VerticalRayShootCallback::setScene(QGraphicsScene* scene_) -{ +void VerticalRayShootCallback::setScene(QGraphicsScene* scene_) { CGAL::Qt::Callback::setScene(scene_); this->highlightedCurves->setScene(scene_); - if (scene_) - { + if (scene_) { this->scene->addItem(this->highlightedCurves); this->scene->addItem(&this->rayGraphicsItem); } } +// template void VerticalRayShootCallback::slotModelChanged() { } +// template -void VerticalRayShootCallback::reset() -{ +void VerticalRayShootCallback::reset() { this->rayGraphicsItem.reset(); this->highlightedCurves->clear(); Q_EMIT modelChanged(); } +// template -void VerticalRayShootCallback::mousePressEvent( - QGraphicsSceneMouseEvent* event) -{ - this->highlightPointLocation(event); -} +void VerticalRayShootCallback:: +mousePressEvent(QGraphicsSceneMouseEvent* event) +{ this->highlightPointLocation(event); } +// template -void VerticalRayShootCallback::mouseMoveEvent( - QGraphicsSceneMouseEvent* /* event */) -{ -} +void VerticalRayShootCallback:: +mouseMoveEvent(QGraphicsSceneMouseEvent* /* event */) {} +// template -void VerticalRayShootCallback::highlightPointLocation( - QGraphicsSceneMouseEvent* event) -{ +void VerticalRayShootCallback:: +highlightPointLocation(QGraphicsSceneMouseEvent* event) { this->highlightedCurves->clear(); QPointF queryQPt = event->scenePos(); @@ -192,25 +186,21 @@ void VerticalRayShootCallback::highlightPointLocation( QRectF viewportRect = this->viewportRect(); qreal y2; - if (this->shootingUp) - { // +y in Qt is towards the bottom + if (this->shootingUp) { // +y in Qt is towards the bottom y2 = viewportRect.bottom(); } - else - { + else { y2 = viewportRect.top(); } Face_const_handle unboundedFace; Halfedge_const_handle halfedge; Vertex_const_handle vertex; - if (CGAL::assign(unboundedFace, pointLocationResult)) - { + if (CGAL::assign(unboundedFace, pointLocationResult)) { this->rayGraphicsItem.setSource(queryQPt); this->rayGraphicsItem.setTargetY(y2); this->rayGraphicsItem.setIsInfinite(true); } - else if (CGAL::assign(halfedge, pointLocationResult)) - { + else if (CGAL::assign(halfedge, pointLocationResult)) { this->highlightedCurves->insert(halfedge->curve()); // draw a ray from the clicked point to the hit curve @@ -221,10 +211,8 @@ void VerticalRayShootCallback::highlightPointLocation( this->rayGraphicsItem.setTargetY(yApprox); this->rayGraphicsItem.setIsInfinite(false); } - else if (CGAL::assign(vertex, pointLocationResult)) - { - if (!vertex->is_at_open_boundary()) - { + else if (CGAL::assign(vertex, pointLocationResult)) { + if (!vertex->is_at_open_boundary()) { auto pt = vertex->point(); this->highlightedCurves->insert(pt); } From 3485ce1a8a7aa6122d52073eab91cd6259f7de89 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Sun, 11 Sep 2022 12:11:53 +0300 Subject: [PATCH 081/105] Fixed trimming and avoided using deprecated code. --- .../ArrangementPainterOstream.cpp | 448 ++++++++---------- .../include/CGAL/Arr_conic_traits_2.h | 54 ++- .../Conic_x_monotone_arc_2.h | 48 +- 3 files changed, 247 insertions(+), 303 deletions(-) diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementPainterOstream.cpp b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementPainterOstream.cpp index 5ab229da8a8..814820208ff 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementPainterOstream.cpp +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementPainterOstream.cpp @@ -15,57 +15,48 @@ #include -namespace CGAL -{ -namespace Qt -{ +namespace CGAL { +namespace Qt { -// Instantiation of Arr_segment_traits_2 +// Specialization of `ArrangementPainterOstream` for the segment traits. template ArrangementPainterOstream>& -ArrangementPainterOstream>::operator<<( - const X_monotone_curve_2& curve) -{ +ArrangementPainterOstream>:: +operator<<(const X_monotone_curve_2& curve) { const Point_2& p1 = curve.source(); const Point_2& p2 = curve.target(); Segment_2 seg(p1, p2); // skip segments outside our view QRectF seg_bb = this->convert(seg.bbox()); - if ( - this->clippingRect.isValid() && !this->clippingRect.intersects(seg_bb) && - (!seg.is_horizontal() && !seg.is_vertical())) - { return *this; } + if (this->clippingRect.isValid() && + ! this->clippingRect.intersects(seg_bb) && + ! seg.is_horizontal() && ! seg.is_vertical()) + return *this; this->painterOstream << seg; return *this; } -// Instantiation of Arr_polyline_traits_2 - +// Specialization of `ArrangementPainterOstream` for the polyline traits. template ArrangementPainterOstream>& ArrangementPainterOstream>:: -operator<<(const X_monotone_curve_2& curve) -{ +operator<<(const X_monotone_curve_2& curve) { int cnt = 0; - for (typename X_monotone_curve_2::Subcurve_const_iterator it = - curve.subcurves_begin(); - it != curve.subcurves_end(); ++it) - { - cnt++; + for (auto it = curve.subcurves_begin(); it != curve.subcurves_end(); ++it) { + ++cnt; this->painterOstream << *it; } return *this; } -// Instantiation of Arr_conic_traits_2 -template -auto ArrangementPainterOstream>::visibleParts(X_monotone_curve_2 curve) - -> std::vector -{ +// Specialization of `ArrangementPainterOstream` for the conic traits. +template +auto ArrangementPainterOstream +>:: +visibleParts(X_monotone_curve_2 curve) -> std::vector { // see if we intersect the bottom edge of the viewport Point_2 bottomLeft = this->convert(this->clippingRect.bottomLeft()); Point_2 bottomRight = this->convert(this->clippingRect.bottomRight()); @@ -101,18 +92,16 @@ auto ArrangementPainterOstream rightEndpt.x()) { std::swap(leftEndpt, rightEndpt); } + if (leftEndpt.x() > rightEndpt.x()) std::swap(leftEndpt, rightEndpt); QPointF qendpt1 = this->convert(leftEndpt); QPointF qendpt2 = this->convert(rightEndpt); std::list pointList; - for (unsigned int i = 0; i < intersections.size(); ++i) - { + for (unsigned int i = 0; i < intersections.size(); ++i) { CGAL::Object o = intersections[i]; std::pair pair; - if (CGAL::assign(pair, o)) - { + if (CGAL::assign(pair, o)) { Point_2 pt = pair.first; pointList.push_back(pt); } @@ -120,41 +109,36 @@ auto ArrangementPainterOstreamclippingRect.contains(qendpt1); bool includeRightEndpoint = this->clippingRect.contains(qendpt2); - if (includeLeftEndpoint) { pointList.push_front(leftEndpt); } + if (includeLeftEndpoint) pointList.push_front(leftEndpt); - if (includeRightEndpoint) { pointList.push_back(rightEndpt); } + if (includeRightEndpoint) pointList.push_back(rightEndpt); // TODO: make ArrangementPainterOstream take traits object - Traits traits; - Construct_x_monotone_subcurve_2 construct_x_monotone_subcurve_2{ - &traits}; + auto trim = traits.trim_2_object(); std::vector clippings; - typename std::list::iterator pointListItr = pointList.begin(); - for (unsigned int i = 0; i < pointList.size(); i += 2) - { - typename Traits::Point_2 p1 = *pointListItr++; - typename Traits::Point_2 p2 = *pointListItr++; - X_monotone_curve_2 subcurve = - construct_x_monotone_subcurve_2(curve, p1, p2); - clippings.push_back(subcurve); + auto it = pointList.begin(); + for (unsigned int i = 0; i < pointList.size(); i += 2) { + typename Traits::Point_2 p1 = *it++; + typename Traits::Point_2 p2 = *it++; + auto xcv = trim(curve, p1, p2); + clippings.push_back(xcv); } return clippings; } -template -void ArrangementPainterOstream< - CGAL::Arr_conic_traits_2>:: - filterIntersectionPoints(std::vector& res) -{ +// +template +void ArrangementPainterOstream +>:: +filterIntersectionPoints(std::vector& res) { std::vector> tmp; // filter out the non-intersection point results - for (unsigned int i = 0; i < res.size(); ++i) - { + for (unsigned int i = 0; i < res.size(); ++i) { CGAL::Object obj = res[i]; std::pair pair; - if (CGAL::assign(pair, obj)) { tmp.push_back(pair); } + if (CGAL::assign(pair, obj)) tmp.push_back(pair); } res.clear(); @@ -163,84 +147,76 @@ void ArrangementPainterOstream< std::sort(tmp.begin(), tmp.end(), compare_intersection_point_result); // box up the sorted elements - for (unsigned int i = 0; i < tmp.size(); ++i) - { + for (unsigned int i = 0; i < tmp.size(); ++i) { std::pair pair = tmp[i]; CGAL::Object o = CGAL::make_object(pair); res.push_back(o); } } -template -ArrangementPainterOstream< - CGAL::Arr_conic_traits_2>& -ArrangementPainterOstream>::operator<<(const X_monotone_curve_2& curve) -{ +// +template +ArrangementPainterOstream +>& +ArrangementPainterOstream +>:: +operator<<(const X_monotone_curve_2& curve) { CGAL::Bbox_2 bb = traits.construct_bbox_2_object()(curve); QRectF qbb = this->convert(bb); // quick cull - if (this->clippingRect.isValid() && !this->clippingRect.intersects(qbb)) - { return *this; } + if (this->clippingRect.isValid() && ! this->clippingRect.intersects(qbb)) + return *this; // get number of segments - // QGraphicsView* view = this->scene->views().first(); - // auto pmin = view->mapFromScene(bb.xmin(), bb.ymin()); - // auto pmax = view->mapFromScene(bb.xmax(), bb.ymax()); - // std::cout << "extreme: " - // << pmin.x() << ", " << pmin.y() << "," - // << pmax.x() << ", " << pmax.y() << std::endl; - // // can be negitive due to rotation trasnformation - // size_t n = static_cast(std::abs(xmax - xmin)); - // if (n == 0) { return *this; } - double error = 1; + QGraphicsView* view = this->scene->views().first(); + auto pmin = view->mapFromScene(bb.xmin(), bb.ymin()); + auto pmax = view->mapFromScene(bb.xmax(), bb.ymax()); + double world_xdiff = std::abs(bb.xmax() - bb.xmin()); + double screen_xdiff = std::abs(pmax.x() - pmin.x()); + double error = world_xdiff / screen_xdiff; auto paint_curve = [&](auto&& curve_) { using Approximate_point_2 = typename Traits::Approximate_point_2; - std::vector app_pts; - // app_pts.reserve(n + 1); - // curve_.polyline_approximation(n, std::back_inserter(app_pts)); + std::vector points; auto aprox = traits.approximate_2_object(); - aprox(curve_, error, std::back_inserter(app_pts)); - auto p_curr = app_pts.begin(); - auto end_pts = app_pts.end(); + aprox(curve_, error, std::back_inserter(points)); + auto p_curr = points.begin(); + auto end_pts = points.end(); auto p_next = p_curr + 1; do { QPointF p1(p_curr->x(), p_curr->y()); QPointF p2(p_next->x(), p_next->y()); this->qp->drawLine(p1, p2); - p_curr++; - p_next++; + ++p_curr; + ++p_next; } while (p_next != end_pts); }; if (this->clippingRect.isValid()) { - std::vector visibleParts; - if (this->clippingRect.contains(qbb)) - visibleParts.push_back(curve); - else - visibleParts = this->visibleParts(curve); - for (auto& visiblePart : visibleParts) paint_curve(visiblePart); + if (this->clippingRect.contains(qbb)) { + paint_curve(curve); + return *this; + } + std::vector parts; + parts = this->visibleParts(curve); + for (auto& part : parts) paint_curve(part); + return *this; } - else { - // draw the whole curve - paint_curve(curve); - } - // paint_curve(curve); + // draw the whole curve + paint_curve(curve); return *this; } -// Instantiation of Arr_Bezier_traits_2 -template < - typename RatKernel, typename AlgKernel, typename NtTraits, - typename BoundingTraits> +// Specialization of `ArrangementPainterOstream` for the Bezier traits. +template std::vector> -ArrangementPainterOstream>::getPoints(const X_monotone_curve_2& curve) -{ +ArrangementPainterOstream +>:: +getPoints(const X_monotone_curve_2& curve) { std::pair param_range = curve.parameter_range(); auto&& supporting_curve = curve.supporting_curve(); @@ -256,12 +232,13 @@ ArrangementPainterOstream -auto ArrangementPainterOstream>::operator<<(const X_monotone_curve_2& curve) +// +template +auto ArrangementPainterOstream +>:: +operator<<(const X_monotone_curve_2& curve) -> ArrangementPainterOstream& { auto sampled_points = this->getPoints(curve); @@ -276,57 +253,45 @@ auto ArrangementPainterOstream ArrangementPainterOstream>& -ArrangementPainterOstream>::operator<<( - const X_monotone_curve_2& curve) -{ - if (curve.is_segment()) - { +ArrangementPainterOstream>:: +operator<<(const X_monotone_curve_2& curve) { + if (curve.is_segment()) { Segment_2 seg = curve.segment(); // skip segments outside our view QRectF seg_bb = this->convert(seg.bbox()); - if ( - this->clippingRect.isValid() && - !this->clippingRect.intersects(seg_bb) && + if (this->clippingRect.isValid() && + ! this->clippingRect.intersects(seg_bb) && (!seg.is_horizontal() && !seg.is_vertical())) - { return *this; } + return *this; this->painterOstream << seg; } - else if (curve.is_ray()) - { + else if (curve.is_ray()) { Ray_2 ray = curve.ray(); QLineF qseg = this->convert(ray); - if (qseg.isNull()) - { // it's out of view - return *this; - } + if (qseg.isNull()) return *this; // it's out of view Segment_2 seg = this->convert(qseg); this->painterOstream << seg; } - else // curve.is_line( ) - { + else { + // curve.is_line( ) Line_2 line = curve.line(); QLineF qseg = this->convert(line); - if (qseg.isNull()) - { // it's out of view - return *this; - } + if (qseg.isNull()) return *this; // it's out of view Segment_2 seg = this->convert(qseg); this->painterOstream << seg; } return *this; } -// Instantiation of Arr_algebraic_segment_traits_2 +// Specialization of `ArrangementPainterOstream` for the algebraic traits. template -static bool lies_on_border( - const ArrangementPainterOstream* apo, const QPointF& point) -{ +static bool lies_on_border(const ArrangementPainterOstream* apo, + const QPointF& point) { QGraphicsView* view = apo->getScene()->views().first(); qreal width = view->width(); qreal height = view->height(); @@ -335,26 +300,27 @@ static bool lies_on_border( std::abs(point.y() - height) < tol || point.y() < tol; } +// template -void ArrangementPainterOstream< - CGAL::Arr_algebraic_segment_traits_2>::remapFacadePainter() -{ - this->qp->setTransform(this->getPointsListMapping()); -} +void +ArrangementPainterOstream>:: +remapFacadePainter() +{ this->qp->setTransform(this->getPointsListMapping()); } +// template -QTransform ArrangementPainterOstream< - CGAL::Arr_algebraic_segment_traits_2>::getPointsListMapping() -{ +QTransform +ArrangementPainterOstream>:: +getPointsListMapping() { auto worldTransform = this->qp->transform(); return this->getPointsListMapping(worldTransform); } +// template QTransform ArrangementPainterOstream>:: - getPointsListMapping(const QTransform& worldTransform) -{ +getPointsListMapping(const QTransform& worldTransform) { auto view = this->getView(); QRectF viewport = this->viewportRect(); @@ -377,11 +343,11 @@ ArrangementPainterOstream>:: return QTransform{m11, m12, m21, m22, dx, dy}; } +// template -auto ArrangementPainterOstream>::getPointsList(const X_monotone_curve_2& curve) - -> std::vector -{ +auto ArrangementPainterOstream +>:: +getPointsList(const X_monotone_curve_2& curve) -> std::vector { typedef Curve_renderer_facade Facade; typedef std::pair Coord_2; typedef std::vector Coord_vec_2; @@ -391,11 +357,11 @@ auto ArrangementPainterOstream ArrangementPainterOstream>& ArrangementPainterOstream>:: -operator<<(const X_monotone_curve_2& curve) -{ +operator<<(const X_monotone_curve_2& curve) { this->qp->save(); this->remapFacadePainter(); this->paintCurve(curve); @@ -403,20 +369,19 @@ operator<<(const X_monotone_curve_2& curve) return *this; } +// template -void ArrangementPainterOstream>::paintCurve(const X_monotone_curve_2& curve) -{ +void ArrangementPainterOstream +>:: +paintCurve(const X_monotone_curve_2& curve) { std::vector points = this->getPointsList(curve); - for (auto& vec : points) - { + for (auto& vec : points) { auto vit = vec.begin(); QPainterPath path; QPointF qpt(vit->first, vit->second); path.moveTo(qpt); - for (auto& vit : vec) - { + for (auto& vit : vec) { QPointF qpt_new = QPointF(vit.first, vit.second); if (lies_on_border(this, qpt) && lies_on_border(this, qpt_new)) path.moveTo(qpt_new); @@ -428,10 +393,10 @@ void ArrangementPainterOstream -void ArrangementPainterOstream< - CGAL::Arr_algebraic_segment_traits_2>::setupFacade() -{ +void ArrangementPainterOstream +>::setupFacade() { typedef Curve_renderer_facade Facade; QGraphicsView* view = this->getView(); QRectF viewport = this->viewportRect(); @@ -439,18 +404,16 @@ void ArrangementPainterOstream< Facade::setup(bbox, view->width(), view->height()); } -// Instantiation of Arr_rational_function_traits_2 - -template +// Specialization of `ArrangementPainterOstream` for Arr_rational_function_traits_2 +template constexpr const T& clamp(const T& v, const T& lo, const T& hi) -{ - return (v < lo) ? lo : (hi < v) ? hi : v; -} +{ return (v < lo) ? lo : (hi < v) ? hi : v; } +// template -auto ArrangementPainterOstream>::operator<<(const X_monotone_curve_2& curve) -> Self& -{ +auto ArrangementPainterOstream +>:: +operator<<(const X_monotone_curve_2& curve) -> Self& { QPainterPath painterPath; const QRectF viewport = this->viewportRect(); // overshoot so that the slope would be more accurate @@ -464,8 +427,7 @@ auto ArrangementPainterOstream max_y || y < min_y) - { + if (y > max_y || y < min_y) { double x_ = x; double y_ = clamp(y, min_y, max_y); @@ -473,8 +435,8 @@ auto ArrangementPainterOstream -auto ArrangementPainterOstream>::getPointsList(const X_monotone_curve_2& curve) - -> std::vector -{ +auto ArrangementPainterOstream +>:: +getPointsList(const X_monotone_curve_2& curve) -> std::vector { std::vector points_list; Coord_vec_2* cur_list = nullptr; @@ -527,15 +486,13 @@ auto ArrangementPainterOstream max_y || y < min_y) - { + if (y > max_y || y < min_y) { double x_ = x; double y_ = clamp(y, min_y, max_y); - if (!disconnected) - cur_list->push_back({x_, y_}); - else if ( - (last_y == min_y && y_ == max_y) || (last_y == max_y && y_ == min_y)) + if (!disconnected) cur_list->push_back({x_, y_}); + else if ((last_y == min_y && y_ == max_y) || + (last_y == max_y && y_ == min_y)) { cur_list->push_back({last_x, last_y}); cur_list->push_back({x_, y_}); @@ -545,10 +502,8 @@ auto ArrangementPainterOstreampush_back({last_x, last_y}); @@ -563,12 +518,12 @@ auto ArrangementPainterOstream template -void ArrangementPainterOstream< - CGAL::Arr_rational_function_traits_2>:: - sample_points(const X_monotone_curve_2& curve, Lambda&& lambda) -{ +void ArrangementPainterOstream +>:: +sample_points(const X_monotone_curve_2& curve, Lambda&& lambda) { // TODO: cache maximum and minimal points for each curve, and include them // in the sampled points const QRectF viewport = this->viewportRect(); @@ -578,80 +533,63 @@ void ArrangementPainterOstream< auto&& numer = curve._f.numer(); auto&& denom = curve._f.denom(); - auto eval_at = [&](auto&& x) { - return numer.evaluate(x) / denom.evaluate(x); - }; + auto eval_at = [&](auto&& x) { return numer.evaluate(x) / denom.evaluate(x); }; - if ( // be conservative and prefer this branch to avoid zero division - curve.left_parameter_space_in_x() == ARR_INTERIOR && - curve.left_x().to_interval().second >= min_x) + // be conservative and prefer this branch to avoid zero division + if (curve.left_parameter_space_in_x() == ARR_INTERIOR && + curve.left_x().to_interval().second >= min_x) { min_x = curve.left_x().to_interval().second; - switch (curve.left_parameter_space_in_y()) - { - case ARR_INTERIOR: { - auto left_pt = curve.left().to_double(); - lambda(min_x, left_pt.second); - break; - } - case ARR_TOP_BOUNDARY: { - lambda(min_x, std::numeric_limits::infinity()); - break; - } - case ARR_BOTTOM_BOUNDARY: { - lambda(min_x, -std::numeric_limits::infinity()); - break; - } - default: { - CGAL_error(); - } + switch (curve.left_parameter_space_in_y()) { + case ARR_INTERIOR: { + auto left_pt = curve.left().to_double(); + lambda(min_x, left_pt.second); + break; + } + case ARR_TOP_BOUNDARY: { + lambda(min_x, std::numeric_limits::infinity()); + break; + } + case ARR_BOTTOM_BOUNDARY: { + lambda(min_x, -std::numeric_limits::infinity()); + break; + } + default: { + CGAL_error(); + } } } - else if ( - curve.right_parameter_space_in_x() != ARR_INTERIOR || - min_x < curve.right_x().to_interval().first) - { + else if (curve.right_parameter_space_in_x() != ARR_INTERIOR || + min_x < curve.right_x().to_interval().first) lambda(min_x, CGAL::to_double(eval_at(Rational{min_x}))); - } - else // outside of viewport - { - return; - } + else return; // outside of viewport std::pair last_pt; - if ( // be conservative and prefer this branch to avoid zero division - curve.right_parameter_space_in_x() == ARR_INTERIOR && - curve.right_x().to_interval().first <= max_x) + // be conservative and prefer this branch to avoid zero division + if (curve.right_parameter_space_in_x() == ARR_INTERIOR && + curve.right_x().to_interval().first <= max_x) { max_x = curve.right_x().to_interval().first; - switch (curve.right_parameter_space_in_y()) - { - case ARR_INTERIOR: { - last_pt = {max_x, curve.right().to_double().second}; - break; - } - case ARR_TOP_BOUNDARY: { - last_pt = {max_x, std::numeric_limits::infinity()}; - break; - } - case ARR_BOTTOM_BOUNDARY: { - last_pt = {max_x, -std::numeric_limits::infinity()}; - break; - } - default: { - CGAL_error(); - } + switch (curve.right_parameter_space_in_y()) { + case ARR_INTERIOR: { + last_pt = {max_x, curve.right().to_double().second}; + break; + } + case ARR_TOP_BOUNDARY: { + last_pt = {max_x, std::numeric_limits::infinity()}; + break; + } + case ARR_BOTTOM_BOUNDARY: { + last_pt = {max_x, -std::numeric_limits::infinity()}; + break; + } + default: { CGAL_error(); } } } else if (max_x > min_x) - { last_pt = {max_x, CGAL::to_double(eval_at(Rational{max_x}))}; - } - else // outside of viewport - { - return; - } + else return; // outside of viewport static constexpr int dx_pixel = 1; static constexpr int min_num_points = 20; diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index 40c48687b61..3681776bd62 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -2885,39 +2885,43 @@ public: * direction of the arc. */ X_monotone_curve_2 trim(const X_monotone_curve_2& xcv, - const Point_2& ps, - const Point_2& pt) const { + const Point_2& ps, const Point_2& pt) const { // Make sure that both ps and pt lie on the arc. CGAL_precondition(m_traits.contains_point(xcv, ps) && m_traits.contains_point(xcv, pt)); - // Make sure that the endpoints conform with the direction of the arc. - X_monotone_curve_2 res_xcv = xcv; - auto cmp_xy = m_traits.m_alg_kernel->compare_xy_2_object(); - if (! ((xcv.test_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT) && - (cmp_xy(ps, pt) == SMALLER)) || - (xcv.test_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT) && - (cmp_xy(ps, pt) == LARGER)))) - { - // We are allowed to change the direction only in case of a segment. - CGAL_assertion(xcv.orientation() == COLLINEAR); - res_xcv.flip_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT); - } + X_monotone_curve_2 res_xcv = xcv; // make a copy of the current arc - // Make a copy of the current arc and assign its endpoints. auto eq = m_traits.m_alg_kernel->equal_2_object(); - if (! eq(ps, xcv.source())) { - res_xcv.set_source(ps); + auto set_source = [&](const Point_2 ps)->void { + if (! eq(ps, xcv.source())) { + res_xcv.set_source(ps); + if (! ps.is_generating_conic(xcv.id())) + res_xcv.source().set_generating_conic(xcv.id()); + } + }; + auto set_target = [&](const Point_2 pt)->void { + if (! eq(pt, xcv.target())) { + res_xcv.set_target(pt); + if (! pt.is_generating_conic(xcv.id())) + res_xcv.target().set_generating_conic(xcv.id()); + } + }; - if (! ps.is_generating_conic(xcv.id())) - res_xcv.source().set_generating_conic(xcv.id()); + // Make sure that the endpoints conform with the direction of the arc. + auto cmp_xy = m_traits.m_alg_kernel->compare_xy_2_object(); + auto res = cmp_xy(ps, pt); + CGAL_assertion(res != EQUAL); + if ((xcv.test_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT) && + (res == LARGER)) || + (! xcv.test_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT) && + (res == SMALLER))) { + set_source(pt); + set_target(ps); } - - if (! eq(pt, xcv.target())) { - res_xcv.set_target(pt); - - if (! pt.is_generating_conic(xcv.id())) - res_xcv.target().set_generating_conic(xcv.id()); + else { + set_source(ps); + set_target(pt); } return res_xcv; diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h index 122da7f7380..6d2bf119bb9 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h @@ -695,32 +695,34 @@ public: // Make sure that the endpoints conform with the direction of the arc. Alg_kernel alg_kernel; - Self res_xcv = xcv; - auto cmp_xy = alg_kernel.compare_xy_2_object(); - if (! ((xcv.test_flag(Self::IS_DIRECTED_RIGHT) && - (cmp_xy(ps, pt) == SMALLER)) || - (xcv.test_flag(Self::IS_DIRECTED_RIGHT) && - (cmp_xy(ps, pt) == LARGER)))) - { - // We are allowed to change the direction only in case of a segment. - CGAL_assertion(xcv.orientation() == COLLINEAR); - res_xcv.flip_flag(Self::IS_DIRECTED_RIGHT); - } - - // Make a copy of the current arc and assign its endpoints. + Self res_xcv = xcv; // make a copy of the current arc auto eq = alg_kernel.equal_2_object(); - if (! eq(ps, xcv.source())) { - res_xcv.set_source(ps); + auto set_source = [&](const Point_2 ps)->void { + if (! eq(ps, xcv.source())) { + res_xcv.set_source(ps); + if (! ps.is_generating_conic(xcv.id())) + res_xcv.source().set_generating_conic(xcv.id()); + } + }; + auto set_target = [&](const Point_2 pt)->void { + if (! eq(pt, xcv.target())) { + res_xcv.set_target(pt); + if (! pt.is_generating_conic(xcv.id())) + res_xcv.target().set_generating_conic(xcv.id()); + } + }; - if (! ps.is_generating_conic(xcv.id())) - res_xcv.source().set_generating_conic(xcv.id()); + auto cmp_xy = alg_kernel.compare_xy_2_object(); + auto res = cmp_xy(ps, pt); + CGAL_assertion(res != EQUAL); + if ((xcv.test_flag(Self::IS_DIRECTED_RIGHT) && (res == LARGER)) || + (! xcv.test_flag(Self::IS_DIRECTED_RIGHT) && (res == SMALLER))) { + set_source(pt); + set_target(ps); } - - if (! eq(pt, xcv.target())) { - res_xcv.set_target(pt); - - if (! pt.is_generating_conic(xcv.id())) - res_xcv.target().set_generating_conic(xcv.id()); + else { + set_source(ps); + set_target(pt); } return res_xcv; From 8635e580f4389bdb681d0636e0c6fb8da0ff1a9a Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 14 Sep 2022 09:29:36 +0300 Subject: [PATCH 082/105] Fixed leak. Used the traits from the arrangement instead of allocating a new one. --- .../demo/Arrangement_on_surface_2/ArrangementIO.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementIO.cpp b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementIO.cpp index a6c573a9b4b..dc95842d6e1 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementIO.cpp +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementIO.cpp @@ -45,12 +45,12 @@ struct ArrReadergeometry_traits(); Conic_reader conicReader(*traits);; std::vector curve_list; CGAL::Bbox_2 bbox; conicReader.read_data(ifs, std::back_inserter(curve_list), bbox); - auto arr = new Arrangement(traits); CGAL::insert(*arr, curve_list.begin(), curve_list.end()); return arr; } From c01b6b95eeb79d9b30d4a8b5323399f0869a80e2 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 28 Sep 2022 11:19:16 +0300 Subject: [PATCH 083/105] Used boost::math::constants::pi() instead of M_PI macro. --- .../include/CGAL/Arr_circle_segment_traits_2.h | 12 +++++++----- .../include/CGAL/Arr_conic_traits_2.h | 11 ++++++----- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h index 2e9aed130e9..b5574767c8a 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h @@ -24,11 +24,12 @@ */ // Keep the following 2 lines first. -#define _USE_MATH_DEFINES #include #include #include +#include + #include #include #include @@ -503,6 +504,7 @@ public: OutputIterator approximate_arc(const X_monotone_curve_2& xcv, double error, OutputIterator oi, bool l2r = true) const { + constexpr auto pi = boost::math::constants::pi(); auto min_vertex = m_traits.construct_min_vertex_2_object(); auto max_vertex = m_traits.construct_max_vertex_2_object(); const auto& src = (l2r) ? min_vertex(xcv) : max_vertex(xcv); @@ -530,16 +532,16 @@ public: // source == (x(ts),y(ts)), and // target == (x(tt),y(tt)) auto ts = std::atan2(r*ys_t, r*xs_t); - if (ts < 0) ts += 2*M_PI; + if (ts < 0) ts += 2*pi; auto tt = std::atan2(r*yt_t, r*xt_t); - if (tt < 0) tt += 2*M_PI; + if (tt < 0) tt += 2*pi; auto orient(xcv.orientation()); if (xcv.source() != src) orient = CGAL::opposite(orient); if (orient == COUNTERCLOCKWISE) { - if (tt < ts) tt += 2*M_PI; + if (tt < ts) tt += 2*pi; } else { - if (ts < tt) ts += 2*M_PI; + if (ts < tt) ts += 2*pi; } *oi++ = Approximate_point_2(xs, ys); diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index 3681776bd62..430d42aba22 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -24,7 +24,6 @@ */ // Keep the following 2 lines first. -#define _USE_MATH_DEFINES #include #include #include @@ -32,6 +31,7 @@ #include #include +#include #include #include @@ -4121,6 +4121,7 @@ public: double& a, double& b, double& cx, double& cy, bool l2r = true) const { + const double pi = boost::math::constants::pi(); auto min_vertex = construct_min_vertex_2_object(); auto max_vertex = construct_max_vertex_2_object(); const auto& src = (l2r) ? min_vertex(xcv) : max_vertex(xcv); @@ -4174,16 +4175,16 @@ public: // source == (x(ts),y(ts)), and // target == (x(tt),y(tt)) ts = std::atan2(a*ys_t, b*xs_t); - if (ts < 0) ts += 2*M_PI; + if (ts < 0) ts += 2*pi; tt = std::atan2(a*yt_t, b*xt_t); - if (tt < 0) tt += 2*M_PI; + if (tt < 0) tt += 2*pi; auto orient(xcv.orientation()); if (xcv.source() != src) orient = CGAL::opposite(orient); if (orient == COUNTERCLOCKWISE) { - if (tt < ts) tt += 2*M_PI; + if (tt < ts) tt += 2*pi; } else { - if (ts < tt) ts += 2*M_PI; + if (ts < tt) ts += 2*pi; } // std::cout << "ts,tt: " << ts << "," << tt << std::endl; } From 2639ef203f63e8e4079626722f667c0b6d9e3609 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 28 Sep 2022 12:20:25 +0300 Subject: [PATCH 084/105] Used CGAL_PI --- .../include/CGAL/Arr_circle_segment_traits_2.h | 11 ++++------- .../include/CGAL/Arr_conic_traits_2.h | 10 ++++------ 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h index b5574767c8a..afa61867dbe 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h @@ -28,8 +28,6 @@ #include #include -#include - #include #include #include @@ -504,7 +502,6 @@ public: OutputIterator approximate_arc(const X_monotone_curve_2& xcv, double error, OutputIterator oi, bool l2r = true) const { - constexpr auto pi = boost::math::constants::pi(); auto min_vertex = m_traits.construct_min_vertex_2_object(); auto max_vertex = m_traits.construct_max_vertex_2_object(); const auto& src = (l2r) ? min_vertex(xcv) : max_vertex(xcv); @@ -532,16 +529,16 @@ public: // source == (x(ts),y(ts)), and // target == (x(tt),y(tt)) auto ts = std::atan2(r*ys_t, r*xs_t); - if (ts < 0) ts += 2*pi; + if (ts < 0) ts += 2*CGAL_PI; auto tt = std::atan2(r*yt_t, r*xt_t); - if (tt < 0) tt += 2*pi; + if (tt < 0) tt += 2*CGAL_PI; auto orient(xcv.orientation()); if (xcv.source() != src) orient = CGAL::opposite(orient); if (orient == COUNTERCLOCKWISE) { - if (tt < ts) tt += 2*pi; + if (tt < ts) tt += 2*CGAL_PI; } else { - if (ts < tt) ts += 2*pi; + if (ts < tt) ts += 2*CGAL_PI; } *oi++ = Approximate_point_2(xs, ys); diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index 430d42aba22..58c5e78fb4d 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -32,7 +32,6 @@ #include #include -#include #include #include @@ -4121,7 +4120,6 @@ public: double& a, double& b, double& cx, double& cy, bool l2r = true) const { - const double pi = boost::math::constants::pi(); auto min_vertex = construct_min_vertex_2_object(); auto max_vertex = construct_max_vertex_2_object(); const auto& src = (l2r) ? min_vertex(xcv) : max_vertex(xcv); @@ -4175,16 +4173,16 @@ public: // source == (x(ts),y(ts)), and // target == (x(tt),y(tt)) ts = std::atan2(a*ys_t, b*xs_t); - if (ts < 0) ts += 2*pi; + if (ts < 0) ts += 2*CGAL_PI; tt = std::atan2(a*yt_t, b*xt_t); - if (tt < 0) tt += 2*pi; + if (tt < 0) tt += 2*CGAL_PI; auto orient(xcv.orientation()); if (xcv.source() != src) orient = CGAL::opposite(orient); if (orient == COUNTERCLOCKWISE) { - if (tt < ts) tt += 2*pi; + if (tt < ts) tt += 2*CGAL_PI; } else { - if (ts < tt) ts += 2*pi; + if (ts < tt) ts += 2*CGAL_PI; } // std::cout << "ts,tt: " << ts << "," << tt << std::endl; } From 8ab29c50b25b2b5d75f1fc38db2c4d91eb61d4b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 13 Oct 2022 13:42:10 +0200 Subject: [PATCH 085/105] fix header --- Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h index 00119383a35..91104a216c1 100644 --- a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h +++ b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include From d8fb80551c9824ea8cbd3268eb0ba67d026cfe96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 13 Oct 2022 13:48:16 +0200 Subject: [PATCH 086/105] fix warnings --- .../include/CGAL/Arr_conic_traits_2.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index 58c5e78fb4d..638e5f630b2 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -812,8 +812,8 @@ public: * `ARR_TOP_BOUNDARY` —the arc approaches the north pole at the arc * right end. */ - Arr_parameter_space operator()(const X_monotone_curve_2& xcv, - Arr_curve_end ce) const { + Arr_parameter_space operator()(const X_monotone_curve_2& /* xcv */, + Arr_curve_end /* ce */) const { CGAL_error_msg("Not implemented yet!"); return ARR_INTERIOR; } @@ -1640,7 +1640,7 @@ public: return d; } - double hyperbola_length(const X_monotone_curve_2& xcv) { + double hyperbola_length(const X_monotone_curve_2& /* xcv */) { CGAL_error_msg("Not implemented yet!"); double l(0.0); return l; @@ -3015,7 +3015,7 @@ public: // Go over the vertical tangency points and try to update the x-points. Alg_point_2 tan_ps[2]; auto n_tan_ps = m_traits.vertical_tangency_points(xcv, tan_ps); - for (auto i = 0; i < n_tan_ps; ++i) { + for (decltype(n_tan_ps) i = 0; i < n_tan_ps; ++i) { if (CGAL::to_double(tan_ps[i].x()) < x_min) x_min = CGAL::to_double(tan_ps[i].x()); if (CGAL::to_double(tan_ps[i].x()) > x_max) @@ -3024,7 +3024,7 @@ public: // Go over the horizontal tangency points and try to update the y-points. n_tan_ps = m_traits.horizontal_tangency_points(xcv, tan_ps); - for (auto i = 0; i < n_tan_ps; ++i) { + for (decltype(n_tan_ps) i = 0; i < n_tan_ps; ++i) { if (CGAL::to_double(tan_ps[i].y()) < y_min) y_min = CGAL::to_double(tan_ps[i].y()); if (CGAL::to_double(tan_ps[i].y()) > y_max) @@ -3944,12 +3944,12 @@ public: // Calculate the horizontal tangency points of the conic. Alg_point_2 ps[2]; - int n = conic_horizontal_tangency_points(cv, ps); + std::size_t n = conic_horizontal_tangency_points(cv, ps); // Return only the points that are contained in the arc interior. int m = 0; - for (int i = 0; i < n; ++i) { + for (std::size_t i = 0; i < n; ++i) { if (cv.is_full_conic() || is_strictly_between_endpoints(cv, ps[i])) hpts[m++] = ps[i]; } From e1c7254ffb9421c42e9d9fe322adf85fd05de680 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 17 Oct 2022 10:30:42 +0200 Subject: [PATCH 087/105] fix conversion warnings --- Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h | 2 +- Envelope_3/include/CGAL/Env_sphere_traits_3.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h index 91104a216c1..079fac49c6e 100644 --- a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h +++ b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h @@ -454,7 +454,7 @@ protected: std::unordered_map m_visited; std::mt19937 m_rng; - std::uniform_int_distribution m_uni; // guaranteed unbiased + std::uniform_int_distribution m_uni; // guaranteed unbiased }; //! Basic viewer of a 2D arrangement. diff --git a/Envelope_3/include/CGAL/Env_sphere_traits_3.h b/Envelope_3/include/CGAL/Env_sphere_traits_3.h index 555e87e552b..bcf2228dbd5 100644 --- a/Envelope_3/include/CGAL/Env_sphere_traits_3.h +++ b/Envelope_3/include/CGAL/Env_sphere_traits_3.h @@ -598,7 +598,7 @@ public: Curve_2 inter_cv = ctr_cv(R, S, T, U, V, W); Alg_point_2 vtan_ps[2]; - CGAL_assertion_code(int n_vtan_ps =) + CGAL_assertion_code(std::size_t n_vtan_ps =) gt_2->vertical_tangency_points(inter_cv, vtan_ps); CGAL_assertion(n_vtan_ps == 2); From a314ee690675186159ba1b3bf917a90d14ccfe4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 17 Oct 2022 11:23:02 +0200 Subject: [PATCH 088/105] add warning message if qt cannot be found --- .../examples/Arrangement_on_surface_2/CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/CMakeLists.txt b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/CMakeLists.txt index 3d61e7b6c81..bd3e707c4b4 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/CMakeLists.txt +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.1...3.23) project(Arrangement_on_surface_2_Examples) -find_package(CGAL REQUIRED COMPONENTS Core Qt5) +find_package(CGAL REQUIRED COMPONENTS Core OPTIONAL_COMPONENTS Qt5) # create a target per cppfile file( @@ -24,4 +24,9 @@ if(CGAL_Qt5_FOUND) target_link_libraries(polylines PUBLIC CGAL::CGAL_Basic_viewer) target_link_libraries(circles PUBLIC CGAL::CGAL_Basic_viewer) target_link_libraries(circular_arcs PUBLIC CGAL::CGAL_Basic_viewer) +else() + message( + STATUS + "NOTICE: Several examples require Qt and will not be compiled." + ) endif() From b6bdac284797dd802d55738e5787370403975bd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 17 Oct 2022 11:23:22 +0200 Subject: [PATCH 089/105] add workaround to use boost hana with MSVC --- .../include/CGAL/draw_arrangement_2.h | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h index 079fac49c6e..98243ddc9d7 100644 --- a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h +++ b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h @@ -21,13 +21,24 @@ #include #include -#include -#include - #include #ifdef CGAL_USE_BASIC_VIEWER +#include + + +#if defined(BOOST_MSVC) +// workaround for using boost::hana with MSVC without warnings +#pragma push_macro("__cplusplus") +#undef __cplusplus +#define __cplusplus _MSVC_LANG +#include +#pragma pop_macro("__cplusplus") +#else +#include +#endif + #include #include From ade16fc7d778a3567f366391b000b6d945c521e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 17 Oct 2022 14:12:41 +0200 Subject: [PATCH 090/105] fix warnings --- Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h index 98243ddc9d7..2e705f9224d 100644 --- a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h +++ b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h @@ -131,7 +131,7 @@ public: CGAL::Bbox_2 bbox; for (auto it = m_arr.vertices_begin(); it != m_arr.vertices_end(); ++it) { bh::if_(has_approximate_2_object(Gt{}), - [&](auto& x) { + [&](auto& /* x */) { const auto* traits = this->m_arr.geometry_traits(); auto approx = traits->approximate_2_object(); auto has_operator = @@ -298,7 +298,7 @@ protected: while (curr->face() == curr->twin()->face()) curr = curr->twin()->next(); bh::if_(has_approximate_2_object(Gt{}), - [&](auto& x) { + [&](auto& /* x */) { auto approx = traits->approximate_2_object(); auto has_operator = bh::is_valid(can_call_operator_curve{}); @@ -366,7 +366,7 @@ protected: bh::is_valid([](auto&& x) -> decltype(x.approximate_2_object()){}); const auto* traits = this->m_arr.geometry_traits(); bh::if_(has_approximate_2_object(Gt{}), - [&](auto& x) { + [&](auto& /* x */) { auto approx = traits->approximate_2_object(); auto has_operator = bh::is_valid(can_call_operator_curve{}); bh::if_(has_operator(approx), From 215b2ea5c495b512775f760bfc08762f076aad33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 18 Oct 2022 18:06:29 +0200 Subject: [PATCH 091/105] add missing config include --- Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h index 2e705f9224d..9c4c35f0311 100644 --- a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h +++ b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h @@ -17,6 +17,8 @@ #ifndef CGAL_DRAW_ARRANGEMENT_2_H #define CGAL_DRAW_ARRANGEMENT_2_H +#include + #include #include #include From 03285a42cf2584c79b6f1d2c5cbdf6851d174b7f Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 19 Oct 2022 01:30:38 +0300 Subject: [PATCH 092/105] Replaced std::uniform_int_distribution with std::uniform_int_distribution to pacify MSVC --- Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h index 9c4c35f0311..dfc3824a45c 100644 --- a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h +++ b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h @@ -467,7 +467,7 @@ protected: std::unordered_map m_visited; std::mt19937 m_rng; - std::uniform_int_distribution m_uni; // guaranteed unbiased + std::uniform_int_distribution m_uni; // guaranteed unbiased }; //! Basic viewer of a 2D arrangement. From 6705b15fdb534da5f4c1e58de4a68099310c4070 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Thu, 9 Feb 2023 01:03:33 +0200 Subject: [PATCH 093/105] Added color generator; improved internal API --- .../include/CGAL/draw_arrangement_2.h | 138 ++++++++++++------ 1 file changed, 93 insertions(+), 45 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h index dfc3824a45c..ff28ac0c630 100644 --- a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h +++ b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h @@ -46,19 +46,33 @@ namespace CGAL { +struct Default_color_generator { + /*! Obtain color + */ + template + CGAL::IO::Color operator()(HalfedgeHandle /* h */) { + static std::random_device rd; + static std::mt19937 rng(rd()); + static std::uniform_int_distribution uni(0, 255); + return CGAL::IO::Color(uni(rng), uni(rng), uni(rng)); + } +}; + // Viewer class for`< Polygon_2 -template +template class Arr_2_basic_viewer_qt : public Basic_viewer_qt { - typedef GeometryTraits_2 Gt; - typedef CGAL::Arrangement_2 Arr; - typedef Basic_viewer_qt Base; - typedef typename Arr::Point_2 Point; - typedef typename Arr::X_monotone_curve_2 X_monotone_curve; - typedef typename Arr::Vertex_const_handle Vertex_const_handle; - typedef typename Arr::Halfedge_const_handle Halfedge_const_handle; - typedef typename Arr::Face_const_handle Face_const_handle; - typedef typename Arr::Ccb_halfedge_const_circulator - Ccb_halfedge_const_circulator; + using Arr = Arrangement_2_; + using Color_generator = ColorGenerator; + using Base = Basic_viewer_qt; + using Gt = typename Arr::Geometry_traits_2; + using Point = typename Arr::Point_2; + using X_monotone_curve = typename Arr::X_monotone_curve_2; + using Vertex_const_handle = typename Arr::Vertex_const_handle; + using Halfedge_const_handle = typename Arr::Halfedge_const_handle; + using Face_const_handle = typename Arr::Face_const_handle; + using Ccb_halfedge_const_circulator = + typename Arr::Ccb_halfedge_const_circulator; template using approximate_2_object_t = @@ -69,11 +83,13 @@ public: /// @param arr the arrangement to view /// @param title the title of the window Arr_2_basic_viewer_qt(QWidget* parent, const Arr& arr, - const char* title = "2D Arrangement Basic Viewer") : + Color_generator color_generator, + const char* title = "2D Arrangement Basic Viewer", + bool draw_vertices = false) : // First draw: vertices; edges, faces; multi-color; no inverse normal - Base(parent, title, true, true, true, false, false), + Base(parent, title, draw_vertices, true, true, false, false), m_arr(arr), - m_uni(0, 255) + m_color_generator(color_generator) { // mimic the computation of Camera::pixelGLRatio() auto bbox = bounding_box(); @@ -157,9 +173,6 @@ public: clear(); m_visited.clear(); - std::random_device rd; - m_rng.seed(rd()); - if (m_arr.is_empty()) return; for (auto it = m_arr.unbounded_faces_begin(); it != m_arr.unbounded_faces_end(); ++it) @@ -289,7 +302,7 @@ protected: auto has_approximate_2_object = bh::is_valid([](auto&& x) -> decltype(x.approximate_2_object()){}); - CGAL::IO::Color color(m_uni(m_rng), m_uni(m_rng), m_uni(m_rng)); + auto color = m_color_generator(circ->face()); this->face_begin(color); const auto* traits = this->m_arr.geometry_traits(); @@ -464,32 +477,35 @@ protected: //! The arrangement to draw. const Arr& m_arr; - std::unordered_map m_visited; + //! The color generator. + Color_generator& m_color_generator; - std::mt19937 m_rng; - std::uniform_int_distribution m_uni; // guaranteed unbiased + std::unordered_map m_visited; }; //! Basic viewer of a 2D arrangement. -template -class Arr_2_viewer_qt : public Arr_2_basic_viewer_qt { +template +class Arr_2_viewer_qt : public Arr_2_basic_viewer_qt { public: - typedef GeometryTraits_2 Gt; - typedef CGAL::Arrangement_2 Arr; - typedef Arr_2_basic_viewer_qt Base; - typedef typename Arr::Point_2 Point; - typedef typename Arr::X_monotone_curve_2 X_monotone_curve; - typedef typename Arr::Halfedge_const_handle Halfedge_const_handle; - typedef typename Arr::Face_const_handle Face_const_handle; - typedef typename Arr::Ccb_halfedge_const_circulator - Ccb_halfedge_const_circulator; + using Arr = Arrangement_2_; + using Color_generator = ColorGenerator; + using Base = Arr_2_basic_viewer_qt; + using Point = typename Arr::Point_2; + using X_monotone_curve = typename Arr::X_monotone_curve_2; + using Halfedge_const_handle = typename Arr::Halfedge_const_handle; + using Face_const_handle = typename Arr::Face_const_handle; + using Ccb_halfedge_const_circulator = + typename Arr::Ccb_halfedge_const_circulator; /// Construct the viewer. /// @param arr the arrangement to view /// @param title the title of the window Arr_2_viewer_qt(QWidget* parent, const Arr& arr, + Color_generator color_generator, const char* title = "2D Arrangement Basic Viewer") : - Base(parent, arr, title) + Base(parent, arr, color_generator, title) {} }; @@ -500,22 +516,54 @@ void draw(const Arrangement_2& arr, #if defined(CGAL_TEST_SUITE) bool cgal_test_suite=true; #else - bool cgal_test_suite=qEnvironmentVariableIsSet("CGAL_TEST_SUITE"); + bool cgal_test_suite = qEnvironmentVariableIsSet("CGAL_TEST_SUITE"); #endif - if (!cgal_test_suite) { - typedef GeometryTraits_2 Gt; + if (cgal_test_suite) return; + using Gt = GeometryTraits_2; + using Arr = CGAL::Arrangement_2; + using Viewer = Arr_2_viewer_qt; - CGAL::Qt::init_ogl_context(4,3); + CGAL::Qt::init_ogl_context(4,3); - int argc = 1; - const char* argv[2] = {"t2_viewer", nullptr}; - QApplication app(argc, const_cast(argv)); - Arr_2_viewer_qt mainwindow(app.activeWindow(), arr, title); - mainwindow.add_elements(); - mainwindow.show(); - app.exec(); - } + int argc = 1; + const char* argv[2] = {"t2_viewer", nullptr}; + QApplication app(argc, const_cast(argv)); + Default_color_generator color_generator; + Viewer mainwindow(app.activeWindow(), arr, color_generator, title); + mainwindow.add_elements(); + mainwindow.show(); + app.exec(); +} + +//! +template +void draw(const Arrangement_2& arr, + ColorGenerator color_generator, + const char* title = "2D Arrangement Basic Viewer") { +#if defined(CGAL_TEST_SUITE) + bool cgal_test_suite=true; +#else + bool cgal_test_suite = qEnvironmentVariableIsSet("CGAL_TEST_SUITE"); +#endif + + if (cgal_test_suite) return; + + using Color_generator = ColorGenerator; + using Gt = GeometryTraits_2; + using Arr = CGAL::Arrangement_2; + using Viewer = Arr_2_viewer_qt; + + CGAL::Qt::init_ogl_context(4,3); + + int argc = 1; + const char* argv[2] = {"t2_viewer", nullptr}; + QApplication app(argc, const_cast(argv)); + Viewer mainwindow(app.activeWindow(), arr, color_generator, title); + mainwindow.add_elements(); + mainwindow.show(); + app.exec(); } } From b0b080e65e0d74944305edb164d94e59b860cb8d Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 15 Feb 2023 18:40:04 +0200 Subject: [PATCH 094/105] Replaced use of boost::hana with c++14 features to implement compile-time dispatching --- .../include/CGAL/draw_arrangement_2.h | 262 ++++++++++-------- 1 file changed, 139 insertions(+), 123 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h index ff28ac0c630..56f17e1ec42 100644 --- a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h +++ b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h @@ -28,19 +28,6 @@ #ifdef CGAL_USE_BASIC_VIEWER #include - - -#if defined(BOOST_MSVC) -// workaround for using boost::hana with MSVC without warnings -#pragma push_macro("__cplusplus") -#undef __cplusplus -#define __cplusplus _MSVC_LANG -#include -#pragma pop_macro("__cplusplus") -#else -#include -#endif - #include #include @@ -74,10 +61,6 @@ class Arr_2_basic_viewer_qt : public Basic_viewer_qt { using Ccb_halfedge_const_circulator = typename Arr::Ccb_halfedge_const_circulator; - template - using approximate_2_object_t = - decltype(std::declval().approximate_2_object()); - public: /// Construct the viewer. /// @param arr the arrangement to view @@ -137,37 +120,45 @@ public: template CGAL::Bbox_2 exact_bbox(const Point& p) { return p.bbox(); } - //! Compute the bounding box - CGAL::Bbox_2 bounding_box() { - namespace bh = boost::hana; - auto has_approximate_2_object = - bh::is_valid([](auto&& x) -> decltype(x.approximate_2_object()){}); + /*! Compile time dispatching + */ + template + auto bounding_box_impl2(CGAL::Bbox_2& bbox, const Point& p, T const& approx, + long) -> decltype(void()) + { bbox += exact_bbox(p); } + template + auto bounding_box_impl2(CGAL::Bbox_2& bbox, const Point& p, T const& approx, + int) -> decltype(approx.operator()(p), void()) + { bbox += approximate_bbox(p, approx); } + + template + auto bounding_box_impl1(CGAL::Bbox_2& bbox, const Point& p, T const& traits, + long) -> decltype(void()) + { bbox += exact_bbox(p); } + + template + auto bounding_box_impl1(CGAL::Bbox_2& bbox, const Point& p, T const& traits, + int) -> + decltype(traits.approximate_2_object(), void()) { + using Approximate = typename Gt::Approximate_2; + bounding_box_impl2(bbox, p, traits.approximate_2_object(), 0); + } + + /*! Compute the bounding box. + */ + CGAL::Bbox_2 bounding_box() { + CGAL::Bbox_2 bbox; + const auto* traits = this->m_arr.geometry_traits(); // At this point we assume that the arrangement is not open, and thus the // bounding box is defined by the vertices. - //! The bounding box - CGAL::Bbox_2 bbox; - for (auto it = m_arr.vertices_begin(); it != m_arr.vertices_end(); ++it) { - bh::if_(has_approximate_2_object(Gt{}), - [&](auto& /* x */) { - const auto* traits = this->m_arr.geometry_traits(); - auto approx = traits->approximate_2_object(); - auto has_operator = - bh::is_valid([](auto&& x) -> - decltype(x.operator()(Point{}, int{})){}); - bh::if_(has_operator(approx), - [&](auto& x) - { bbox += x.approximate_bbox(it->point(), approx); }, - [&](auto& x) { bbox += x.exact_bbox(it->point()); } - )(*this); - }, - [&](auto& x) { bbox += x.exact_bbox(it->point()); } - )(*this); - } + for (auto it = m_arr.vertices_begin(); it != m_arr.vertices_end(); ++it) + bounding_box_impl1(bbox, it->point(), *traits, 0); return bbox; } - //! + /*! Add all elements to be drawn. + */ void add_elements() { // std::cout << "ratio: " << this->pixel_ratio() << std::endl; clear(); @@ -258,7 +249,8 @@ protected: } } - //! Draw an exact curve. + /*! Draw an exact curve. + */ template void draw_exact_curve(const XMonotoneCurve& curve) { const auto* traits = this->m_arr.geometry_traits(); @@ -267,21 +259,40 @@ protected: this->add_segment(ctr_min(curve), ctr_max(curve)); } - //! Draw an exact region. + /*! Draw an exact region. + */ void draw_exact_region(Halfedge_const_handle curr) { this->add_point_in_face(curr->source()->point()); draw_exact_curve(curr->curve()); } - //! Utility struct - template - struct can_call_operator_curve { - template - constexpr auto operator()(F&& f) -> - decltype(f.template operator()(X_monotone_curve{}, double{}, T{}, bool{})) {} - }; + /*! Compile time dispatching + */ + template + auto draw_region_impl2(Halfedge_const_handle curr, T const& approx, long) -> + decltype(void()) + { draw_exact_region(curr); } - //! Draw a region. + template + auto draw_region_impl2(Halfedge_const_handle curr, T const& approx, int) -> + decltype(approx.template operator()(X_monotone_curve{}, double{}, I{}, + bool{}), void()) + { draw_approximate_region(curr, approx); } + + template + auto draw_region_impl1(Halfedge_const_handle curr, T const& traits, long) -> + decltype(void()) + { draw_exact_region(curr); } + + template + auto draw_region_impl1(Halfedge_const_handle curr, T const& traits, int) -> + decltype(traits.approximate_2_object(), void()) { + using Approximate = typename Gt::Approximate_2; + draw_region_impl2(curr, traits.approximate_2_object(), 0); + } + + /*! Draw a region. + */ void draw_region(Ccb_halfedge_const_circulator circ) { /* Check whether the traits has a member function called * approximate_2_object() and if so check whether the return type, namely @@ -296,34 +307,19 @@ protected: * C++17 has experimental constructs called is_detected and * is_detected_v that can be used to achieve the same goal. * - * For now we use C++14 features and boost.hana instead. + * For now we use C++14 features. */ - namespace bh = boost::hana; - auto has_approximate_2_object = - bh::is_valid([](auto&& x) -> decltype(x.approximate_2_object()){}); - auto color = m_color_generator(circ->face()); this->face_begin(color); const auto* traits = this->m_arr.geometry_traits(); auto ext = find_smallest(circ); auto curr = ext; + do { // Skip halfedges that are "antenas": while (curr->face() == curr->twin()->face()) curr = curr->twin()->next(); - - bh::if_(has_approximate_2_object(Gt{}), - [&](auto& /* x */) { - auto approx = traits->approximate_2_object(); - auto has_operator = - bh::is_valid(can_call_operator_curve{}); - bh::if_(has_operator(approx), - [&](auto& x) { x.draw_approximate_region(curr, approx); }, - [&](auto& x) { x.draw_exact_region(curr); } - )(*this); - }, - [&](auto& x) { x.draw_exact_region(curr); } - )(*this); + draw_region_impl1(curr, *traits, 0); curr = curr->next(); } while (curr != ext); @@ -348,7 +344,33 @@ protected: for (; it != polyline.end(); prev = it++) this->add_segment(*prev, *it); } - //! Draw a curve. + /*! Compile time dispatching + */ + template + auto draw_curve_impl2(const X_monotone_curve& xcv, T const& approx, long) -> + decltype(void()) + { draw_exact_curve(xcv); } + + template + auto draw_curve_impl2(const X_monotone_curve& xcv, T const& approx, int) -> + decltype(approx.template operator()(X_monotone_curve{}, double{}, I{}, + bool{}), void()) + { draw_approximate_curve(xcv, approx); } + + template + auto draw_curve_impl1(const X_monotone_curve& xcv, T const& traits, long) -> + decltype(void()) + { draw_exact_curve(xcv); } + + template + auto draw_curve_impl1(const X_monotone_curve& xcv, T const& traits, int) -> + decltype(traits.approximate_2_object(), void()) { + using Approximate = typename Gt::Approximate_2; + draw_curve_impl2(xcv, traits.approximate_2_object(), 0); + } + + /*! Draw a curve. + */ template void draw_curve(const XMonotoneCurve& curve) { /* Check whether the traits has a member function called @@ -364,7 +386,7 @@ protected: * C++17 has experimental constructs called is_detected and * is_detected_v that can be used to achieve the same goal. * - * For now we use C++14 features and boost.hana instead. + * For now we use C++14 features. */ #if 0 if constexpr (std::experimental::is_detected_v) @@ -376,56 +398,44 @@ protected: } draw_exact_curve(curve); #else - namespace bh = boost::hana; - auto has_approximate_2_object = - bh::is_valid([](auto&& x) -> decltype(x.approximate_2_object()){}); const auto* traits = this->m_arr.geometry_traits(); - bh::if_(has_approximate_2_object(Gt{}), - [&](auto& /* x */) { - auto approx = traits->approximate_2_object(); - auto has_operator = bh::is_valid(can_call_operator_curve{}); - bh::if_(has_operator(approx), - [&](auto& x) { x.draw_approximate_curve(curve, approx); }, - [&](auto& x) { x.draw_exact_curve(curve); } - )(*this); - }, - [&](auto& x) { x.draw_exact_curve(curve); } - )(*this); + draw_curve_impl1(curve, *traits, 0); #endif } - /*! Add an approximation of a point. - * \param[in] p the (exact) point. - * Call this member function only if the geometry traits is equipped with - * the coordinate-approximation functionality of a point. - * This function must be inlined (e.g., a template) to enable the - * compiled-time dispatching in the function `draw_point()`. + /*! Compile time dispatching */ - template - void draw_approximate_point(const Point& p, const Approximate& approx) - { this->add_point(approx(p)); } + template + auto draw_point_impl2(const Point& p, T const& approx, long) -> + decltype(void()) + { add_point(p); } - //! - void draw_point(const Point& p) { - namespace bh = boost::hana; - auto has_approximate_2_object = - bh::is_valid([](auto&& x) -> decltype(x.approximate_2_object()){}); - bh::if_(has_approximate_2_object(Gt{}), - [&](auto& x) { - const auto* traits = x.m_arr.geometry_traits(); - auto approx = traits->approximate_2_object(); - auto has_operator = - bh::is_valid([](auto&& x) -> decltype(x.operator()(Point{})){}); - bh::if_(has_operator(approx), - [&](auto& x) { x.draw_approximate_point(p, approx); }, - [&](auto& x) { x.add_point(p); } - )(*this); - }, - [&](auto& x) { x.add_point(p); } - )(*this); + template + auto draw_point_impl2(const Point& p, T const& approx, int) -> + decltype(approx.operator()(p), void()) + { add_point(approx(p)); } + + template + auto draw_point_impl1(const Point& p, T const& traits, long) -> + decltype(void()) + { add_point(p); } + + template + auto draw_point_impl1(const Point& p, T const& traits, int) -> + decltype(traits.approximate_2_object(), void()) { + using Approximate = typename Gt::Approximate_2; + draw_point_impl2(p, traits.approximate_2_object(), 0); } - //! + /*! Draw a point. + */ + void draw_point(const Point& p) { + const auto* traits = m_arr.geometry_traits(); + draw_point_impl1(p, *traits, 0); + } + + /*! Add a Connected Component of the Boundary. + */ void add_ccb(Ccb_halfedge_const_circulator circ) { auto curr = circ; do { @@ -436,7 +446,8 @@ protected: } while (++curr != circ); } - //! + /*! Add a face. + */ void add_face(Face_const_handle face) { for (auto it = face->inner_ccbs_begin(); it != face->inner_ccbs_end(); ++it) add_ccb(*it); @@ -504,15 +515,18 @@ public: /// @param title the title of the window Arr_2_viewer_qt(QWidget* parent, const Arr& arr, Color_generator color_generator, - const char* title = "2D Arrangement Basic Viewer") : - Base(parent, arr, color_generator, title) + const char* title = "2D Arrangement Basic Viewer", + bool draw_vertices = false) : + Base(parent, arr, color_generator, title, draw_vertices) {} }; -//! +/*! Draw an arrangement. + */ template void draw(const Arrangement_2& arr, - const char* title = "2D Arrangement Basic Viewer") { + const char* title = "2D Arrangement Basic Viewer", + bool draw_vertices = false) { #if defined(CGAL_TEST_SUITE) bool cgal_test_suite=true; #else @@ -530,18 +544,20 @@ void draw(const Arrangement_2& arr, const char* argv[2] = {"t2_viewer", nullptr}; QApplication app(argc, const_cast(argv)); Default_color_generator color_generator; - Viewer mainwindow(app.activeWindow(), arr, color_generator, title); + Viewer mainwindow(app.activeWindow(), arr, color_generator, title, draw_vertices); mainwindow.add_elements(); mainwindow.show(); app.exec(); } -//! +/*! Draw an arrangement using a given color generator. + */ template void draw(const Arrangement_2& arr, ColorGenerator color_generator, - const char* title = "2D Arrangement Basic Viewer") { + const char* title = "2D Arrangement Basic Viewer", + bool draw_vertices = false) { #if defined(CGAL_TEST_SUITE) bool cgal_test_suite=true; #else @@ -560,7 +576,7 @@ void draw(const Arrangement_2& arr, int argc = 1; const char* argv[2] = {"t2_viewer", nullptr}; QApplication app(argc, const_cast(argv)); - Viewer mainwindow(app.activeWindow(), arr, color_generator, title); + Viewer mainwindow(app.activeWindow(), arr, color_generator, title, draw_vertices); mainwindow.add_elements(); mainwindow.show(); app.exec(); From 2a8100bff6b10b3413f5426018c917cff7d205e5 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 22 Feb 2023 14:49:49 +0200 Subject: [PATCH 095/105] Removed unused variables; Fixed color_generator parameter passing; pacified msvc --- .../include/CGAL/draw_arrangement_2.h | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h index 56f17e1ec42..0c8e5135538 100644 --- a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h +++ b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h @@ -123,8 +123,8 @@ public: /*! Compile time dispatching */ template - auto bounding_box_impl2(CGAL::Bbox_2& bbox, const Point& p, T const& approx, - long) -> decltype(void()) + auto bounding_box_impl2(CGAL::Bbox_2& bbox, const Point& p, T const&, long) + -> decltype(void()) { bbox += exact_bbox(p); } template @@ -133,8 +133,8 @@ public: { bbox += approximate_bbox(p, approx); } template - auto bounding_box_impl1(CGAL::Bbox_2& bbox, const Point& p, T const& traits, - long) -> decltype(void()) + auto bounding_box_impl1(CGAL::Bbox_2& bbox, const Point& p, T const&, long) + -> decltype(void()) { bbox += exact_bbox(p); } template @@ -269,7 +269,7 @@ protected: /*! Compile time dispatching */ template - auto draw_region_impl2(Halfedge_const_handle curr, T const& approx, long) -> + auto draw_region_impl2(Halfedge_const_handle curr, T const&, long) -> decltype(void()) { draw_exact_region(curr); } @@ -280,7 +280,7 @@ protected: { draw_approximate_region(curr, approx); } template - auto draw_region_impl1(Halfedge_const_handle curr, T const& traits, long) -> + auto draw_region_impl1(Halfedge_const_handle curr, T const&, long) -> decltype(void()) { draw_exact_region(curr); } @@ -347,7 +347,7 @@ protected: /*! Compile time dispatching */ template - auto draw_curve_impl2(const X_monotone_curve& xcv, T const& approx, long) -> + auto draw_curve_impl2(const X_monotone_curve& xcv, T const&, long) -> decltype(void()) { draw_exact_curve(xcv); } @@ -358,7 +358,7 @@ protected: { draw_approximate_curve(xcv, approx); } template - auto draw_curve_impl1(const X_monotone_curve& xcv, T const& traits, long) -> + auto draw_curve_impl1(const X_monotone_curve& xcv, T const&, long) -> decltype(void()) { draw_exact_curve(xcv); } @@ -406,8 +406,7 @@ protected: /*! Compile time dispatching */ template - auto draw_point_impl2(const Point& p, T const& approx, long) -> - decltype(void()) + auto draw_point_impl2(const Point& p, T const&, long) -> decltype(void()) { add_point(p); } template @@ -416,8 +415,7 @@ protected: { add_point(approx(p)); } template - auto draw_point_impl1(const Point& p, T const& traits, long) -> - decltype(void()) + auto draw_point_impl1(const Point& p, T const&, long) -> decltype(void()) { add_point(p); } template @@ -449,11 +447,15 @@ protected: /*! Add a face. */ void add_face(Face_const_handle face) { - for (auto it = face->inner_ccbs_begin(); it != face->inner_ccbs_end(); ++it) + using Inner_ccb_const_iterator = typename Arr::Inner_ccb_const_iterator; + using Outer_ccb_const_iterator = typename Arr::Outer_ccb_const_iterator; + + for (Inner_ccb_const_iterator it = face->inner_ccbs_begin(); + it != face->inner_ccbs_end(); ++it) add_ccb(*it); - for (auto it = face->outer_ccbs_begin(); it != face->outer_ccbs_end(); ++it) - { + for (Outer_ccb_const_iterator it = face->outer_ccbs_begin(); + it != face->outer_ccbs_end(); ++it) { add_ccb(*it); draw_region(*it); } @@ -489,7 +491,7 @@ protected: const Arr& m_arr; //! The color generator. - Color_generator& m_color_generator; + Color_generator m_color_generator; std::unordered_map m_visited; }; @@ -544,7 +546,8 @@ void draw(const Arrangement_2& arr, const char* argv[2] = {"t2_viewer", nullptr}; QApplication app(argc, const_cast(argv)); Default_color_generator color_generator; - Viewer mainwindow(app.activeWindow(), arr, color_generator, title, draw_vertices); + Viewer mainwindow(app.activeWindow(), arr, color_generator, title, + draw_vertices); mainwindow.add_elements(); mainwindow.show(); app.exec(); @@ -576,7 +579,8 @@ void draw(const Arrangement_2& arr, int argc = 1; const char* argv[2] = {"t2_viewer", nullptr}; QApplication app(argc, const_cast(argv)); - Viewer mainwindow(app.activeWindow(), arr, color_generator, title, draw_vertices); + Viewer mainwindow(app.activeWindow(), arr, color_generator, title, + draw_vertices); mainwindow.add_elements(); mainwindow.show(); app.exec(); From 77141601beb545619ead965872229eb9e8b56fed Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 22 Feb 2023 15:01:58 +0200 Subject: [PATCH 096/105] Removed unused variable --- .../Arrangement_on_surface_2/ArrangementPainterOstream.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementPainterOstream.cpp b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementPainterOstream.cpp index 814820208ff..2ea11fd5d49 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementPainterOstream.cpp +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementPainterOstream.cpp @@ -43,12 +43,8 @@ template ArrangementPainterOstream>& ArrangementPainterOstream>:: operator<<(const X_monotone_curve_2& curve) { - int cnt = 0; - for (auto it = curve.subcurves_begin(); it != curve.subcurves_end(); ++it) { - ++cnt; + for (auto it = curve.subcurves_begin(); it != curve.subcurves_end(); ++it) this->painterOstream << *it; - } - return *this; } From 1277bd141adaf1f35dcce3a4d0552d6cab18ddf0 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 22 Feb 2023 15:02:21 +0200 Subject: [PATCH 097/105] Added color generator --- .../Arrangement_on_surface_2/draw_arr.cpp | 75 ++++++++++++++++++- 1 file changed, 73 insertions(+), 2 deletions(-) diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/draw_arr.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/draw_arr.cpp index 6d6874f872a..6a63425e6e7 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/draw_arr.cpp +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/draw_arr.cpp @@ -6,9 +6,72 @@ using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel; using Traits = CGAL::Arr_segment_traits_2; using Point = Traits::Point_2; -using X_monotone_curve = Traits::X_monotone_curve_2; using Arrangement_2 = CGAL::Arrangement_2; +/*! Convert HSV to RGB color space + * Converts a given set of HSV values `h', `s', `v' into RGB coordinates. + * The output RGB values are in the range [0, 255], and the input HSV values + * are in the ranges h = [0, 360], and s, v = [0, 1], respectively. + * + * \param hue Hue component range: [0, 360] + * \param sat Saturation component range: [0, 1] + * \param value Value component range: [0, 1] + * \return tuple, where each component is in the range [0, 255] +*/ +std::tuple +hsv_to_rgb(float hue, float sat, float value) { + float red, green, blue; + float fc = value * sat; // Chroma + float hue_prime = fmod(hue / 60.0, 6); + float fx = fc * (1.0 - fabs(fmod(hue_prime, 2) - 1.0)); + float fm = value - fc; + + if(0 <= hue_prime && hue_prime < 1) { + red = fc; + green = fx; + blue = 0; + } + else if(1 <= hue_prime && hue_prime < 2) { + red = fx; + green = fc; + blue = 0; + } + else if(2 <= hue_prime && hue_prime < 3) { + red = 0; + green = fc; + blue = fx; + } + else if(3 <= hue_prime && hue_prime < 4) { + red = 0; + green = fx; + blue = fc; + } + else if(4 <= hue_prime && hue_prime < 5) { + red = fx; + green = 0; + blue = fc; + } + else if(5 <= hue_prime && hue_prime < 6) { + red = fc; + green = 0; + blue = fx; + } + else { + red = 0; + green = 0; + blue = 0; + } + + red += fm; + green += fm; + blue += fm; + + red *= 255; + green *= 255; + blue *= 255; + return std::make_tuple(red, green, blue); +} + int main() { Traits traits; Arrangement_2 arr(&traits); @@ -33,7 +96,15 @@ int main() { << arr.number_of_edges() << ", " << arr.number_of_faces() << std::endl; - CGAL::draw(arr); + std::size_t id(0); + CGAL::draw(arr, [&] (Arrangement_2::Face_const_handle fh) -> CGAL::IO::Color { + float h = 360.0 * id++ / arr.number_of_faces(); + float s = 0.5; + float v = 0.5; + float r, g, b; + std::tie(r, g, b) = hsv_to_rgb(h, s, v); + return CGAL::IO::Color(r, g, b); + }); return EXIT_SUCCESS; } From ba3d648bf72729da802f806409ec1bd4978d3cbb Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Tue, 28 Feb 2023 13:01:14 +0200 Subject: [PATCH 098/105] removed unused parameter and overode the default parameter in the draw() call. --- .../examples/Arrangement_on_surface_2/draw_arr.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/draw_arr.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/draw_arr.cpp index 6a63425e6e7..ea99cca39a8 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/draw_arr.cpp +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/draw_arr.cpp @@ -97,14 +97,14 @@ int main() { << arr.number_of_faces() << std::endl; std::size_t id(0); - CGAL::draw(arr, [&] (Arrangement_2::Face_const_handle fh) -> CGAL::IO::Color { + CGAL::draw(arr, [&] (Arrangement_2::Face_const_handle) -> CGAL::IO::Color { float h = 360.0 * id++ / arr.number_of_faces(); float s = 0.5; float v = 0.5; float r, g, b; std::tie(r, g, b) = hsv_to_rgb(h, s, v); return CGAL::IO::Color(r, g, b); - }); + }, "hsv colors", true); return EXIT_SUCCESS; } From 3e07f88ab586507b566d5fb4a6c6acae1834cd83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 24 Apr 2023 12:01:17 +0200 Subject: [PATCH 099/105] catch more --- GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h index 3c7b05082b9..37873145733 100644 --- a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h +++ b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h @@ -1816,8 +1816,8 @@ protected: namespace CGAL { - template - void draw(const T&, const char* ="", bool=false) + template + void draw(T...) { std::cerr<<"Impossible to draw, CGAL_USE_BASIC_VIEWER is not defined."< Date: Wed, 26 Apr 2023 19:32:43 +0300 Subject: [PATCH 100/105] Implemented and alternative for compile time dispatching, which might work with MSVC 14. --- .../include/CGAL/draw_arrangement_2.h | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h index 0c8e5135538..a5b65fda0be 100644 --- a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h +++ b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h @@ -405,6 +405,7 @@ protected: /*! Compile time dispatching */ +#if 0 template auto draw_point_impl2(const Point& p, T const&, long) -> decltype(void()) { add_point(p); } @@ -422,14 +423,31 @@ protected: auto draw_point_impl1(const Point& p, T const& traits, int) -> decltype(traits.approximate_2_object(), void()) { using Approximate = typename Gt::Approximate_2; - draw_point_impl2(p, traits.approximate_2_object(), 0); + draw_point_impl2(p, traits.approximate_2_object(), true); } +#else + template + void draw_point_impl2(const Point& p, T const&, ...) { add_point(p); } + + template + void draw_point_impl2(const Point& p, T const& traits, bool) { + auto approx = traits.approximate_2_object(); + add_point(approx(p)); + } + + template + void draw_point_impl1(const Point& p, T const&, ...) { add_point(p); } + + template + void draw_point_impl1(const Point& p, T const& traits, bool) + { draw_point_impl2(p, traits, true); } +#endif /*! Draw a point. */ void draw_point(const Point& p) { const auto* traits = m_arr.geometry_traits(); - draw_point_impl1(p, *traits, 0); + draw_point_impl1(p, *traits, true); } /*! Add a Connected Component of the Boundary. From ef7b62119b595b7219a67b1c612d78aa92aed782 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Thu, 27 Apr 2023 13:31:10 +0300 Subject: [PATCH 101/105] Add member operator() to Approximate() for point and segment approximation and used it to remove the compile-time-dispatching all together in the drawing function --- .../Arr_non_caching_segment_basic_traits_2.h | 61 +++++++++++++------ .../include/CGAL/Arr_segment_traits_2.h | 46 ++++++++++++-- .../include/CGAL/draw_arrangement_2.h | 59 +++++++++--------- 3 files changed, 115 insertions(+), 51 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_non_caching_segment_basic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_non_caching_segment_basic_traits_2.h index 1190c3e1085..60964a1e46b 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_non_caching_segment_basic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_non_caching_segment_basic_traits_2.h @@ -30,6 +30,7 @@ * functors required by the concept it models. */ +#include #include #include #include @@ -230,37 +231,63 @@ public: /// \name Functor definitions for the landmarks point-location strategy. //@{ - typedef double Approximate_number_type; + typedef double Approximate_number_type; + typedef CGAL::Cartesian Approximate_kernel; + typedef Approximate_kernel::Point_2 Approximate_point_2; + + class Approximate_2 { + protected: + using Traits = Arr_non_caching_segment_basic_traits_2; + + /*! The traits (in case it has state) */ + const Traits& m_traits; + + /*! Constructor + * \param traits the traits. + */ + Approximate_2(const Traits& traits) : m_traits(traits) {} + + friend class Arr_non_caching_segment_basic_traits_2; - class Approximate_2 - { public: - - /*! - * Return an approximation of a point coordinate. + /*! Return an approximation of a point coordinate. * \param p The exact point. * \param i The coordinate index (either 0 or 1). * \pre i is either 0 or 1. * \return An approximation of p's x-coordinate (if i == 0), or an * approximation of p's y-coordinate (if i == 1). */ - Approximate_number_type operator() (const Point_2& p, - int i) const - { + Approximate_number_type operator() (const Point_2& p, int i) const { CGAL_precondition (i == 0 || i == 1); + return (i == 0) ? (CGAL::to_double(p.x())) : (CGAL::to_double(p.y())); + } - if (i == 0) - return (CGAL::to_double(p.x())); - else - return (CGAL::to_double(p.y())); + /*! Obtain an approximation of a point. + */ + Approximate_point_2 operator()(const Point_2& p) const + { return Approximate_point_2(operator()(p, 0), operator()(p, 1)); } + + /*! Obtain an approximation of an \f$x\f$-monotone curve. + */ + template + OutputIterator operator()(const X_monotone_curve_2& xcv, double error, + OutputIterator oi, bool l2r = true) const { + auto min_vertex = m_traits.construct_min_vertex_2_object(); + auto max_vertex = m_traits.construct_max_vertex_2_object(); + const auto& src = (l2r) ? min_vertex(xcv) : max_vertex(xcv); + const auto& trg = (l2r) ? max_vertex(xcv) : min_vertex(xcv); + auto xs = CGAL::to_double(src.x()); + auto ys = CGAL::to_double(src.y()); + auto xt = CGAL::to_double(trg.x()); + auto yt = CGAL::to_double(trg.y()); + *oi++ = Approximate_point_2(xs, ys); + *oi++ = Approximate_point_2(xt, yt); + return oi; } }; /*! Get an Approximate_2 functor object. */ - Approximate_2 approximate_2_object () const - { - return Approximate_2(); - } + Approximate_2 approximate_2_object () const { return Approximate_2(*this); } typedef typename Kernel::Construct_segment_2 Construct_x_monotone_curve_2; diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h index 1e3b908faa6..b973e20d62f 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -879,9 +880,24 @@ public: /// \name Functor definitions for the landmarks point-location strategy. //@{ - typedef double Approximate_number_type; + typedef double Approximate_number_type; + typedef CGAL::Cartesian Approximate_kernel; + typedef Approximate_kernel::Point_2 Approximate_point_2; class Approximate_2 { + protected: + using Traits = Arr_segment_traits_2; + + /*! The traits (in case it has state) */ + const Traits& m_traits; + + /*! Constructor + * \param traits the traits. + */ + Approximate_2(const Traits& traits) : m_traits(traits) {} + + friend class Arr_segment_traits_2; + public: /*! Obtain an approximation of a point coordinate. * \param p the exact point. @@ -890,15 +906,37 @@ public: * \return An approximation of p's x-coordinate (if i == 0), or an * approximation of p's y-coordinate (if i == 1). */ - Approximate_number_type operator()(const Point_2& p, int i) const - { + Approximate_number_type operator()(const Point_2& p, int i) const { CGAL_precondition((i == 0) || (i == 1)); return (i == 0) ? (CGAL::to_double(p.x())) : (CGAL::to_double(p.y())); } + + /*! Obtain an approximation of a point. + */ + Approximate_point_2 operator()(const Point_2& p) const + { return Approximate_point_2(operator()(p, 0), operator()(p, 1)); } + + /*! Obtain an approximation of an \f$x\f$-monotone curve. + */ + template + OutputIterator operator()(const X_monotone_curve_2& xcv, double error, + OutputIterator oi, bool l2r = true) const { + auto min_vertex = m_traits.construct_min_vertex_2_object(); + auto max_vertex = m_traits.construct_max_vertex_2_object(); + const auto& src = (l2r) ? min_vertex(xcv) : max_vertex(xcv); + const auto& trg = (l2r) ? max_vertex(xcv) : min_vertex(xcv); + auto xs = CGAL::to_double(src.x()); + auto ys = CGAL::to_double(src.y()); + auto xt = CGAL::to_double(trg.x()); + auto yt = CGAL::to_double(trg.y()); + *oi++ = Approximate_point_2(xs, ys); + *oi++ = Approximate_point_2(xt, yt); + return oi; + } }; /*! Obtain an Approximate_2 functor object. */ - Approximate_2 approximate_2_object() const { return Approximate_2(); } + Approximate_2 approximate_2_object() const { return Approximate_2(*this); } //! Functor class Construct_x_monotone_curve_2 { diff --git a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h index a5b65fda0be..7bdee98fb53 100644 --- a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h +++ b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h @@ -122,9 +122,9 @@ public: /*! Compile time dispatching */ +#if 0 template - auto bounding_box_impl2(CGAL::Bbox_2& bbox, const Point& p, T const&, long) - -> decltype(void()) + void bounding_box_impl2(CGAL::Bbox_2& bbox, const Point& p, T const&, long) { bbox += exact_bbox(p); } template @@ -133,8 +133,7 @@ public: { bbox += approximate_bbox(p, approx); } template - auto bounding_box_impl1(CGAL::Bbox_2& bbox, const Point& p, T const&, long) - -> decltype(void()) + void bounding_box_impl1(CGAL::Bbox_2& bbox, const Point& p, T const&, long) { bbox += exact_bbox(p); } template @@ -144,6 +143,12 @@ public: using Approximate = typename Gt::Approximate_2; bounding_box_impl2(bbox, p, traits.approximate_2_object(), 0); } +#else + template + void bounding_box_impl1(CGAL::Bbox_2& bbox, const Point& p, T const& traits, + int) + { bbox += approximate_bbox(p, traits.approximate_2_object()); } +#endif /*! Compute the bounding box. */ @@ -268,9 +273,9 @@ protected: /*! Compile time dispatching */ +#if 0 template - auto draw_region_impl2(Halfedge_const_handle curr, T const&, long) -> - decltype(void()) + void draw_region_impl2(Halfedge_const_handle curr, T const&, long) { draw_exact_region(curr); } template @@ -280,8 +285,7 @@ protected: { draw_approximate_region(curr, approx); } template - auto draw_region_impl1(Halfedge_const_handle curr, T const&, long) -> - decltype(void()) + void draw_region_impl1(Halfedge_const_handle curr, T const&, long) { draw_exact_region(curr); } template @@ -290,6 +294,11 @@ protected: using Approximate = typename Gt::Approximate_2; draw_region_impl2(curr, traits.approximate_2_object(), 0); } +#else + template + void draw_region_impl1(Halfedge_const_handle curr, T const& traits, int) + { draw_approximate_region(curr, traits.approximate_2_object()); } +#endif /*! Draw a region. */ @@ -346,9 +355,9 @@ protected: /*! Compile time dispatching */ +#if 0 template - auto draw_curve_impl2(const X_monotone_curve& xcv, T const&, long) -> - decltype(void()) + void draw_curve_impl2(const X_monotone_curve& xcv, T const&, long) { draw_exact_curve(xcv); } template @@ -358,8 +367,7 @@ protected: { draw_approximate_curve(xcv, approx); } template - auto draw_curve_impl1(const X_monotone_curve& xcv, T const&, long) -> - decltype(void()) + void draw_curve_impl1(const X_monotone_curve& xcv, T const&, long) { draw_exact_curve(xcv); } template @@ -368,6 +376,11 @@ protected: using Approximate = typename Gt::Approximate_2; draw_curve_impl2(xcv, traits.approximate_2_object(), 0); } +#else + template + void draw_curve_impl1(const X_monotone_curve& xcv, T const& traits, int) + { draw_approximate_curve(xcv, traits.approximate_2_object()); } +#endif /*! Draw a curve. */ @@ -407,8 +420,7 @@ protected: */ #if 0 template - auto draw_point_impl2(const Point& p, T const&, long) -> decltype(void()) - { add_point(p); } + void draw_point_impl2(const Point& p, T const&, long) { add_point(p); } template auto draw_point_impl2(const Point& p, T const& approx, int) -> @@ -416,8 +428,7 @@ protected: { add_point(approx(p)); } template - auto draw_point_impl1(const Point& p, T const&, long) -> decltype(void()) - { add_point(p); } + void draw_point_impl1(const Point& p, T const&, long) { add_point(p); } template auto draw_point_impl1(const Point& p, T const& traits, int) -> @@ -427,20 +438,8 @@ protected: } #else template - void draw_point_impl2(const Point& p, T const&, ...) { add_point(p); } - - template - void draw_point_impl2(const Point& p, T const& traits, bool) { - auto approx = traits.approximate_2_object(); - add_point(approx(p)); - } - - template - void draw_point_impl1(const Point& p, T const&, ...) { add_point(p); } - - template - void draw_point_impl1(const Point& p, T const& traits, bool) - { draw_point_impl2(p, traits, true); } + void draw_point_impl1(const Point& p, T const& traits, int) + { add_point(traits.approximate_2_object()(p)); } #endif /*! Draw a point. From f6db4a6d947776a24b48302770c9c16436b01363 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Thu, 27 Apr 2023 14:02:29 +0300 Subject: [PATCH 102/105] Fixed argument to draw_point_imp1() --- Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h index 7bdee98fb53..c7637f04b91 100644 --- a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h +++ b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h @@ -446,7 +446,7 @@ protected: */ void draw_point(const Point& p) { const auto* traits = m_arr.geometry_traits(); - draw_point_impl1(p, *traits, true); + draw_point_impl1(p, *traits, 0); } /*! Add a Connected Component of the Boundary. From 141731ec79eb20d5b7b0c4572acb4cf01f556d62 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Tue, 2 May 2023 09:58:18 +0300 Subject: [PATCH 103/105] Fixed Approximate_2 --- .../CGAL/Arr_polycurve_basic_traits_2.h | 83 ++++++++++--------- .../include/CGAL/Arr_polyline_traits_2.h | 57 ++++++++++++- 2 files changed, 101 insertions(+), 39 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_polycurve_basic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_polycurve_basic_traits_2.h index 0824ddf9e02..56b0a849627 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_polycurve_basic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_polycurve_basic_traits_2.h @@ -1088,59 +1088,67 @@ public: // ArrangementLandmarkTraits concept. //@{ -#if 0 - // The following block assumes that the subcurve traits template parameter - // is a model of the ArrangementLandmarkTraits concept; in other words, it - // defines the nested types Approximate_number_type and Approximate_2 and - // the member function approximate_2_object(). It cannot be used as is if - // the subcurve traits does not model the ArrangementLandmarkTraits concept. - // The functor Construct_x_monotone_curve_2 is provided regardless of the - // subcurve traits. - - typedef typename Subcurve_traits_2::Approximate_number_type - Approximate_number_type; - typedef typename Subcurve_traits_2::Approximate_2 Approximate_2; - - /*! Obtain an Approximate_2 functor object. */ - Approximate_2 approximate_2_object() const - { return subcurve_traits_2()->approximate_2_object(); } -#else // The following block defines the nested types Approximate_number_type and // Approximate_2 and the member function approximate_2_object() based on the // corresponding types and function definitions of the subcurve traits. If // the subcurve traits does not provide these definitions, they are defined - // as dummies. Essentially, the polycurve traits becomes a practical model of - // the ArrangementLandmarkTraits concept only if the subcurve traits is a - // model of this concept. + // as dummies. Essentially, the polycurve traits becomes a model of the + // ArrangementLandmarkTraits concept only if the subcurve traits is a model + // of this concept. // // The following implementation is inspired by // https://stackoverflow.com/a/11816999/1915421 template - struct Void { - typedef void type; - }; + struct Void { typedef void type; }; template struct has_approximate_2 { // Generic implementation - typedef void Approximate_number_type; - typedef void Approximate_2; + using Approximate_number_type = void; + using Approximate_point_2 = void; + + struct Approximate_2 { + /*! Obtain an approximation of a point coordinate. + * \param p the exact point. + * \param i the coordinate index (either 0 or 1). + * \pre i is either 0 or 1. + * \return An approximation of p's x-coordinate (if i == 0), or an + * approximation of p's y-coordinate (if i == 1). + */ + Approximate_number_type operator()(const Point_2& p, int i) const + { CGAL_error_msg("The subtraits does not define Approximate_2!"); } + + /*! Obtain an approximation of a point. + */ + Approximate_point_2 operator()(const Point_2& p) const + { CGAL_error_msg("The subtraits does not define Approximate_2!"); } + + /*! Obtain an approximation of an \f$x\f$-monotone curve. + */ + template + OutputIterator operator()(const X_monotone_curve_2& xcv, double error, + OutputIterator oi, bool l2r = true) const { + CGAL_error_msg("The subtraits does not define Approximate_2!"); + return oi; + } + }; }; template - struct has_approximate_2::type> - { + struct has_approximate_2::type> { // Specialization for types holding a nested type T::Approximate_2 - typedef typename T::Approximate_number_type - Approximate_number_type; - typedef typename T::Approximate_2 Approximate_2; + using Approximate_number_type = typename T::Approximate_number_type; + using Approximate_2 = typename T::Approximate_2; + using Approximate_point_2 = typename T::Approximate_point_2; }; - typedef typename has_approximate_2::Approximate_number_type - Approximate_number_type; - typedef typename has_approximate_2::Approximate_2 - Approximate_2; + using Approximate_number_type = + typename has_approximate_2::Approximate_number_type; + using Approximate_2 = + typename has_approximate_2::Approximate_2; + using Approximate_point_2 = + typename has_approximate_2::Approximate_point_2; /*! Obtain an Approximate_2 functor object. */ Approximate_2 approximate_2_object_impl(std::false_type) const @@ -1148,13 +1156,12 @@ public: Approximate_2 approximate_2_object_impl(std::true_type) const { } - Approximate_2 approximate_2_object() const - { - typedef typename std::is_same::type Is_void; + Approximate_2 approximate_2_object() const { + using Is_void = typename std::is_same::type; return approximate_2_object_impl(Is_void()); } -#endif + // class Construct_x_monotone_curve_2 { protected: typedef Arr_polycurve_basic_traits_2 diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_polyline_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_polyline_traits_2.h index f2f7fe7c8e2..a2f0acbd721 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_polyline_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_polyline_traits_2.h @@ -98,7 +98,6 @@ public: typedef typename Base::Equal_2 Equal_2; typedef typename Base::Compare_endpoints_xy_2 Compare_endpoints_xy_2; typedef typename Base::Construct_opposite_2 Construct_opposite_2; - typedef typename Base::Approximate_2 Approximate_2; typedef typename Base::Parameter_space_in_x_2 Parameter_space_in_x_2; typedef typename Base::Parameter_space_in_y_2 Parameter_space_in_y_2; typedef typename Base::Compare_x_on_boundary_2 Compare_x_on_boundary_2; @@ -595,6 +594,62 @@ public: Construct_x_monotone_curve_2 construct_x_monotone_curve_2_object() const { return Construct_x_monotone_curve_2(*this); } + // + using Approximate_number_type = typename Base::Approximate_number_type; + using Approximate_point_2 = typename Base::Approximate_point_2; + + class Approximate_2 : public Base::Approximate_2 { + protected: + using Traits = Arr_polyline_traits_2; + + /*! The traits (in case it has state) */ + const Traits& m_traits; + + /*! Constructor + * \param traits the traits. + */ + Approximate_2(const Traits& traits) : + Base::Approximate_2(*(traits.subcurve_traits_2())), + m_traits(traits) + {} + + friend class Arr_polyline_traits_2; + + public: + Approximate_number_type operator()(const Point_2& p, int i) const + { return Base::Approximate_2::operator()(p, i); } + + Approximate_point_2 operator()(const Point_2& p) const + { return Base::Approximate_2::operator()(p); } + + /*! Obtain an approximation of an \f$x\f$-monotone curve. + */ + template + OutputIterator operator()(const X_monotone_curve_2& xcv, double error, + OutputIterator oi, bool l2r = true) const { + if (l2r) { + for (auto it = xcv.points_begin(); it != xcv.points_end(); ++it) { + const auto& p = *it; + auto x = CGAL::to_double(p.x()); + auto y = CGAL::to_double(p.y()); + *oi++ = Approximate_point_2(x, y); + } + return oi; + } + + for (auto it = xcv.points_rbegin(); it != xcv.points_rend(); ++it) { + const auto& p = *it; + auto x = CGAL::to_double(p.x()); + auto y = CGAL::to_double(p.y()); + *oi++ = Approximate_point_2(x, y); + } + return oi; + } + }; + + /*! Obtain an Approximate_2 functor object. */ + Approximate_2 approximate_2_object() const { return Approximate_2(*this); } + /*! Deprecated! * Obtain the segment traits. * \return the segment traits. From 92bc3de2deaf48356c39042c3b87522fa6925487 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Fri, 5 May 2023 18:43:10 +0300 Subject: [PATCH 104/105] Fixed Approximate_2 for the geodesic traits. Fixed unused formal variables. --- .../Arr_geodesic_arc_on_sphere_traits_2.h | 24 +++++++++++++++---- .../CGAL/Arr_polycurve_basic_traits_2.h | 15 ++++++------ .../include/CGAL/Arr_polyline_traits_2.h | 2 +- .../include/CGAL/Arr_segment_traits_2.h | 2 +- 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geodesic_arc_on_sphere_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geodesic_arc_on_sphere_traits_2.h index 1468d38bc67..4ade2a45fe2 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geodesic_arc_on_sphere_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geodesic_arc_on_sphere_traits_2.h @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -2834,11 +2835,12 @@ public: /// \name Functor definitions for the landmarks point-location strategy. //@{ - typedef double Approximate_number_type; + typedef double Approximate_number_type; + typedef CGAL::Cartesian Approximate_kernel; + typedef Approximate_kernel::Point_2 Approximate_point_2; class Approximate_2 { public: - /*! Return an approximation of a point coordinate. * \param p the exact point. * \param i the coordinate index (either 0 or 1). @@ -2846,11 +2848,23 @@ public: * \return an approximation of p's x-coordinate (if i == 0), or an * approximation of p's y-coordinate (if i == 1). */ - Approximate_number_type operator()(const Point_2& p, int i) const - { - CGAL_precondition(i == 0 || i == 1); + Approximate_number_type operator()(const Point_2& p, int i) const { + CGAL_precondition((i == 0) || (i == 1)); return (i == 0) ? CGAL::to_double(p.x()) : CGAL::to_double(p.y()); } + + /*! Obtain an approximation of a point. + */ + Approximate_point_2 operator()(const Point_2& p) const + { return Approximate_point_2(operator()(p, 0), operator()(p, 1)); } + + /*! Obtain an approximation of an \f$x\f$-monotone curve. + */ + template + OutputIterator operator()(const X_monotone_curve_2& xcv, double error, + OutputIterator oi, bool l2r = true) const { + CGAL_error_msg("Not implemented yet!"); + } }; /*! Obtain an Approximate_2 function object */ diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_polycurve_basic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_polycurve_basic_traits_2.h index 56b0a849627..84c9cee01d9 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_polycurve_basic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_polycurve_basic_traits_2.h @@ -1099,10 +1099,9 @@ public: // The following implementation is inspired by // https://stackoverflow.com/a/11816999/1915421 - template - struct Void { typedef void type; }; + template using void_t = void; - template + template struct has_approximate_2 { // Generic implementation using Approximate_number_type = void; @@ -1116,19 +1115,19 @@ public: * \return An approximation of p's x-coordinate (if i == 0), or an * approximation of p's y-coordinate (if i == 1). */ - Approximate_number_type operator()(const Point_2& p, int i) const + Approximate_number_type operator()(const Point_2&, int) const { CGAL_error_msg("The subtraits does not define Approximate_2!"); } /*! Obtain an approximation of a point. */ - Approximate_point_2 operator()(const Point_2& p) const + Approximate_point_2 operator()(const Point_2&) const { CGAL_error_msg("The subtraits does not define Approximate_2!"); } /*! Obtain an approximation of an \f$x\f$-monotone curve. */ template - OutputIterator operator()(const X_monotone_curve_2& xcv, double error, - OutputIterator oi, bool l2r = true) const { + OutputIterator operator()(const X_monotone_curve_2&, double, + OutputIterator oi, bool = true) const { CGAL_error_msg("The subtraits does not define Approximate_2!"); return oi; } @@ -1136,7 +1135,7 @@ public: }; template - struct has_approximate_2::type> { + struct has_approximate_2> { // Specialization for types holding a nested type T::Approximate_2 using Approximate_number_type = typename T::Approximate_number_type; using Approximate_2 = typename T::Approximate_2; diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_polyline_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_polyline_traits_2.h index a2f0acbd721..be6fb987894 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_polyline_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_polyline_traits_2.h @@ -625,7 +625,7 @@ public: /*! Obtain an approximation of an \f$x\f$-monotone curve. */ template - OutputIterator operator()(const X_monotone_curve_2& xcv, double error, + OutputIterator operator()(const X_monotone_curve_2& xcv, double /* error */, OutputIterator oi, bool l2r = true) const { if (l2r) { for (auto it = xcv.points_begin(); it != xcv.points_end(); ++it) { diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h index b973e20d62f..e4828c134c4 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h @@ -919,7 +919,7 @@ public: /*! Obtain an approximation of an \f$x\f$-monotone curve. */ template - OutputIterator operator()(const X_monotone_curve_2& xcv, double error, + OutputIterator operator()(const X_monotone_curve_2& xcv, double /* error */, OutputIterator oi, bool l2r = true) const { auto min_vertex = m_traits.construct_min_vertex_2_object(); auto max_vertex = m_traits.construct_max_vertex_2_object(); From 1c277cdb062bf7824ee13c8147b55a8c24b82a73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 9 May 2023 18:38:16 +0200 Subject: [PATCH 105/105] fix warnings --- .../include/CGAL/Arr_geodesic_arc_on_sphere_traits_2.h | 4 ++-- .../include/CGAL/Arr_non_caching_segment_basic_traits_2.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geodesic_arc_on_sphere_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geodesic_arc_on_sphere_traits_2.h index 4ade2a45fe2..c87b4a357e7 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geodesic_arc_on_sphere_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geodesic_arc_on_sphere_traits_2.h @@ -2861,8 +2861,8 @@ public: /*! Obtain an approximation of an \f$x\f$-monotone curve. */ template - OutputIterator operator()(const X_monotone_curve_2& xcv, double error, - OutputIterator oi, bool l2r = true) const { + OutputIterator operator()(const X_monotone_curve_2& /* xcv */, double /* error */, + OutputIterator /* oi */, bool /* l2r */ = true) const { CGAL_error_msg("Not implemented yet!"); } }; diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_non_caching_segment_basic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_non_caching_segment_basic_traits_2.h index 60964a1e46b..f394e3adf86 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_non_caching_segment_basic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_non_caching_segment_basic_traits_2.h @@ -270,7 +270,7 @@ public: /*! Obtain an approximation of an \f$x\f$-monotone curve. */ template - OutputIterator operator()(const X_monotone_curve_2& xcv, double error, + OutputIterator operator()(const X_monotone_curve_2& xcv, double /* error */, OutputIterator oi, bool l2r = true) const { auto min_vertex = m_traits.construct_min_vertex_2_object(); auto max_vertex = m_traits.construct_max_vertex_2_object();