Cleaned up

This commit is contained in:
Efi Fogel 2024-01-29 19:19:25 +02:00
parent e6b72fc7c8
commit 0bf75c9062
1 changed files with 94 additions and 153 deletions

View File

@ -15,13 +15,11 @@
#include <CGAL/license/Envelope_2.h> #include <CGAL/license/Envelope_2.h>
#include <CGAL/Arr_enums.h>
#include <CGAL/Arrangement_2/Arr_traits_adaptor_2.h>
#include <optional> #include <optional>
#include <vector> #include <vector>
#include <CGAL/Arr_enums.h>
#include <CGAL/Arrangement_2/Arr_traits_adaptor_2.h>
namespace CGAL { namespace CGAL {
@ -29,11 +27,9 @@ namespace CGAL {
* A class implementing the divide-and-conquer algorithm for computing the * A class implementing the divide-and-conquer algorithm for computing the
* lower (or upper) envelope of a set of curves. * lower (or upper) envelope of a set of curves.
*/ */
template <class Traits_, class Diagram_> template <typename Traits_, typename Diagram_>
class Envelope_divide_and_conquer_2 class Envelope_divide_and_conquer_2 {
{
public: public:
typedef Traits_ Traits_2; typedef Traits_ Traits_2;
typedef typename Traits_2::Point_2 Point_2; typedef typename Traits_2::Point_2 Point_2;
typedef typename Traits_2::X_monotone_curve_2 X_monotone_curve_2; typedef typename Traits_2::X_monotone_curve_2 X_monotone_curve_2;
@ -42,11 +38,9 @@ public:
typedef Diagram_ Envelope_diagram_1; typedef Diagram_ Envelope_diagram_1;
protected: protected:
typedef Envelope_divide_and_conquer_2<Traits_2, Envelope_diagram_1> Self; typedef Envelope_divide_and_conquer_2<Traits_2, Envelope_diagram_1> Self;
enum Envelope_type enum Envelope_type {
{
LOWER, LOWER,
UPPER UPPER
}; };
@ -62,159 +56,118 @@ protected:
typedef Arr_traits_adaptor_2<Traits_2> Traits_adaptor_2; typedef Arr_traits_adaptor_2<Traits_2> Traits_adaptor_2;
// Data members: // Data members:
const Traits_adaptor_2 *traits; // The traits object. const Traits_adaptor_2* traits; // The traits object.
bool own_traits; // Whether we own the traits object. bool own_traits; // Whether we own the traits object.
Envelope_type env_type; // Either LOWER or UPPER. Envelope_type env_type; // Either LOWER or UPPER.
// Copy constructor and assignment operator - not supported. // Copy constructor and assignment operator - not supported.
Envelope_divide_and_conquer_2 (const Self& ); Envelope_divide_and_conquer_2(const Self&);
Self& operator= (const Self& ); Self& operator=(const Self& );
public: public:
/*! Constructor.
/*!
* Constructor.
*/ */
Envelope_divide_and_conquer_2 () : Envelope_divide_and_conquer_2() :
own_traits(true), own_traits(true),
env_type(LOWER) env_type(LOWER)
{ { traits = new Traits_adaptor_2; }
traits = new Traits_adaptor_2;
}
/*! /*! Constructor with a traits object.
* Constructor with a traits object.
* \param _traits The traits object. * \param _traits The traits object.
*/ */
Envelope_divide_and_conquer_2 (const Traits_2* _traits) : Envelope_divide_and_conquer_2(const Traits_2* _traits) :
own_traits(false), own_traits(false),
env_type(LOWER) env_type(LOWER)
{ { traits = static_cast<const Traits_adaptor_2*> (_traits); }
traits = static_cast<const Traits_adaptor_2*> (_traits);
}
/*! /*! Destructor.
* Destructor.
*/ */
~Envelope_divide_and_conquer_2 () ~Envelope_divide_and_conquer_2()
{ { if (own_traits) delete traits; }
if (own_traits)
delete traits;
}
/*! /*! Construct the lower (or upper) envelope to the given range of curves.
* Construct the lower (or upper) envelope to the given range of curves.
* \param begin An iterator pointing at the beginning of the curves range. * \param begin An iterator pointing at the beginning of the curves range.
* \param end A past-the-end iterator for the curves range. * \param end A past-the-end iterator for the curves range.
* \param type The envelope type (true for lower, false of upper). * \param type The envelope type (true for lower, false of upper).
* \param diagram Output: The minimization (or maximization) diagram. * \param diagram Output: The minimization (or maximization) diagram.
*/ */
template <class CurvesIterator> template <typename CurvesIterator>
void insert_curves (CurvesIterator begin, CurvesIterator end, void insert_curves(CurvesIterator begin, CurvesIterator end, bool type,
bool type, Envelope_diagram_1& diagram) {
Envelope_diagram_1& diagram)
{
// Subdivide the curves into x-monotone subcurves. // Subdivide the curves into x-monotone subcurves.
CurvesIterator it;
std::list<std::variant<Point_2, X_monotone_curve_2>> objects; std::list<std::variant<Point_2, X_monotone_curve_2>> objects;
std::list<X_monotone_curve_2> x_curves; std::list<X_monotone_curve_2> x_curves;
for (it = begin; it != end; it++) for (auto it = begin; it != end; ++it) {
{
// Split the current curve to x-monotone subcurves. // Split the current curve to x-monotone subcurves.
objects.clear(); objects.clear();
traits->make_x_monotone_2_object()(*it, std::back_inserter(objects)); traits->make_x_monotone_2_object()(*it, std::back_inserter(objects));
for (auto obj_it = objects.begin(); obj_it != objects.end(); ++obj_it) for (auto obj_it = objects.begin(); obj_it != objects.end(); ++obj_it) {
{ if (const auto* xcv_ptr = std::get_if<X_monotone_curve_2>(&(*obj_it)))
if(const X_monotone_curve_2* xcv_ptr = std::get_if<X_monotone_curve_2>(&(*obj_it)))
x_curves.push_back (*xcv_ptr); x_curves.push_back (*xcv_ptr);
} }
} }
// Construct the envelope of the x-monotone curves. // Construct the envelope of the x-monotone curves.
insert_x_monotone_curves (x_curves.begin(), x_curves.end(), insert_x_monotone_curves(x_curves.begin(), x_curves.end(), type, diagram);
type,
diagram);
return;
} }
/*! /*! Construct the lower (or upper) envelope to the given range of
* Construct the lower (or upper) envelope to the given range of
* x-monotone curves. * x-monotone curves.
* \param begin An iterator pointing at the beginning of the curves range. * \param begin An iterator pointing at the beginning of the curves range.
* \param end A past-the-end iterator for the curves range. * \param end A past-the-end iterator for the curves range.
* \param type The envelope type (true for lower, false for upper). * \param type The envelope type (true for lower, false for upper).
* \param diagram Output: The minimization (or maximization) diagram. * \param diagram Output: The minimization (or maximization) diagram.
*/ */
template <class XCurvesIterator> template <typename XCurvesIterator>
void insert_x_monotone_curves (XCurvesIterator begin, XCurvesIterator end, void insert_x_monotone_curves(XCurvesIterator begin, XCurvesIterator end,
bool type, bool type, Envelope_diagram_1& diagram) {
Envelope_diagram_1& diagram)
{
// Set the envelope type. // Set the envelope type.
env_type = (type ? LOWER : UPPER); env_type = (type ? LOWER : UPPER);
// Separate the regular curves from the vertical ones. // Separate the regular curves from the vertical ones.
typename Traits_2::Is_vertical_2 is_vertical = auto is_vertical = traits->is_vertical_2_object();
traits->is_vertical_2_object();
Curve_pointer_vector reg_vec; Curve_pointer_vector reg_vec;
Curve_pointer_vector vert_vec; Curve_pointer_vector vert_vec;
XCurvesIterator iter;
for (iter = begin; iter != end; ++iter) for (auto iter = begin; iter != end; ++iter) {
{ if (is_vertical (*iter)) vert_vec.push_back (&(*iter));
if (is_vertical (*iter)) else reg_vec.push_back (&(*iter));
vert_vec.push_back (&(*iter));
else
reg_vec.push_back (&(*iter));
} }
// Construct the envelope for the non-vertical curves. // Construct the envelope for the non-vertical curves.
_construct_envelope_non_vertical (reg_vec.begin(), reg_vec.end(), _construct_envelope_non_vertical(reg_vec.begin(), reg_vec.end(), diagram);
diagram);
// Merge the vertical segments. // Merge the vertical segments.
if (vert_vec.size() > 0) if (vert_vec.size() > 0) _merge_vertical_segments(vert_vec, diagram);
_merge_vertical_segments (vert_vec,
diagram);
return;
} }
/*! /*! Get the traits object.
* Get the traits object.
* \return A pointer to the traits object. * \return A pointer to the traits object.
*/ */
Traits_2* get_traits () const Traits_2* get_traits() const { return (traits); }
{
return (traits);
}
protected: protected:
/*! Construct the lower/upper envelope of the given list of non-vertical
/*!
* Construct the lower/upper envelope of the given list of non-vertical
* curves. * curves.
* \param begin The first x-monotone curve. * \param begin The first x-monotone curve.
* \param end A past-the-end iterator for the curves. * \param end A past-the-end iterator for the curves.
* \param out_d Output: The minimization (or maximization) diagram. * \param out_d Output: The minimization (or maximization) diagram.
*/ */
void _construct_envelope_non_vertical (Curve_pointer_iterator begin, void _construct_envelope_non_vertical(Curve_pointer_iterator begin,
Curve_pointer_iterator end, Curve_pointer_iterator end,
Envelope_diagram_1& out_d); Envelope_diagram_1& out_d);
/*! /*! Construct a singleton diagram, which matches a single curve.
* Construct a singleton diagram, which matches a single curve.
* \param cv The x-monotone curve. * \param cv The x-monotone curve.
* \param out_d Output: The minimization (or maximization) diagram. * \param out_d Output: The minimization (or maximization) diagram.
*/ */
void _construct_singleton_diagram (const X_monotone_curve_2& cv, void _construct_singleton_diagram (const X_monotone_curve_2& cv,
Envelope_diagram_1& out_d); Envelope_diagram_1& out_d);
/* /* Merge two minimization (or maximization) diagrams.
* Merge two minimization (or maximization) diagrams.
* \param d1 The first diagram, * \param d1 The first diagram,
* representing the envelope of the curve set C1. * representing the envelope of the curve set C1.
* \param d1 The first diagram, * \param d1 The first diagram,
@ -222,12 +175,11 @@ protected:
* \param out_d Output: The merged diagram, representing the envelope of * \param out_d Output: The merged diagram, representing the envelope of
* the union of C1 and C2. * the union of C1 and C2.
*/ */
void _merge_envelopes (const Envelope_diagram_1& d1, void _merge_envelopes(const Envelope_diagram_1& d1,
const Envelope_diagram_1& d2, const Envelope_diagram_1& d2,
Envelope_diagram_1& out_d); Envelope_diagram_1& out_d);
/*! /*! Compare two vertices.
* Compare two vertices.
* \param v1 The first vertex. * \param v1 The first vertex.
* \param v2 The second vertex. * \param v2 The second vertex.
* \param same_x Output parameter: TRUE iff x(v1) = x(v2). * \param same_x Output parameter: TRUE iff x(v1) = x(v2).
@ -239,13 +191,12 @@ protected:
* - we compute the upper envelope, and y(v1) < y(v2). * - we compute the upper envelope, and y(v1) < y(v2).
* EQUAL if v1 = v2. * EQUAL if v1 = v2.
*/ */
Comparison_result _compare_vertices (Vertex_const_handle v1, Comparison_result _compare_vertices(Vertex_const_handle v1,
Vertex_const_handle v2, Vertex_const_handle v2,
bool& same_x) const; bool& same_x) const;
/*! /*! Deal with an interval which is non-empty in one of the merged diagrams
* Deal with an interval which is non-empty in one of the merged diagrams and * and empty in the other.
* empty in the other.
* \param e The non-empty edge. * \param e The non-empty edge.
* \param other_edge The empty edge. * \param other_edge The empty edge.
* \param v The next vertex to the right. * \param v The next vertex to the right.
@ -256,24 +207,24 @@ protected:
* the same place. * the same place.
* \param out_d The merged diagram. * \param out_d The merged diagram.
*/ */
void _merge_single_interval (Edge_const_handle e, void _merge_single_interval(Edge_const_handle e,
Edge_const_handle other_edge, Edge_const_handle other_edge,
Vertex_const_handle v, bool v_exists, Vertex_const_handle v, bool v_exists,
Comparison_result origin_of_v, Comparison_result origin_of_v,
Envelope_diagram_1& out_d); Envelope_diagram_1& out_d);
//! Compare the $y$-coordinates of two curves at their endpoints /*! Compare the $y$-coordinates of two curves at their endpoints
/*! The function compares the $y$ values of two curves with a joint * The function compares the $y$ values of two curves with a joint
range of $x$ values, at the end of the joint range. * range of $x$ values, at the end of the joint range.
\param xcv1 The first curve * \param xcv1 The first curve
\param xcv2 The second curve * \param xcv2 The second curve
\param curve_end ARR_MIN_END - compare the $y$ value of the smaller * \param curve_end ARR_MIN_END - compare the $y$ value of the smaller
endpoint, ARR_MAX_END - compare the $y$ value of the larger endpoint. * endpoint, ARR_MAX_END - compare the $y$ value of the larger endpoint.
\pre The two $x$-monotone curves need to have a partially overlapping * \pre The two $x$-monotone curves need to have a partially overlapping
$x$-ranges. * $x$-ranges.
\return * \return
\todo Move it to Arr_traits_adaptor ? * \todo Move it to Arr_traits_adaptor ?
*/ */
Comparison_result compare_y_at_end(const X_monotone_curve_2& xcv1, Comparison_result compare_y_at_end(const X_monotone_curve_2& xcv1,
const X_monotone_curve_2& xcv2, const X_monotone_curve_2& xcv2,
@ -281,8 +232,7 @@ protected:
/*! /*! Merge two non-empty intervals into the merged diagram.
* Merge two non-empty intervals into the merged diagram.
* \param e1 The first non-empty edge. * \param e1 The first non-empty edge.
* \param is_leftmost1 Is it the leftmost edge in its diagram. * \param is_leftmost1 Is it the leftmost edge in its diagram.
* \param e2 The second non-empty edge. * \param e2 The second non-empty edge.
@ -295,14 +245,13 @@ protected:
* is still taken from e2. * is still taken from e2.
* \param out_d The merged diagram. * \param out_d The merged diagram.
*/ */
void _merge_two_intervals (Edge_const_handle e1, bool is_leftmost1, void _merge_two_intervals(Edge_const_handle e1, bool is_leftmost1,
Edge_const_handle e2, bool is_leftmost2, Edge_const_handle e2, bool is_leftmost2,
Vertex_const_handle v, bool v_exists, Vertex_const_handle v, bool v_exists,
Comparison_result origin_of_v, Comparison_result origin_of_v,
Envelope_diagram_1& out_d); Envelope_diagram_1& out_d);
/*! /*! Append a vertex to the given diagram: The new vertex that represents the
* Append a vertex to the given diagram: The new vertex that represents the
* given point as the new rightmost vertex of the diagram. The edge * given point as the new rightmost vertex of the diagram. The edge
* between the current rightmost vertex and the new one contains the same * between the current rightmost vertex and the new one contains the same
* curves as the input edge. * curves as the input edge.
@ -311,52 +260,44 @@ protected:
* \param e The input edge. * \param e The input edge.
* \return A handle for the vertex. * \return A handle for the vertex.
*/ */
Vertex_handle _append_vertex (Envelope_diagram_1& diag, Vertex_handle _append_vertex(Envelope_diagram_1& diag,
const Point_2& p, Edge_const_handle e); const Point_2& p, Edge_const_handle e);
/*! \struct /*! \struct
* A functor used to sort vertical segments by their x-coordinate. * A functor used to sort vertical segments by their x-coordinate.
*/ */
class Less_vertical_segment class Less_vertical_segment {
{
private: private:
typename Traits_2::Compare_x_2 comp_x; typename Traits_2::Compare_x_2 comp_x;
typename Traits_2::Construct_min_vertex_2 min_vertex; typename Traits_2::Construct_min_vertex_2 min_vertex;
public: public:
Less_vertical_segment(const Traits_2 *traits) :
Less_vertical_segment (const Traits_2 *traits) :
comp_x(traits->compare_x_2_object()), comp_x(traits->compare_x_2_object()),
min_vertex(traits->construct_min_vertex_2_object()) min_vertex(traits->construct_min_vertex_2_object())
{} {}
bool operator() (const X_monotone_curve_2 *cv1, bool operator()(const X_monotone_curve_2* cv1,
const X_monotone_curve_2 *cv2) const const X_monotone_curve_2* cv2) const
{ { return(comp_x(min_vertex(*cv1), min_vertex(*cv2)) == SMALLER); }
return (comp_x (min_vertex (*cv1),
min_vertex (*cv2)) == SMALLER);
}
}; };
/*! /*! Merge the vertical segments into the lower/upper envelope given as a
* Merge the vertical segments into the lower/upper envelope given as a
* minimization (or maximization) diagram. * minimization (or maximization) diagram.
* \param vert_vec The list of vertical segments. * \param vert_vec The list of vertical segments.
* \param out_d The input minimization (or maximization) diagram. * \param out_d The input minimization (or maximization) diagram.
* The function merges the vertical segments into this diagram. * The function merges the vertical segments into this diagram.
*/ */
void _merge_vertical_segments (Curve_pointer_vector& vert_vec, void _merge_vertical_segments(Curve_pointer_vector& vert_vec,
Envelope_diagram_1& out_d); Envelope_diagram_1& out_d);
/*! /*! Split a given diagram edge by inserting a vertex in its interior.
* Split a given diagram edge by inserting a vertex in its interior.
* \param diag The diagram. * \param diag The diagram.
* \param p The point that the new vertex is associated with. * \param p The point that the new vertex is associated with.
* \param e The edge to split. * \param e The edge to split.
* \return A handle for the vertex. * \return A handle for the vertex.
*/ */
Vertex_handle _split_edge (Envelope_diagram_1& diag, Vertex_handle _split_edge(Envelope_diagram_1& diag,
const Point_2& p, Edge_handle e); const Point_2& p, Edge_handle e);
}; };