Introduced compare_xy()

This commit is contained in:
Efi Fogel 2018-03-21 19:04:12 +02:00
parent 52c2eaeec6
commit 98b4a49690
1 changed files with 400 additions and 13 deletions

View File

@ -18,7 +18,7 @@
// $Date$
//
//
// Author(s) : Ron Wein <wein@post.tau.ac.il>s
// Author(s): Ron Wein <wein@post.tau.ac.il>s
// Efi Fogel <efif@post.tau.ac.il>
// Eric Berberich <eric@mpi-inf.mpg.de>
// (based on old version by Iddo Hanniel
@ -27,6 +27,7 @@
// Efi Fogel
// Ron Wein
// Idit Haran)
#ifndef CGAL_ARR_TRAITS_ADAPTOR_2_H
#define CGAL_ARR_TRAITS_ADAPTOR_2_H
@ -73,6 +74,12 @@ public:
Right_side_category;
protected:
// All sides
typedef typename Arr_are_all_sides_oblivious_tag<Left_side_category,
Bottom_side_category,
Top_side_category,
Right_side_category>::result
Are_all_sides_oblivious_category;
// left-right dispatch
typedef CGAL::internal::Arr_left_right_implementation_dispatch<
@ -2270,10 +2277,10 @@ class Arr_traits_adaptor_2 :
public Arr_traits_basic_adaptor_2<ArrangementTraits_>
{
public:
// Traits-class geometric types.
typedef ArrangementTraits_ Base_traits_2;
typedef Arr_traits_basic_adaptor_2<ArrangementTraits_> Base;
typedef Arr_traits_basic_adaptor_2<Base_traits_2> Base;
typedef Arr_traits_adaptor_2<Base_traits_2> Self;
typedef typename Base_traits_2::Curve_2 Curve_2;
typedef typename Base::X_monotone_curve_2 X_monotone_curve_2;
@ -2289,6 +2296,9 @@ public:
typedef typename Base::Top_side_category Top_side_category;
typedef typename Base::Right_side_category Right_side_category;
typedef typename Base::Are_all_sides_oblivious_category
Are_all_sides_oblivious_category;
/// \name Construction.
//@{
/*! Default constructor. */
@ -2300,7 +2310,7 @@ public:
// Inherited functors:
typedef typename Base::Compare_x_2 Compare_x_2;
typedef typename Base::Compare_xy_2 Compare_xy_2;
// typedef typename Base::Compare_xy_2 Compare_xy_2;
typedef typename Base::Construct_min_vertex_2 Construct_min_vertex_2;
typedef typename Base::Construct_max_vertex_2 Construct_max_vertex_2;
typedef typename Base::Is_vertical_2 Is_vertical_2;
@ -2317,6 +2327,383 @@ public:
/// \name Overriden functors.
//@{
/*! A functor that compares two points or two x-monotone curves
* lexigoraphically. Twp points are compared firest by their x-coordinates,
* then by their y-coordinates. Two curves are compared first their left-most
* endpoint, then by the graphs, and finally by their right-most endpoint.
*/
class Compare_xy_2 {
public:
/*! Compare two points lexigoraphically: by x, then by y.
* \param p1 the first point.
* \param p2 the second point.
* \return SMALLER - x(p1) < x(p2);
* SMALLER - x(p1) = x(p2) and y(p1) < y(p2);
* EQUAL - x(p1) = x(p2) and y(p1) = y(p2);
* LARGER - x(p1) = x(p2) and y(p1) > y(p2);
* LARGER - x(p1) > x(p2).
* \pre p1 does not lie on the boundary.
* \pre p2 does not lie on the boundary.
*/
Comparison_result operator()(const Point_2& p1, const Point_2& p2) const
{
Base base(m_self);
return base.compare_xy_2_object()(p1, p2);
}
/*! Compare two x-monotone curves lexigoraphically.
* Input: C1, C2, intersections = empty
* compare(C1, C2, intersections)
* Compare the left-most points of C1 and C2.
* If not equal return the comparison result.
* Otherwise (the left-most points are equal)
* Compare C1 and C2 to the right of the point.
* If not equal return the comparison result.
* Otherwise (they overlap)
* If intersection is empty, compute the intersections,
* Remove the first overlapping section from c1, c2, and intersections.
* If intersections is empty
* Compare the right-most point and return the result.
* return compare(C1, C2, intersections).
*/
Comparison_result operator()(const X_monotone_curve_2& c1,
const X_monotone_curve_2& c2) const
{
std::list<CGAL::Object> intersections;
return operator()(c1, c2, intersections,
Are_all_sides_oblivious_category());
}
protected:
//! The base traits.
const Self& m_self;
/*! Constructor.
* \param trait The base traits class. It must be passed, to handle non
* stateless traits objects, (which stores data).
* The constructor is declared private to allow only the functor
* obtaining function, which is a member of the nesting class,
* constructing it.
*/
Compare_xy_2(const Self& self) : m_self(self) {}
//! Allow its functor obtaining function calling the private constructor.
friend class Arr_traits_adaptor_2<Base_traits_2>;
/*! Compare the max end of two x-monotone curves lexigoraphically.
*/
Comparison_result compare_max_end(const X_monotone_curve_2& c1,
const X_monotone_curve_2& c2,
Arr_all_sides_oblivious_tag tag) const
{
typedef typename Self::Construct_max_vertex_2 Construct_max_vertex_2;
Construct_max_vertex_2 ctr_max =
m_self.construct_max_vertex_2_object();
const Point_2& p1 = ctr_max(c1);
const Point_2& p2 = ctr_max(c2);
return operator()(p1, p2);
}
/*! Compare the max (right) end of two x-monotone curves lexigoraphically.
* \pre the curve overlap
*/
Comparison_result compare_max_end(const X_monotone_curve_2& c1,
const X_monotone_curve_2& c2,
Arr_not_all_sides_oblivious_tag tag) const
{
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;
Parameter_space_in_x_2 psx = m_self.parameter_space_in_x_2_object();
Parameter_space_in_y_2 psy = m_self.parameter_space_in_y_2_object();
Arr_parameter_space px1 = psx(c1, ARR_MAX_END);
Arr_parameter_space py1 = psy(c1, ARR_MAX_END);
Arr_parameter_space px2 = psx(c2, ARR_MAX_END);
Arr_parameter_space py2 = psy(c2, ARR_MAX_END);
// Handle the trivial cases:
if ((px1 == ARR_LEFT_BOUNDARY) && (px2 != ARR_LEFT_BOUNDARY))
return SMALLER;
if ((px2 == ARR_LEFT_BOUNDARY) && (px1 != ARR_LEFT_BOUNDARY))
return LARGER;
if ((px1 == ARR_RIGHT_BOUNDARY) && (px2 != ARR_RIGHT_BOUNDARY))
return LARGER;
if ((px2 == ARR_RIGHT_BOUNDARY) && (px1 != ARR_RIGHT_BOUNDARY))
return SMALLER;
// The only casese left are px1,px2 = (I,I), (L,L), and (R,R)
if (px1 == ARR_INTERIOR) {
CGAL_assertion(px2 == ARR_INTERIOR);
if ((py1 == ARR_INTERIOR) && (py2 == ARR_INTERIOR))
return compare_max_end(c1, c2, Arr_all_sides_oblivious_tag());
// px1, px2, py1 are interior
if (py1 == ARR_INTERIOR) {
CGAL_assertion(py2 != ARR_INTERIOR);
typedef typename Self::Compare_x_on_boundary_2 Compare_x_on_boundary_2;
Compare_x_on_boundary_2 cmp_x_on_bnd =
m_self.compare_x_on_boundary_2_object();
const Point_2& c1_max = m_self.construct_max_vertex_2_object()(c1);
Comparison_result res = cmp_x_on_bnd(c1_max, c2, ARR_MAX_END);
if (res != EQUAL) return res;
return (py2 == ARR_TOP_BOUNDARY) ? SMALLER : LARGER;
}
// px1, px2, py2 are interior
if (py2 == ARR_INTERIOR) {
CGAL_assertion(py1 != ARR_INTERIOR);
typedef typename Self::Compare_x_on_boundary_2 Compare_x_on_boundary_2;
Compare_x_on_boundary_2 cmp_x_on_bnd =
m_self.compare_x_on_boundary_2_object();
const Point_2& c2_max = m_self.construct_max_vertex_2_object()(c2);
Comparison_result res = cmp_x_on_bnd(c2_max, c1, ARR_MAX_END);
if (res != EQUAL) return CGAL::opposite(res);
return (py1 == ARR_BOTTOM_BOUNDARY) ? SMALLER : LARGER;
}
// Both py1 and py2 not interior
typedef typename Self::Compare_x_on_boundary_2 Compare_x_on_boundary_2;
Compare_x_on_boundary_2 cmp_x_on_bnd =
m_self.compare_x_on_boundary_2_object();
Comparison_result res = cmp_x_on_bnd(c1, ARR_MAX_END, c2, ARR_MAX_END);
if (res != EQUAL) return res;
if ((py1 == ARR_BOTTOM_BOUNDARY) && (py2 != ARR_BOTTOM_BOUNDARY))
return SMALLER;
if ((py1 == ARR_TOP_BOUNDARY) && (py2 != ARR_TOP_BOUNDARY))
return LARGER;
return EQUAL;
}
// Both endpoints lie either on the left boundary or on the right
// boundary, which means that their x-coordinates are equal.
// Handle the trivial cases:
if ((py1 == ARR_BOTTOM_BOUNDARY) && (py2 != ARR_BOTTOM_BOUNDARY))
return SMALLER;
if ((py1 == ARR_TOP_BOUNDARY) && (py2 != ARR_TOP_BOUNDARY))
return LARGER;
typedef typename Self::Compare_y_on_boundary_2 Compare_y_on_boundary_2;
Compare_y_on_boundary_2 cmp_y_on_bnd =
m_self.compare_y_on_boundary_2_object();
const Point_2& c1_max = m_self.construct_max_vertex_2_object()(c1);
const Point_2& c2_max = m_self.construct_max_vertex_2_object()(c2);
Comparison_result res = cmp_y_on_bnd(c1_max, c2_max);
return res;
}
/*! Compare two x-monotone curves lexigoraphically.
*/
Comparison_result operator()(const X_monotone_curve_2& c1,
const X_monotone_curve_2& c2,
std::list<CGAL::Object>& intersections,
Arr_all_sides_oblivious_tag tag) const
{
const Point_2& c1_min = m_self.construct_min_vertex_2_object()(c1);
const Point_2& c2_min = m_self.construct_min_vertex_2_object()(c2);
Comparison_result res = operator()(c1_min, c2_min);
if (res != EQUAL) return res;
// Left-most points are equal.
// Compare their slopes to their right:
typedef typename Self::Compare_y_at_x_right_2 Compare_y_at_x_right_2;
Compare_y_at_x_right_2 cmp_y_at_x_right =
m_self.compare_y_at_x_right_2_object();
res = cmp_y_at_x_right(c1, c2, c1_min);
if (res != EQUAL) return res;
// Right-most sections are equal.
// Advance to the next respective sections:
if (intersections.empty()) {
typedef typename Self::Intersect_2 Intersect_2;
Intersect_2 intersect = m_self.intersect_2_object();
intersect(c1, c2, std::back_inserter(intersections));
}
// Verify the first intersection is an overlap, remove it, and
// recursively call.
CGAL::Object first = intersections.front();
X_monotone_curve_2 xcv;
if (!assign(xcv, first)) {
CGAL_error_msg("The first intersection is not an overlap!");
return SMALLER;
}
intersections.pop_front();
if (intersections.empty())
return compare_max_end(c1, c2, Are_all_sides_oblivious_category());
// Otherwise, split and continue.
typedef typename Self::Split_2 Split_2;
Split_2 split = m_self.split_2_object();
X_monotone_curve_2 c11, c12, c21, c22;
const Point_2& p1 = ctr_max(xcv);
const Point_2& p2 = ctr_max(xcv);
split(c1, p1, c11, c12);
split(c2, p2, c21, c22);
return operator()(c12, c22, intersections, tag);
}
/*!
*/
Comparison_result operator()(const X_monotone_curve_2& c1,
const X_monotone_curve_2& c2,
std::list<CGAL::Object>& intersections,
Arr_not_all_sides_oblivious_tag) const
{
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;
Parameter_space_in_x_2 psx = m_self.parameter_space_in_x_2_object();
Parameter_space_in_y_2 psy = m_self.parameter_space_in_y_2_object();
Arr_parameter_space min_px1 = psx(c1, ARR_MIN_END);
Arr_parameter_space min_py1 = psy(c1, ARR_MIN_END);
Arr_parameter_space min_px2 = psx(c2, ARR_MIN_END);
Arr_parameter_space min_py2 = psy(c2, ARR_MIN_END);
// Handle the trivial cases:
if ((min_px1 == ARR_LEFT_BOUNDARY) && (min_px2 != ARR_LEFT_BOUNDARY))
return SMALLER;
if ((min_px2 == ARR_LEFT_BOUNDARY) && (min_px1 != ARR_LEFT_BOUNDARY))
return LARGER;
if ((min_px1 == ARR_RIGHT_BOUNDARY) && (min_px2 != ARR_RIGHT_BOUNDARY))
return LARGER;
if ((min_px2 == ARR_RIGHT_BOUNDARY) && (min_px1 != ARR_RIGHT_BOUNDARY))
return SMALLER;
// The only casese left are px1,px2 = (I,I), (L,L), and (R,R)
if (min_px1 == ARR_INTERIOR) {
CGAL_assertion(min_px2 == ARR_INTERIOR);
if ((min_py1 == ARR_INTERIOR) && (min_py2 == ARR_INTERIOR)) {
return operator()(c1, c2, intersections,
Arr_all_sides_oblivious_tag());
}
//
if (min_py1 == ARR_INTERIOR) {
CGAL_assertion(min_py2 != ARR_INTERIOR);
typedef typename Self::Compare_x_on_boundary_2 Compare_x_on_boundary_2;
Compare_x_on_boundary_2 cmp_x_on_bnd =
m_self.compare_x_on_boundary_2_object();
const Point_2& c1_min = m_self.construct_min_vertex_2_object()(c1);
Comparison_result res = cmp_x_on_bnd(c1_min, c2, ARR_MIN_END);
if (res != EQUAL) return res;
return (min_py2 == ARR_TOP_BOUNDARY) ? SMALLER : LARGER;
}
if (min_py2 == ARR_INTERIOR) {
CGAL_assertion(min_py1 != ARR_INTERIOR);
typedef typename Self::Compare_x_on_boundary_2 Compare_x_on_boundary_2;
Compare_x_on_boundary_2 cmp_x_on_bnd =
m_self.compare_x_on_boundary_2_object();
const Point_2& c2_min = m_self.construct_min_vertex_2_object()(c2);
Comparison_result res = cmp_x_on_bnd(c2_min, c1, ARR_MIN_END);
if (res != EQUAL) return CGAL::opposite(res);
return (min_py1 == ARR_BOTTOM_BOUNDARY) ? SMALLER : LARGER;
}
// Both min_py1 and min_py2 not interior
typedef typename Self::Compare_x_on_boundary_2 Compare_x_on_boundary_2;
Compare_x_on_boundary_2 cmp_x_on_bnd =
m_self.compare_x_on_boundary_2_object();
Comparison_result res = cmp_x_on_bnd(c1, ARR_MIN_END, c2, ARR_MIN_END);
if (res != EQUAL) return res;
if ((min_py1 == ARR_BOTTOM_BOUNDARY) && (min_py2 == ARR_TOP_BOUNDARY))
return SMALLER;
if ((min_py1 == ARR_TOP_BOUNDARY) && (min_py2 == ARR_BOTTOM_BOUNDARY))
return LARGER;
// Left-most points are equal.
// Compare their slopes to their right:
//! \todo
}
if ((min_py1 == ARR_BOTTOM_BOUNDARY) && (min_py2 != ARR_BOTTOM_BOUNDARY))
return SMALLER;
if ((min_py1 == ARR_TOP_BOUNDARY) && (min_py2 != ARR_TOP_BOUNDARY))
return LARGER;
// \todo what if open?
if (min_px1 == ARR_LEFT_BOUNDARY) {
// The min points of the two curves lie on the left boundary.
CGAL_assertion(min_px2 == ARR_LEFT_BOUNDARY);
typedef typename Self::Compare_y_on_boundary_2 Compare_y_on_boundary_2;
Compare_y_on_boundary_2 cmp_y_on_bnd =
m_self.compare_y_on_boundary_2_object();
const Point_2& c1_min = m_self.construct_min_vertex_2_object()(c1);
const Point_2& c2_min = m_self.construct_min_vertex_2_object()(c2);
Comparison_result res = cmp_y_on_bnd(c1_min, c2_min);
if (res != EQUAL) return res;
typedef typename Self::Is_vertical_2 Is_vertical_2;
Is_vertical_2 is_vert = m_self.is_vertical_2_object();
bool vert1 = is_vert(c1);
bool vert2 = is_vert(c2);
if (vert1 && ! vert2) return SMALLER;
if (vert2 && ! vert1) return LARGER;
if (vert1 && vert2) {
const Point_2& c1_max = m_self.construct_max_vertex_2_object()(c1);
const Point_2& c2_max = m_self.construct_max_vertex_2_object()(c2);
res = cmp_y_on_bnd(c1_max, c2_max);
if (res == SMALLER) return SMALLER;
}
// Compare slightly to the right near the boundary.
typedef typename Self::Compare_y_near_boundary_2
Compare_y_near_boundary_2;
Compare_y_near_boundary_2 cmp_y_near_bnd =
m_self.compare_y_near_boundary_2_object();
res = cmp_y_near_bnd(c1, c2, CGAL::ARR_MIN_END);
if (res == SMALLER) return SMALLER;
//! \todo
}
// \todo what if open
if (min_px1 == ARR_RIGHT_BOUNDARY) {
// The min points of the two curves lie on the right boundary.
// It implies that the entire curves lie on the right boundary, and
// thus both are vertical.
CGAL_assertion(min_px2 == ARR_RIGHT_BOUNDARY);
typedef typename Self::Compare_y_on_boundary_2 Compare_y_on_boundary_2;
Compare_y_on_boundary_2 cmp_y_on_bnd =
m_self.compare_y_on_boundary_2_object();
const Point_2& c1_min = m_self.construct_min_vertex_2_object()(c1);
const Point_2& c2_min = m_self.construct_min_vertex_2_object()(c2);
Comparison_result res = cmp_y_on_bnd(c1_min, c2_min);
if (res != EQUAL) return res;
const Point_2& c1_max = m_self.construct_max_vertex_2_object()(c1);
const Point_2& c2_max = m_self.construct_max_vertex_2_object()(c2);
res = cmp_y_on_bnd(c1_max, c2_max);
if (res == SMALLER) return SMALLER;
//! \todo
}
return EQUAL;
}
};
/*! Obtain a Compare_xy_2 function object */
Compare_xy_2 compare_xy_2_object() const { return Compare_xy_2(*this); }
/*! A functor that tests whether two x-monotone curves can be merged. */
class Are_mergeable_2 {
public: