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 6c26e4c1eba..4869f43a525 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 @@ -6841,9 +6841,9 @@ arrangement-with-history from a file: \cgalExample{Arrangement_on_surface_2/io_curve_history.cpp} \cgalAdvancedBegin -The arrangement package also includes the free functions `write(arr, -os, formatter)` and `read(arr, os, formatter)` that operate on a given -arrangement-with-history instance `arr`. Both functions are +The arrangement package also includes the free functions +`write(arr, os, formatter)` and `read(arr, os, formatter)` that operate +on a given arrangement-with-history instance `arr`. Both functions are parameterized by a `formatter` object, which defines the I/O format. The package contains a template called, `Arr_with_hist_text_formatter`, which extends an @@ -6855,12 +6855,24 @@ and defines a simple textual input/output format. \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. +An arrangement data structure can be visualized by calling one of the +\link PkgArrangementOnSurface2Draw `CGAL::draw()` \endlink +overloaded template functions. Every variant opens a new window +showing the given arrangement. A call to any \link +PkgArrangementOnSurface2Draw `CGAL::draw()` \endlink function is +blocking; that is, the program continues execution only after the user +closes the window. The most simple variant accepts the arrangement to +draw and an optional string used as the title of the window. In the +following example we exploit a variant that also accepts an object the +type of which is an instance of the class template +`Graphics_scene_options`. It allows us to tune the drawings. \cgalExample{Arrangement_on_surface_2/draw_arr.cpp} -This function requires `CGAL_Qt6`, 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_Qt6` and add the definition `CGAL_USE_BASIC_VIEWER`. +This function requires `CGAL_Qt6`, 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_Qt6` 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 @@ -6868,6 +6880,10 @@ A snapshot of the window created by the program of 14 vertices, 15 edges, and 3 faces. Notice that the colors are generated at random. \cgalFigureEnd +Another pair of overloaded \link PkgArrangementOnSurface2Draw +`CGAL::draw()` \endlink functions also accept a bounding box. Each +of these two variants can be ised to draw arrangements induced by +unbounded curves. \section aos_sec-bgl Adapting to Boost Graphs diff --git a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arr_circle_segment_traits_2.h b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arr_circle_segment_traits_2.h index 88b0fc1dc2b..c05c6e2b3a1 100644 --- a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arr_circle_segment_traits_2.h +++ b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arr_circle_segment_traits_2.h @@ -32,7 +32,7 @@ namespace CGAL { * same direction as a precondition. Moreover, `Arr_circle_segment_traits_2` * supports the merging of curves of opposite directions. * - * \cgalModels{AosTraits_2,AosApproximateTraits_2,AosDirectionalXMonotoneTraits_2} + * \cgalModels{AosTraits_2,AosApproximateTraits_2,AosApproximatePointTraits_2,AosDirectionalXMonotoneTraits_2} * */ template 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 33a5f127a31..613942f9e75 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 @@ -80,7 +80,7 @@ namespace CGAL { * to have the same direction as a precondition. Moreover, `Arr_conic_traits_2` * supports the merging of curves of opposite directions. * - * \cgalModels{AosTraits_2,AosLandmarkTraits_2,AosApproximateTraits_2,AosDirectionalXMonotoneTraits_2} + * \cgalModels{AosTraits_2,AosLandmarkTraits_2,AosApproximateTraits_2,AosApproximatePointTraits_2,AosDirectionalXMonotoneTraits_2} * * \cgalHeading{Types} */ diff --git a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arr_linear_traits_2.h b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arr_linear_traits_2.h index 8a26dc62256..d46569f0e12 100644 --- a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arr_linear_traits_2.h +++ b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arr_linear_traits_2.h @@ -21,7 +21,7 @@ namespace CGAL { * we can find out its actual type and convert it to the respective kernel * object (say, to a `Kernel::Ray_2`). * - * \cgalModels{AosTraits_2,AosLandmarkTraits_2,AosOpenBoundaryTraits_2} + * \cgalModels{AosTraits_2,AosLandmarkTraits_2,AosOpenBoundaryTraits_2,AosApproximatePointTraits_2,AosApproximateTraits_2,AosApproximateUnboundedTraits_2} */ template class Arr_linear_traits_2 { diff --git a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arr_segment_traits_2.h b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arr_segment_traits_2.h index 3d2826da6f5..5a4db7d2735 100644 --- a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arr_segment_traits_2.h +++ b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arr_segment_traits_2.h @@ -52,7 +52,7 @@ namespace CGAL { * same direction as a precondition. Moreover, `Arr_segment_traits_2` supports * the merging of curves of opposite directions. * - * \cgalModels{AosTraits_2,AosLandmarkTraits_2,AosApproximateTraits_2,AosDirectionalXMonotoneTraits_2} + * \cgalModels{AosTraits_2,AosLandmarkTraits_2,AosApproximateTraits_2,AosApproximatePointTraits_2,AosDirectionalXMonotoneTraits_2} */ template class Arr_segment_traits_2 : public Kernel { 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 index e8748ae253c..3660fd211d6 100644 --- 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 @@ -19,6 +19,8 @@ #include +#include "CGAL/Bbox_2.h" + #ifdef DOXYGEN_RUNNING namespace CGAL { @@ -26,8 +28,8 @@ namespace CGAL { /*! \ingroup PkgArrangementOnSurface2Draw * The function opens a new window and draws `arr`, an instance of the - * `CGAL::Arrangement_2` class template. Parameters of the drawing are taken - * from the optional graphics scene options parameter. + * `CGAL::Arrangement_on_surface_2` class template. Parameters of the drawing + * are taken from the optional graphics scene options parameter. * * A call to this function blocks the execution of the program until the drawing * window is closed. This function requires `CGAL_Qt6`, and is only available if @@ -35,57 +37,64 @@ namespace CGAL { * `CGAL::CGAL_Basic_viewer` will link with `CGAL_Qt6` 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 `AosDcel` concept. + * \tparam GeometryTraits a geometry traits type, a model of a 2D arrangement + * geometry traits concept. Observe that not all geometery-traits models are + * supported. + * + * \tparam TopologyTraits a topology traits type, a model of the + * `AosTopologyTraits` concept. + * * \tparam GSOptions a model of `GraphicsSceneOptions` concept. * * \param arr the 2D arrangement to draw. - * \param gso the graphics scene options parameter. + * \param bbox a bounding box in parameter space. + * \param gso the graphics scene options. + * \param title the optional title of the window. * - * \sa `AosDcel` * \sa `AosTraits_2` + * \sa `AosTopologyTraits` + * \sa `GraphicsSceneOptions` */ -template -void draw(const Arrangement_2& arr, - const GSOptions& gso); + +template +void draw(const Arrangement_on_surface_2& arr, + const Bbox_2& bbox, const GSOptions& gso, + const char* title = "2D Arrangement on Surface"); /*! \ingroup PkgArrangementOnSurface2Draw * - * A shortcut to `CGAL::draw(arr, Graphics_scene_options{})`. + * A shortcut to `CGAL::draw(arr, bbox, Graphics_scene_options{})`, where `Aos` is + * `Arrangement_on_surface_2`. */ -template -void draw(const Arrangement_2& arr); + +template +void draw(const Arrangement_on_surface_2& arr, + const Bbox_2& bbox, const char* title = "2D Arrangement on Surface"); /*! \ingroup PkgArrangementOnSurface2Draw * - * adds the vertices, edges and faces of `arr` into the given graphic scene - * `gs`. Parameters of the cells are taken from the optional graphics scene - * options parameter `gso`. Note that `gs` is not cleared before being filled - * (to enable to draw several data structures in the same 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 `AosDcel` concept. - * \tparam GSOptions a model of `GraphicsSceneOptions` concept. - * - * \param arr the 2D arrangement to draw. - * \param gs the graphic scene to fill. - * \param gso the graphics scene options parameter. + * Similar to `CGAL::draw(arr, bbox, gso)`, where the bounding box `bbox` is + * computed to bound all points and curves of the arrangement in parameter + * space. */ -template -void add_to_graphics_scene(const Arrangement_2& arr, - CGAL::Graphics_scene& gs, const GSOptions& gso); + +template +void draw(const Arrangement_on_surface_2& arr, + const GSOptions& gso, const char* title = "2D Arrangement on Surface"); /*! \ingroup PkgArrangementOnSurface2Draw - * A shortcut to `CGAL::add_to_graphics_scene(arr, gs, - * Graphics_scene_options{})`. + * + * A shortcut to `CGAL::draw(arr, Graphics_scene_options{})`, where `Aos` is + * `Arrangement_on_surface_2`. */ -template -void add_to_graphics_scene(const Arrangement_2& arr, - CGAL::Graphics_scene& gs); + +template +void draw(const Arrangement_on_surface_2& arr, + const char* title = "2D Arrangement on Surface"); } /* namespace CGAL */ diff --git a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/AosApproximatePointTraits_2.h b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/AosApproximatePointTraits_2.h index 90b53ff56e5..367a8703ce3 100644 --- a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/AosApproximatePointTraits_2.h +++ b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/AosApproximatePointTraits_2.h @@ -18,8 +18,6 @@ * \cgalHasModels{CGAL::Arr_rational_function_traits_2} * \cgalHasModelsEnd * - * \sa `AosConstructXMonotoneCurveTraits_2` - * \sa `AosXMonotoneTraits_2` * \sa `AosTraits_2` */ class AosApproximatePointTraits_2 { @@ -35,7 +33,7 @@ public: /// \name Functor Types /// @{ - /// models the concept `AosTraits::Approximate_2`. + /// models the concept `AosTraits::ApproximatePoint_2`. typedef unspecified_type Approximate_2; /// @} diff --git a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/AosApproximateTraits_2.h b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/AosApproximateTraits_2.h index 2020e723039..c04fee15fc2 100644 --- a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/AosApproximateTraits_2.h +++ b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/AosApproximateTraits_2.h @@ -17,7 +17,9 @@ * \cgalHasModelsEnd * * \sa `AosApproximatePointTraits_2` - * \sa `draw()` + * \sa `AosConstructXMonotoneCurveTraits_2` + * \sa `AosXMonotoneTraits_2` + * \sa \link PkgArrangementOnSurface2Draw `CGAL::draw()`\endlink */ class AosApproximateTraits_2 { public: diff --git a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/AosApproximateUnboundedTraits_2.h b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/AosApproximateUnboundedTraits_2.h new file mode 100644 index 00000000000..518d5b01889 --- /dev/null +++ b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/AosApproximateUnboundedTraits_2.h @@ -0,0 +1,40 @@ +/*! \ingroup PkgArrangementOnSurface2ConceptsTraits + * \cgalConcept + * + * The concept `AosApproximateUnboundedTraits_2` refines the concept + * `AosApproximateTraits_2`. A model of this concept is able to approximate a + * curve constrained to a given bounding box (in addition to the ability to + * approximate a point and a curve without constraints). + * + * \cgalRefines{AosApproximateTraits_2} + * + * \cgalHasModelsBegin + * \cgalHasModels{CGAL::Arr_linear_traits_2} + * \cgalHasModelsEnd + * + * \sa `AosApproximateTraits_2` + * \sa \link PkgArrangementOnSurface2Draw `CGAL::draw()`\endlink + */ +class AosApproximateUnboundedTraits_2 { +public: + /// \name Types + /// @{ + + /// @} + + /// \name Functor Types + /// @{ + + /// models the concept `AosTraits::ApproximateUnbounded_2`. + typedef unspecified_type Approximate_2; + + /// @} + + /// \name Accessing Functor Objects + /// @{ + + /// + Approximate_2 approximate_2_object() const; + + /// @} +} diff --git a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/AosTraits--ApproximatePoint_2.h b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/AosTraits--ApproximatePoint_2.h new file mode 100644 index 00000000000..6d311aff303 --- /dev/null +++ b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/AosTraits--ApproximatePoint_2.h @@ -0,0 +1,28 @@ +namespace AosTraits { + +/*! \ingroup PkgArrangementOnSurface2ConceptsFunctionObjects + * \cgalConcept + * + * \cgalRefines{Functor} + * + * \cgalHasModelsBegin + * \cgalHasModels{AosApproximatePointTraits_2::Approximate_2} + * \cgalHasModels{AosApproximateTraits_2::Approximate_2} + * \cgalHasModelsEnd + */ +class ApproximatePoint_2 { +public: + /// \name Operations + /// A model of this concept must provide: + /// @{ + + /*! obtains an approximation of `p`'s \f$x\f$-coordinate (if `i == 0`), or of + * `p`'s \f$y\f$-coordinate (if `i == 1`). + * \pre `i` is either 0 or 1. + */ + Approximate_number_type operator()(AosTraits::Point_2 p, int i); + + /// @} +}; /* end AosTraits::Approximate_2 */ + +} diff --git a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/AosTraits--ApproximateUnbounded_2.h b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/AosTraits--ApproximateUnbounded_2.h new file mode 100644 index 00000000000..6431ad05d9f --- /dev/null +++ b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/AosTraits--ApproximateUnbounded_2.h @@ -0,0 +1,49 @@ +namespace AosTraits { + +/*! \ingroup PkgArrangementOnSurface2ConceptsFunctionObjects + * \cgalConcept + * + * \cgalRefines{Approximate_2} + * + * \cgalHasModelsBegin + * \cgalHasModels{AosApproximatePointTraits_2::Approximate_2} + * \cgalHasModels{AosApproximateTraits_2::Approximate_2} + * \cgalHasModels{AosApproximateUnboundedTraits_2::Approximate_2} + * \cgalHasModelsEnd + */ +class ApproximateUnbounded_2 { +public: + /// \name Operations + /// A model of this concept must provide: + /// @{ + + /*! approximates a given \f$x\f$-monotone curve constrained to a bounding + * box. It computes one or more sequences of approximate points that represent + * the disconnected portions of a polyline that approximates `xcv` within the + * bounding box `bbox`, and inserts them into output containers given through + * the output iterator `oi`. The first point of the first sequence and the + * last point of the last sequence are always approximations of the endpoints + * of the given curve. + * + * \param xcv The exact \f$x\f$-monotone curve. + * \param error The error bound of the polyline approximation. This is the + * Hausdorff distance between the curve and the polyline that + * approximates the curve. + * \param oi An output iterator for the output containers. + * \param bbox the bounding box. + * \param l2r A Boolean flag that indicates whether the curve direction is + * left to right. + * \return The past-the-end iterator of the output container. + * + * \pre Dereferencing `oi` must yield an object the type of which is a + * container, where the value type of this container is + * `AosApproximateTraits_2::Approximate_point_2`. + */ + template + OutputIterator operator()(const X_monotone_curve_2& xcv, double error, OutputIterator oi, + const Bbox_2& bbox, bool l2r = true) const; + + /// @} +}; /* end AosTraits::Approximate_2 */ + +} diff --git a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/AosTraits--Approximate_2.h b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/AosTraits--Approximate_2.h index a9712000aa9..f1a3caaf62b 100644 --- a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/AosTraits--Approximate_2.h +++ b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/AosTraits--Approximate_2.h @@ -3,7 +3,7 @@ namespace AosTraits { /*! \ingroup PkgArrangementOnSurface2ConceptsFunctionObjects * \cgalConcept * - * \cgalRefines{Functor} + * \cgalRefines{ApproximatePoint_2} * * \cgalHasModelsBegin * \cgalHasModels{AosApproximatePointTraits_2::Approximate_2} @@ -16,15 +16,9 @@ public: /// A model of this concept must provide: /// @{ - /*! obtains an approximation of `p`'s \f$x\f$-coordinate (if `i == 0`), or of - * `p`'s \f$y\f$-coordinate (if `i == 1`). - * \pre `i` is either 0 or 1. - */ - CGAL::Approximate_number_type operator()(AosTraits::Point_2 p, int i); - /*! obtains an approximation of `p`. */ - CGAL::Approximate_point_2 operator()(AosTraits::Point_2 p); + Approximate_point_2 operator()(AosTraits::Point_2 p); /*! approximates a given \f$x\f$-monotone curve. It computes a sequence of * approximate points that represent an approximate polyline, and inserts @@ -42,7 +36,7 @@ public: * \return The past-the-end iterator of the output container. * * \pre Dereferencing `oi` must yield an object of type - * `Arr_conic_traits_2::Approximate_point_2`. + * `AosApproximateTraits_2::Approximate_point_2`. */ template OutputIterator operator()(const X_monotone_curve_2& xcv, double error, 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 ea1b0b666e7..d1f0ab2fa19 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 @@ -113,6 +113,7 @@ implemented as peripheral classes or as free (global) functions. - `AosApproximateTraits_2` - `AosApproximatePointTraits_2` +- `AosApproximateUnboundedTraits_2` - `AosBasicTopologyTraits` - `AosBasicTraits_2` - `AosBottomSideTraits_2` @@ -167,6 +168,8 @@ implemented as peripheral classes or as free (global) functions. \cgalCRPSection{Function Object Concepts} - `AosTraits::Approximate_2` +- `AosTraits::ApproximatePoint_2` +- `AosTraits::ApproximateUnbounded_2` - `AosTraits::AreMergeable_2` - `AosTraits::CompareX_2` - `AosTraits::CompareXy_2` @@ -262,6 +265,6 @@ implemented as peripheral classes or as free (global) functions. - \link PkgArrangementOnSurface2op_right_shift `CGAL::operator<<` \endlink \cgalCRPSection{Draw an `Arrangemen_2` object} -- \link PkgArrangementOnSurface2Draw CGAL::draw<>() \endlink +- \link PkgArrangementOnSurface2Draw CGAL::draw<>() \endlink */ diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_linear_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_linear_traits_2.h index bf8792fdac5..0554989666e 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_linear_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_linear_traits_2.h @@ -28,6 +28,7 @@ #include +#include #include #include #include @@ -1517,9 +1518,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_linear_traits_2; + + /*! The traits (in case it has state) */ + const Traits& m_traits; + + /*! constructs + * \param traits the traits. + */ + Approximate_2(const Traits& traits) : m_traits(traits) {} + + friend class Arr_linear_traits_2; + public: /*! obtains an approximation of a point coordinate. * \param p The exact point. @@ -1533,10 +1549,102 @@ public: CGAL_precondition((i == 0) || (i == 1)); return (i == 0) ? CGAL::to_double(p.x()) : CGAL::to_double(p.y()); } + + /*! obtains an approximation of a point. + */ + Approximate_point_2 operator()(const Point_2& p) const + { return Approximate_point_2(operator()(p, 0), operator()(p, 1)); } + + /*! obtains 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; + } + + /*! obtains an approximation of an \f$x\f$-monotone curve. + */ + template + OutputIterator operator()(const X_monotone_curve_2& xcv, double /* error */, + OutputIterator oi, const Bbox_2& bbox, + bool l2r = true) const + { + using Approx_pnt = Approximate_point_2; + using Approx_seg = Approximate_kernel::Segment_2; + using Approx_ray = Approximate_kernel::Ray_2; + using Approx_lin = Approximate_kernel::Line_2; + auto xmin = bbox.xmin(); + auto ymin = bbox.ymin(); + auto xmax = bbox.xmax(); + auto ymax = bbox.ymax(); + Approximate_kernel::Iso_rectangle_2 rect(xmin, ymin, xmax, ymax); + if (xcv.is_ray()) { + auto ray = xcv.ray(); + Kernel kernel; + auto construct_vertex = kernel.construct_point_on_2_object(); + Approx_pnt s = this->operator()(construct_vertex(ray, 0)); + Approx_pnt t = this->operator()(construct_vertex(ray, 1)); + const auto result = CGAL::intersection(rect, Approx_ray(s, t)); + if (! result) return oi; + + if (const auto* res_seg = std::get_if(&*result)) { + *oi++ = l2r ? (res_seg->min)() : (res_seg->max)(); + *oi++ = l2r ? (res_seg->max)() : (res_seg->min)(); + return oi; + } + const auto* res_pnt = std::get_if(&*result); + CGAL_assertion(res_pnt != nullptr); + *oi++ = *res_pnt; + return oi; + } + if (xcv.is_line()) { + const Line_2 & supp_line = xcv.supp_line(); + Approx_lin approx_supp_line( + CGAL::to_double(supp_line.a()), + CGAL::to_double(supp_line.b()), + CGAL::to_double(supp_line.c())); + const auto result = CGAL::intersection(rect, approx_supp_line); + if (! result) return oi; + + if (const auto* res_seg = std::get_if(&*result)) { + *oi++ = l2r ? (res_seg->min)() : (res_seg->max)(); + *oi++ = l2r ? (res_seg->max)() : (res_seg->min)(); + return oi; + } + const auto* res_pnt = std::get_if(&*result); + CGAL_assertion(res_pnt != nullptr); + *oi++ = *res_pnt; + return oi; + } + Approx_seg seg(this->operator()(xcv.source()), this->operator()(xcv.target())); + const auto result = CGAL::intersection(rect, seg); + if (! result) return oi; + + if (const auto* res_seg = std::get_if(&*result)) { + *oi++ = l2r ? (res_seg->min)() : (res_seg->max)(); + *oi++ = l2r ? (res_seg->max)() : (res_seg->min)(); + return oi; + } + const auto* res_pnt = std::get_if(&*result); + CGAL_assertion(res_pnt != nullptr); + *oi++ = *res_pnt; + return oi; + } }; /*! obtains 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 1057e1c0f8a..fb5b0ef6b1d 100644 --- a/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h +++ b/Arrangement_on_surface_2/include/CGAL/draw_arrangement_2.h @@ -37,58 +37,55 @@ namespace CGAL { -namespace draw_function_for_arrangement_2 -{ - template - class Draw_arr_tool - { - public: - using Halfedge_const_handle=typename Arr::Halfedge_const_handle; - using Vertex_const_handle=typename Arr::Vertex_const_handle; - using Face_const_handle=typename Arr::Face_const_handle; - using Ccb_halfedge_const_circulator=typename Arr::Ccb_halfedge_const_circulator; - using Inner_ccb_const_iterator=typename Arr::Inner_ccb_const_iterator; - using Outer_ccb_const_iterator=typename Arr::Outer_ccb_const_iterator; - using Gt=typename Arr::Geometry_traits_2; - using Point=typename Arr::Point_2; - using X_monotone_curve = typename Arr::X_monotone_curve_2; +namespace draw_aos { - Draw_arr_tool(Arr& a_aos, CGAL::Graphics_scene& a_gs, const GSOptions& a_gso): - m_aos(a_aos), m_gs(a_gs), m_gso(a_gso) - {} +template +class Draw_arr_tool { +public: + using Halfedge_const_handle=typename Arr::Halfedge_const_handle; + using Vertex_const_handle=typename Arr::Vertex_const_handle; + using Face_const_handle=typename Arr::Face_const_handle; + using Ccb_halfedge_const_circulator=typename Arr::Ccb_halfedge_const_circulator; + using Inner_ccb_const_iterator=typename Arr::Inner_ccb_const_iterator; + using Outer_ccb_const_iterator=typename Arr::Outer_ccb_const_iterator; + using Gt=typename Arr::Geometry_traits_2; + using Point=typename Arr::Point_2; + using X_monotone_curve = typename Arr::X_monotone_curve_2; - /// Add a face. - void add_face(Face_const_handle face) - { - // std::cout << "add_face()\n"; - for (Inner_ccb_const_iterator it = face->inner_ccbs_begin(); - it != face->inner_ccbs_end(); ++it) - { add_ccb(*it); } + Draw_arr_tool(Arr& a_aos, CGAL::Graphics_scene& a_gs, const GSOptions& a_gso): + m_aos(a_aos), m_gs(a_gs), m_gso(a_gso) + {} + //! adds a face. + void add_face(Face_const_handle face) { + // std::cout << "add_face()\n"; + for (Inner_ccb_const_iterator it = face->inner_ccbs_begin(); + it != face->inner_ccbs_end(); ++it) + add_ccb(*it); + + if (! face->is_unbounded()) { for (Outer_ccb_const_iterator it = face->outer_ccbs_begin(); - it != face->outer_ccbs_end(); ++it) - { + it != face->outer_ccbs_end(); ++it) { add_ccb(*it); draw_region(*it); } } + } - /// Add a Connected Component of the Boundary. - void add_ccb(Ccb_halfedge_const_circulator circ) - { - // std::cout << "add_ccb()\n"; - auto curr = circ; - do { - auto new_face = curr->twin()->face(); - if (m_visited.find(new_face) != m_visited.end()) continue; - m_visited[new_face] = true; - add_face(new_face); - } while (++curr != circ); - } + //! adds a Connected Component of the Boundary. + void add_ccb(Ccb_halfedge_const_circulator circ) { + // std::cout << "add_ccb()\n"; + auto curr = circ; + do { + auto new_face = curr->twin()->face(); + if (m_visited.find(new_face) != m_visited.end()) continue; + m_visited[new_face] = true; + add_face(new_face); + } while (++curr != circ); + } - ///! Draw a region. - void draw_region(Ccb_halfedge_const_circulator circ) - { + //! draws a region. + void draw_region(Ccb_halfedge_const_circulator circ) { // std::cout << "draw_region()\n"; /* Check whether the traits has a member function called * approximate_2_object() and if so check whether the return type, namely @@ -105,318 +102,300 @@ namespace draw_function_for_arrangement_2 * * For now we use C++14 features. */ - if(m_gso.colored_face(m_aos, circ->face())) - { m_gs.face_begin(m_gso.face_color(m_aos, circ->face())); } - else - { m_gs.face_begin(); } + if (m_gso.colored_face(m_aos, circ->face())) + m_gs.face_begin(m_gso.face_color(m_aos, circ->face())); + else + m_gs.face_begin(); - const auto* traits = this->m_aos.geometry_traits(); - auto ext = find_smallest(circ, *traits); - auto curr = ext; + const auto* traits = this->m_aos.geometry_traits(); + auto ext = find_smallest(circ, *traits); + auto curr = ext; - do { - // Skip halfedges that are "antenas": - while (curr->face() == curr->twin()->face()) curr = curr->twin()->next(); - draw_region_impl1(curr, *traits, 0); - curr = curr->next(); - } while (curr != ext); + do { + // Skip halfedges that are "antenas": + while (curr->face() == curr->twin()->face()) curr = curr->twin()->next(); + draw_region_impl1(curr, *traits, 0); + curr = curr->next(); + } while (curr != ext); - m_gs.face_end(); - } + m_gs.face_end(); + } - /// Compile time dispatching + //! Compile time dispatching #if 0 - template - void draw_region_impl2(Halfedge_const_handle curr, T const&, long) - { draw_exact_region(curr); } + template + void draw_region_impl2(Halfedge_const_handle curr, T const&, long) + { draw_exact_region(curr); } - 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_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 - void draw_region_impl1(Halfedge_const_handle curr, T const&, long) - { draw_exact_region(curr); } + template + void draw_region_impl1(Halfedge_const_handle curr, T const&, long) + { 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); - } + 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); + } #else - template - void draw_region_impl1(Halfedge_const_handle curr, T const& traits, int) - { draw_approximate_region(curr, traits.approximate_2_object()); } + template + void draw_region_impl1(Halfedge_const_handle curr, T const& traits, int) + { draw_approximate_region(curr, traits.approximate_2_object()); } #endif - template - void draw_region_impl1 - (Halfedge_const_handle curr, - Arr_geodesic_arc_on_sphere_traits_2 const& traits, - int) - { - if(!m_gso.draw_edge(m_aos, curr)) - { return; } + template + void draw_region_impl1 + (Halfedge_const_handle curr, + Arr_geodesic_arc_on_sphere_traits_2 const& traits, + int) + { + if (! m_gso.draw_edge(m_aos, curr)) return; - // std::cout << "draw_region_impl1()\n"; - auto approx = traits.approximate_2_object(); - using Kernel = Kernel_; - using Traits = Arr_geodesic_arc_on_sphere_traits_2; - using Ak = typename Traits::Approximate_kernel; - using Ap = typename Traits::Approximate_point_2; - using Approx_point_3 = typename Ak::Point_3; + // std::cout << "draw_region_impl1()\n"; + auto approx = traits.approximate_2_object(); + using Kernel = Kernel_; + using Traits = Arr_geodesic_arc_on_sphere_traits_2; + using Ak = typename Traits::Approximate_kernel; + using Ap = typename Traits::Approximate_point_2; + using Approx_point_3 = typename Ak::Point_3; - std::vector polyline; - double error(0.01); - 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(); + std::vector polyline; + double error(0.01); + 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 x = it->dx(); + auto y = it->dy(); + auto z = it->dz(); + auto l = std::sqrt(x*x + y*y + z*z); + Approx_point_3 prev(x/l, y/l, z/l); + for (++it; it != polyline.end(); ++it) { auto x = it->dx(); auto y = it->dy(); auto z = it->dz(); auto l = std::sqrt(x*x + y*y + z*z); - Approx_point_3 prev(x/l, y/l, z/l); - for (++it; it != polyline.end(); ++it) { - auto x = it->dx(); - auto y = it->dy(); - auto z = it->dz(); - auto l = std::sqrt(x*x + y*y + z*z); - Approx_point_3 next(x/l, y/l, z/l); + Approx_point_3 next(x/l, y/l, z/l); - if(m_gso.colored_edge(m_aos, curr)) - { m_gs.add_segment(prev, next, m_gso.edge_color(m_aos, curr)); } - else - { m_gs.add_segment(prev, next); } - - prev = next; - // m_gs.add_point_in_face(*prev); - } - } - - /*! Draw a region using approximate 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) - { - // std::cout << "draw_approximate_region()\n"; - std::vector polyline; - double error(0.01); // TODO? (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++) { - if(m_gso.draw_edge(m_aos, curr)) - { - if(m_gso.colored_edge(m_aos, curr)) - { m_gs.add_segment(*prev, *it, m_gso.edge_color(m_aos, curr)); } - else - { m_gs.add_segment(*prev, *it); } - } - m_gs.add_point_in_face(*prev); - } - } - - /// Draw an exact curve. - template - void draw_exact_curve(const XMonotoneCurve& curve) - { - const auto* traits = this->m_aos.geometry_traits(); - auto ctr_min = traits->construct_min_vertex_2_object(); - auto ctr_max = traits->construct_max_vertex_2_object(); - m_gs.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()); - } - - /// Add all faces. - template - void add_faces(const Traits&) - { - for (auto it=m_aos.unbounded_faces_begin(); it!=m_aos.unbounded_faces_end(); ++it) - { add_face(it); } - } - - /// Add all faces. - template - void add_faces(Arr_geodesic_arc_on_sphere_traits_2 const&) - { add_face(m_aos.faces_begin()); } - - /// Compile time dispatching -#if 0 - template - void draw_point_impl2(const Point& p, T const&, long) { m_gs.add_point(p); } - - template - auto draw_point_impl2(const Point& p, T const& approx, int) -> - decltype(approx.operator()(p), void()) - { m_gs.add_point(approx(p)); } - - template - void draw_point_impl1(const Point& p, T const&, long) { m_gs.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(), true); - } -#else - template - void draw_point_impl1(const Point& p, T const& traits, int, - bool colored, const CGAL::IO::Color& color) - { - if(colored) - { m_gs.add_point(traits.approximate_2_object()(p), color); } + if (m_gso.colored_edge(m_aos, curr)) + m_gs.add_segment(prev, next, m_gso.edge_color(m_aos, curr)); else - { m_gs.add_point(traits.approximate_2_object()(p)); } + m_gs.add_segment(prev, next); + + prev = next; + // m_gs.add_point_in_face(*prev); } + } + + /*! draws a region using approximate 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) { + // std::cout << "draw_approximate_region()\n"; + std::vector polyline; + double error(0.01); // TODO? (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++) { + if (m_gso.draw_edge(m_aos, curr)) { + if (m_gso.colored_edge(m_aos, curr)) + m_gs.add_segment(*prev, *it, m_gso.edge_color(m_aos, curr)); + else + m_gs.add_segment(*prev, *it); + } + m_gs.add_point_in_face(*prev); + } + } + + //! draws an exact curve. + template + void draw_exact_curve(const XMonotoneCurve& curve) { + const auto* traits = this->m_aos.geometry_traits(); + auto ctr_min = traits->construct_min_vertex_2_object(); + auto ctr_max = traits->construct_max_vertex_2_object(); + m_gs.add_segment(ctr_min(curve), ctr_max(curve)); + } + + //! draws an exact region. + void draw_exact_region(Halfedge_const_handle curr) { + // this->add_point_in_face(curr->source()->point()); + draw_exact_curve(curr->curve()); + } + + //! adds all faces. + template + void add_faces(const Traits&) { + for (auto it = m_aos.unbounded_faces_begin(); it != m_aos.unbounded_faces_end(); ++it) + add_face(it); + } + + //! adds all faces. + template + void add_faces(Arr_geodesic_arc_on_sphere_traits_2 const&) + { add_face(m_aos.faces_begin()); } + + //! Compile time dispatching +#if 0 + template + void draw_point_impl2(const Point& p, T const&, long) { m_gs.add_point(p); } + + template + auto draw_point_impl2(const Point& p, T const& approx, int) -> + decltype(approx.operator()(p), void()) + { m_gs.add_point(approx(p)); } + + template + void draw_point_impl1(const Point& p, T const&, long) { m_gs.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(), true); + } +#else + template + void draw_point_impl1(const Point& p, T const& traits, int, + bool colored, const CGAL::IO::Color& color) { + if (colored) + { m_gs.add_point(traits.approximate_2_object()(p), color); } + else + { m_gs.add_point(traits.approximate_2_object()(p)); } + } #endif - template - void draw_point_impl1 - (const Point& p, - Arr_geodesic_arc_on_sphere_traits_2 const& traits, - int, - bool colored, - const CGAL::IO::Color& color) - { - auto approx = traits.approximate_2_object(); - using Traits = Arr_geodesic_arc_on_sphere_traits_2; - using Ak = typename Traits::Approximate_kernel; - using Approx_point_3 = typename Ak::Point_3; - auto ap = approx(p); - auto x = ap.dx(); - auto y = ap.dy(); - auto z = ap.dz(); - auto l = std::sqrt(x*x + y*y + z*z); - Approx_point_3 p3(x/l, y/l, z/l); - if(colored) - { m_gs.add_point(p3, color); } + template + void draw_point_impl1 + (const Point& p, + Arr_geodesic_arc_on_sphere_traits_2 const& traits, + int, + bool colored, + const CGAL::IO::Color& color) { + auto approx = traits.approximate_2_object(); + using Traits = Arr_geodesic_arc_on_sphere_traits_2; + using Ak = typename Traits::Approximate_kernel; + using Approx_point_3 = typename Ak::Point_3; + auto ap = approx(p); + auto x = ap.dx(); + auto y = ap.dy(); + auto z = ap.dz(); + auto l = std::sqrt(x*x + y*y + z*z); + Approx_point_3 p3(x/l, y/l, z/l); + if (colored) m_gs.add_point(p3, color); + else m_gs.add_point(p3); + } + + //! draws a point. + void draw_point(Vertex_const_handle vh) { + const auto* traits = m_aos.geometry_traits(); + if (m_gso.draw_vertex(m_aos, vh)) { + if (m_gso.colored_vertex(m_aos, vh)) + draw_point_impl1(vh->point(), *traits, 0, true, + m_gso.vertex_color(m_aos, vh)); else - { m_gs.add_point(p3); } + draw_point_impl1(vh->point(), *traits, 0, false, CGAL::IO::Color()); // color will be unused } + } - /// Draw a point. - void draw_point(Vertex_const_handle vh) - { - const auto* traits = m_aos.geometry_traits(); - if(m_gso.draw_vertex(m_aos, vh)) - { - if(m_gso.colored_vertex(m_aos, vh)) - { draw_point_impl1(vh->point(), *traits, 0, true, - m_gso.vertex_color(m_aos, vh)); } - else - { draw_point_impl1(vh->point(), *traits, 0, false, CGAL::IO::Color()); } // color will be unused + template + Halfedge_const_handle + find_smallest(Ccb_halfedge_const_circulator circ, + Arr_geodesic_arc_on_sphere_traits_2 const&) + { return circ; } + + /*! finds the halfedge incident to the lexicographically smallest vertex + * along the CCB, such that there is no other halfedge underneath. + */ + template + Halfedge_const_handle find_smallest(Ccb_halfedge_const_circulator circ, + const Traits&) { + // std::cout << "find_smallest()\n"; + const auto* traits = this->m_aos.geometry_traits(); + 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; } - } - template - Halfedge_const_handle - find_smallest(Ccb_halfedge_const_circulator circ, - Arr_geodesic_arc_on_sphere_traits_2 const&) - { return circ; } + // 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); - /*! Find the halfedge incident to the lexicographically smallest vertex - * along the CCB, such that there is no other halfedge underneath. - */ - template - Halfedge_const_handle find_smallest(Ccb_halfedge_const_circulator circ, - const Traits&) - { - // std::cout << "find_smallest()\n"; - const auto* traits = this->m_aos.geometry_traits(); - auto cmp_xy = traits->compare_xy_2_object(); - auto cmp_y = traits->compare_y_at_x_right_2_object(); + return ext; + } - // 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); - - return ext; - } - - /// Add all elements to be drawn. - void add_elements() - { + //! adds all elements to be drawn. + void add_elements() { // std::cout << "add_elements()\n"; // std::cout << "ratio: " << this->pixel_ratio() << std::endl; m_visited.clear(); if (m_aos.is_empty()) return; - if(m_gso.are_faces_enabled()) + if (m_gso.are_faces_enabled()) { add_faces(*(this->m_aos.geometry_traits())); } // Add edges that do not separate faces. - if(m_gso.are_edges_enabled()) - { - for (auto it = m_aos.edges_begin(); it != m_aos.edges_end(); ++it) - { if (it->face()==it->twin()->face()) - { - if(m_gso.draw_edge(m_aos, it)) - { - if(m_gso.colored_edge(m_aos, it)) - { draw_curve(it->curve(), true, m_gso.edge_color(m_aos, it)); } + if (m_gso.are_edges_enabled()) { + for (auto it = m_aos.edges_begin(); it != m_aos.edges_end(); ++it) { + if (it->face()==it->twin()->face()) { + if (m_gso.draw_edge(m_aos, it)) { + if (m_gso.colored_edge(m_aos, it)) + draw_curve(it->curve(), true, m_gso.edge_color(m_aos, it)); else - { draw_curve(it->curve(), false, CGAL::IO::Color()); } + draw_curve(it->curve(), false, CGAL::IO::Color()); } } } } // Add all points - if(m_gso.are_vertices_enabled()) - { + if (m_gso.are_vertices_enabled()) { for (auto it = m_aos.vertices_begin(); it != m_aos.vertices_end(); ++it) - { draw_point(it); } + draw_point(it); } m_visited.clear(); } - /*! Draw a curve using approximate coordinates. + /*! draws a curve using approximate 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 @@ -425,149 +404,138 @@ namespace draw_function_for_arrangement_2 template void draw_approximate_curve(const XMonotoneCurve& curve, const Approximate& approx, - bool colored, const CGAL::IO::Color& c) - { + bool colored, const CGAL::IO::Color& c) { std::vector polyline; double error(0.01); // TODO? (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++) - { - if(colored) - { m_gs.add_segment(*prev, *it, c); } - else - { m_gs.add_segment(*prev, *it); } + for (; it != polyline.end(); prev = it++) { + if (colored) m_gs.add_segment(*prev, *it, c); + else m_gs.add_segment(*prev, *it); } - } /*! Compile time dispatching */ #if 0 - template - void draw_curve_impl2(const X_monotone_curve& xcv, T const&, long) - { draw_exact_curve(xcv); } + template + void draw_curve_impl2(const X_monotone_curve& xcv, T const&, long) + { 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_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 - void draw_curve_impl1(const X_monotone_curve& xcv, T const&, long) - { draw_exact_curve(xcv); } + template + void draw_curve_impl1(const X_monotone_curve& xcv, T const&, long) + { 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); - } + 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); + } #else - template - void draw_curve_impl1(const X_monotone_curve& xcv, T const& traits, int, - bool colored, const CGAL::IO::Color& c) - { draw_approximate_curve(xcv, traits.approximate_2_object(), colored, c); } + template + void draw_curve_impl1(const X_monotone_curve& xcv, T const& traits, int, + bool colored, const CGAL::IO::Color& c) + { draw_approximate_curve(xcv, traits.approximate_2_object(), colored, c); } #endif - template - void draw_curve_impl1 - (const X_monotone_curve& xcv, - Arr_geodesic_arc_on_sphere_traits_2 const& traits, - int, - bool colored, const CGAL::IO::Color& c) - { - auto approx = traits.approximate_2_object(); - using Kernel = Kernel_; - using Traits = Arr_geodesic_arc_on_sphere_traits_2; - using Ak = typename Traits::Approximate_kernel; - using Ap = typename Traits::Approximate_point_2; - using Approx_point_3 = typename Ak::Point_3; - std::vector apoints; - double error(0.01); - approx(xcv, error, std::back_inserter(apoints)); - auto it = apoints.begin(); + template + void draw_curve_impl1 + (const X_monotone_curve& xcv, + Arr_geodesic_arc_on_sphere_traits_2 const& traits, + int, + bool colored, const CGAL::IO::Color& c) + { + auto approx = traits.approximate_2_object(); + using Kernel = Kernel_; + using Traits = Arr_geodesic_arc_on_sphere_traits_2; + using Ak = typename Traits::Approximate_kernel; + using Ap = typename Traits::Approximate_point_2; + using Approx_point_3 = typename Ak::Point_3; + std::vector apoints; + double error(0.01); + approx(xcv, error, std::back_inserter(apoints)); + auto it = apoints.begin(); + auto x = it->dx(); + auto y = it->dy(); + auto z = it->dz(); + auto l = std::sqrt(x*x + y*y + z*z); + Approx_point_3 prev(x/l, y/l, z/l); + for (++it; it != apoints.end(); ++it) { auto x = it->dx(); auto y = it->dy(); auto z = it->dz(); auto l = std::sqrt(x*x + y*y + z*z); - Approx_point_3 prev(x/l, y/l, z/l); - for (++it; it != apoints.end(); ++it) { - auto x = it->dx(); - auto y = it->dy(); - auto z = it->dz(); - auto l = std::sqrt(x*x + y*y + z*z); - Approx_point_3 next(x/l, y/l, z/l); - if(colored) - { m_gs.add_segment(prev, next, c); } - else - { m_gs.add_segment(prev, next); } - prev = next; - } + Approx_point_3 next(x/l, y/l, z/l); + if (colored) m_gs.add_segment(prev, next, c); + else m_gs.add_segment(prev, next); + prev = next; } + } - /// Draw a curve. - template - void draw_curve(const XMonotoneCurve& curve, - bool colored, const CGAL::IO::Color& c) - { - /* 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. - */ + //! draws a curve. + template + void draw_curve(const XMonotoneCurve& curve, + bool colored, const CGAL::IO::Color& c) { + /* 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. + */ #if 0 - if constexpr (std::experimental::is_detected_v) - { - const auto* traits = this->m_aos.geometry_traits(); - auto approx = traits->approximate_2_object(); - draw_approximate_curve(curve, approx); - return; - } - draw_exact_curve(curve); -#else + if constexpr (std::experimental::is_detected_v) { const auto* traits = this->m_aos.geometry_traits(); - draw_curve_impl1(curve, *traits, 0, colored, c); -#endif + auto approx = traits->approximate_2_object(); + draw_approximate_curve(curve, approx); + return; } + draw_exact_curve(curve); +#else + const auto* traits = this->m_aos.geometry_traits(); + draw_curve_impl1(curve, *traits, 0, colored, c); +#endif + } - protected: - Arr& m_aos; - CGAL::Graphics_scene& m_gs; - const GSOptions& m_gso; - std::unordered_map m_visited; - }; +protected: + Arr& m_aos; + CGAL::Graphics_scene& m_gs; + const GSOptions& m_gso; + std::unordered_map m_visited; +}; -} // namespace draw_function_for_arrangement_2 +} // namespace draw_aos #define CGAL_ARR_TYPE CGAL::Arrangement_on_surface_2 template void add_to_graphics_scene(const CGAL_ARR_TYPE& aos, CGAL::Graphics_scene& graphics_scene, - const GSOptions& gso) -{ - draw_function_for_arrangement_2::Draw_arr_tool dar(aos, graphics_scene, gso); + const GSOptions& gso) { + draw_aos::Draw_arr_tool dar(aos, graphics_scene, gso); dar.add_elements(); } template void add_to_graphics_scene(const CGAL_ARR_TYPE& aos, - CGAL::Graphics_scene& graphics_scene) -{ + CGAL::Graphics_scene& graphics_scene) { CGAL::Graphics_scene_options void draw(const CGAL_ARR_TYPE& aos, const GSOptions& gso, - const char* title = "2D Arrangement on Surface Basic Viewer") -{ + const char* title = "2D Arrangement on Surface Basic Viewer") { CGAL::Graphics_scene graphics_scene; add_to_graphics_scene(aos, graphics_scene, gso); draw_graphics_scene(graphics_scene, title); @@ -600,8 +567,7 @@ void draw(const CGAL_ARR_TYPE& aos, const GSOptions& gso, template void draw(const CGAL_ARR_TYPE& aos, - const char* title = "2D Arrangement on Surface Basic Viewer") -{ + const char* title = "2D Arrangement on Surface Basic Viewer") { CGAL::Graphics_scene graphics_scene; add_to_graphics_scene(aos, graphics_scene); draw_graphics_scene(graphics_scene, title); diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 37950b4a3f9..60074890e3b 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -4,6 +4,12 @@ Release date: July 2026 +### [2D Arrangements](https://doc.cgal.org/6.1/Manual/packages.html#PkgArrangementOnSurface2) + +- Introduced a Geometry Traits concept for arrangement on surfaces that enables the provision of the disconnected portions of an approximation of a curve within a given bounding box. +- Made the `Arr_linear_traits_2` a model of the new concept. + + ### [Linear Cell Complex](https://doc.cgal.org/6.2/Manual/packages.html#PkgLinearCellComplex) - **API Changes**: The following import functions have been deprecated and renamed for better naming clarity and consistency: