mirror of https://github.com/CGAL/cgal
bug fix
This commit is contained in:
parent
49bdb725f6
commit
e06b7c0165
|
|
@ -21,8 +21,12 @@
|
||||||
|
|
||||||
#include <CGAL/Arr_enums.h>
|
#include <CGAL/Arr_enums.h>
|
||||||
#include <CGAL/Arrangement_2/Arr_traits_adaptor_2.h>
|
#include <CGAL/Arrangement_2/Arr_traits_adaptor_2.h>
|
||||||
|
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
CGAL_BEGIN_NAMESPACE
|
CGAL_BEGIN_NAMESPACE
|
||||||
|
|
||||||
/*! \class
|
/*! \class
|
||||||
|
|
@ -263,6 +267,42 @@ protected:
|
||||||
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);
|
||||||
|
|
||||||
|
//! Checks whether a curve-end is in the parameter space interior.
|
||||||
|
/*!
|
||||||
|
\param xcv The curve
|
||||||
|
\param curve_end The end of the curve to be checked.
|
||||||
|
\return True, if the curve-end is inside the parameter space, false,
|
||||||
|
otherwise.
|
||||||
|
\todo Move to Arr_traits_adaptor.
|
||||||
|
*/
|
||||||
|
bool is_in_interior_of_parameter_space(const X_monotone_curve_2& xcv,
|
||||||
|
Arr_curve_end curve_end) const;
|
||||||
|
|
||||||
|
|
||||||
|
boost::optional<Point_2> get_joint_endpoint(const X_monotone_curve_2& xcv1,
|
||||||
|
const X_monotone_curve_2& xcv2,
|
||||||
|
Arr_curve_end curve_end,
|
||||||
|
Comparison_result &out_origin)
|
||||||
|
const;
|
||||||
|
|
||||||
|
//! Compare the $y$-coordinates of two curves at their endpoints
|
||||||
|
/*! The function compares the $y$ values of two curves with a joint
|
||||||
|
range of $x$ values, at the end of the joint range.
|
||||||
|
\param xcv1 The first curve
|
||||||
|
\param xcv2 The second curve
|
||||||
|
\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.
|
||||||
|
\pre The two $x$-monotone curves need to have a partially overlapping
|
||||||
|
$x$-ranges.
|
||||||
|
\return
|
||||||
|
\todo Move it to Arr_traits_adaptor ?
|
||||||
|
*/
|
||||||
|
Comparison_result compare_y_at_end(const X_monotone_curve_2& xcv1,
|
||||||
|
const X_monotone_curve_2& xcv2,
|
||||||
|
Arr_curve_end curve_end) const;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Merge two non-empty intervals into the merged diagram.
|
* Merge two non-empty intervals into the merged diagram.
|
||||||
|
|
|
||||||
|
|
@ -23,25 +23,10 @@
|
||||||
* Definitions of the functions of the Envelope_divide_and_conquer_2 class.
|
* Definitions of the functions of the Envelope_divide_and_conquer_2 class.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
CGAL_BEGIN_NAMESPACE
|
CGAL_BEGIN_NAMESPACE
|
||||||
|
|
||||||
/*! \todo Make the handlers default constructibe
|
|
||||||
* Some compilers complain that the handlers are not initialized. Currently,
|
|
||||||
* there is no requirement from the concepts they model respectively to
|
|
||||||
* have default constructors. The following is a work around.
|
|
||||||
*/
|
|
||||||
template <typename Handle>
|
|
||||||
class Vertex_initializer {
|
|
||||||
public:
|
|
||||||
void operator()(Handle & handle) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Vertex>
|
|
||||||
class Vertex_initializer<Vertex *> {
|
|
||||||
public:
|
|
||||||
void operator()(Vertex * & handle) {handle = NULL; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Construct the lower/upper envelope of the given list of non-vertical curves.
|
// Construct the lower/upper envelope of the given list of non-vertical curves.
|
||||||
//
|
//
|
||||||
|
|
@ -243,11 +228,6 @@ _merge_envelopes (const Envelope_diagram_1& d1,
|
||||||
Comparison_result res_v = EQUAL;
|
Comparison_result res_v = EQUAL;
|
||||||
bool same_x = false;
|
bool same_x = false;
|
||||||
|
|
||||||
Vertex_initializer<Vertex_const_handle> v_init;
|
|
||||||
v_init(v1);
|
|
||||||
v_init(v2);
|
|
||||||
v_init(next_v);
|
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
// Locate the vertex that has smaller x-coordinate between v1 and v2.
|
// Locate the vertex that has smaller x-coordinate between v1 and v2.
|
||||||
|
|
@ -466,6 +446,136 @@ _merge_single_interval (Edge_const_handle e, Edge_const_handle other_edge,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! \brief Functions that should be on Arr_traits_adaptor.
|
||||||
|
/*@{*/
|
||||||
|
|
||||||
|
inline
|
||||||
|
Arr_curve_end
|
||||||
|
operator-(Arr_curve_end o)
|
||||||
|
{ return static_cast<Arr_curve_end>( - static_cast<int>(o)); }
|
||||||
|
|
||||||
|
//! Checks whether a curve-end is in the parameter space interior.
|
||||||
|
/*!
|
||||||
|
\param xcv The curve
|
||||||
|
\param curve_end The end of the curve to be checked.
|
||||||
|
\return True, if the curve-end is inside the parameter space, false,
|
||||||
|
otherwise.
|
||||||
|
\todo Move to Arr_traits_adaptor.
|
||||||
|
*/
|
||||||
|
template <class Traits, class Diagram>
|
||||||
|
bool Envelope_divide_and_conquer_2<Traits,Diagram>::
|
||||||
|
is_in_interior_of_parameter_space(const X_monotone_curve_2& xcv,
|
||||||
|
Arr_curve_end curve_end) const
|
||||||
|
{
|
||||||
|
Arr_parameter_space ps = traits->parameter_space_in_x_2_object ()
|
||||||
|
(xcv, curve_end);
|
||||||
|
if (ps != ARR_INTERIOR)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ps = traits->parameter_space_in_y_2_object () (xcv, curve_end);
|
||||||
|
if (ps != ARR_INTERIOR)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Traits, class Diagram>
|
||||||
|
boost::optional<typename Traits::Point_2>
|
||||||
|
Envelope_divide_and_conquer_2<Traits,Diagram>::
|
||||||
|
get_joint_endpoint(const X_monotone_curve_2& xcv1,
|
||||||
|
const X_monotone_curve_2& xcv2,
|
||||||
|
Arr_curve_end curve_end,
|
||||||
|
Comparison_result &out_origin) const
|
||||||
|
{
|
||||||
|
bool x1_bounded = is_in_interior_of_parameter_space (xcv1, curve_end);
|
||||||
|
bool x2_bounded = is_in_interior_of_parameter_space (xcv2, curve_end);
|
||||||
|
|
||||||
|
boost::optional<Point_2> p1, p2;
|
||||||
|
if (curve_end == ARR_MIN_END)
|
||||||
|
{
|
||||||
|
if (x1_bounded)
|
||||||
|
p1 = traits->construct_min_vertex_2_object() (xcv1);
|
||||||
|
if (x2_bounded)
|
||||||
|
p2 = traits->construct_min_vertex_2_object() (xcv2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (x1_bounded)
|
||||||
|
p1 = traits->construct_max_vertex_2_object() (xcv1);
|
||||||
|
if (x2_bounded)
|
||||||
|
p2 = traits->construct_max_vertex_2_object() (xcv2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Comparison_result wanted_res = (curve_end == ARR_MIN_END) ? SMALLER : LARGER;
|
||||||
|
|
||||||
|
boost::optional<Point_2> p;
|
||||||
|
out_origin = EQUAL;
|
||||||
|
if (p1 && p2)
|
||||||
|
{
|
||||||
|
if (traits->compare_x_2_object() (*p1, *p2) == wanted_res)
|
||||||
|
{
|
||||||
|
p = *p2; out_origin = LARGER;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = *p1; out_origin = SMALLER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (p1 && !p2)
|
||||||
|
{
|
||||||
|
p = p1; out_origin = SMALLER;
|
||||||
|
}
|
||||||
|
else if (!p1 && p2)
|
||||||
|
{
|
||||||
|
p = p2; out_origin = LARGER;
|
||||||
|
}
|
||||||
|
|
||||||
|
CGAL_postcondition(!p || out_origin != EQUAL);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Compare the $y$-coordinates of two curves at their endpoints
|
||||||
|
/*! The function compares the $y$ values of two curves with a joint
|
||||||
|
range of $x$ values, at the end of the joint range.
|
||||||
|
\param xcv1 The first curve
|
||||||
|
\param xcv2 The second curve
|
||||||
|
\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.
|
||||||
|
\pre The two $x$-monotone curves need to have a partially overlapping
|
||||||
|
$x$-ranges.
|
||||||
|
\return
|
||||||
|
\todo Move it to Arr_traits_adaptor ?
|
||||||
|
*/
|
||||||
|
template <class Traits, class Diagram>
|
||||||
|
Comparison_result Envelope_divide_and_conquer_2<Traits,Diagram>::
|
||||||
|
compare_y_at_end(const X_monotone_curve_2& xcv1,
|
||||||
|
const X_monotone_curve_2& xcv2,
|
||||||
|
Arr_curve_end curve_end) const
|
||||||
|
{
|
||||||
|
// \todo Extend it to ARR_MAX_END
|
||||||
|
|
||||||
|
CGAL_precondition (traits->is_in_x_range_2_object() (xcv1, xcv2));
|
||||||
|
|
||||||
|
boost::optional<Point_2> p;
|
||||||
|
Comparison_result p_origin = SMALLER;
|
||||||
|
p = get_joint_endpoint(xcv1, xcv2, curve_end, p_origin);
|
||||||
|
if (!p)
|
||||||
|
p = get_joint_endpoint(xcv1, xcv2, CGAL::opposite(curve_end), p_origin);
|
||||||
|
|
||||||
|
Comparison_result res = EQUAL;
|
||||||
|
if (p)
|
||||||
|
{
|
||||||
|
res = traits->compare_y_at_x_2_object()(*p, ((p_origin == SMALLER)
|
||||||
|
? xcv2 : xcv1));
|
||||||
|
res = (p_origin == SMALLER ? res : CGAL::opposite(res));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
res = traits->compare_y_position_2_object() (xcv1, xcv2);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Merge two non-empty intervals into the merged diagram.
|
// Merge two non-empty intervals into the merged diagram.
|
||||||
//
|
//
|
||||||
|
|
@ -479,47 +589,47 @@ _merge_two_intervals (Edge_const_handle e1, bool is_leftmost1,
|
||||||
{
|
{
|
||||||
// Get the relative position of two curves associated with e1 and e2
|
// Get the relative position of two curves associated with e1 and e2
|
||||||
// at the rightmost of the left endpoints of e1 and e2.
|
// at the rightmost of the left endpoints of e1 and e2.
|
||||||
Comparison_result u_res;
|
Comparison_result current_res;
|
||||||
bool equal_at_v = false;
|
bool equal_at_v = false;
|
||||||
Point_2 pu;
|
boost::optional<Point_2> last_ip; // last observed intersetion point.
|
||||||
bool pu_exists = false;
|
|
||||||
|
|
||||||
u_res = traits->compare_y_position_2_object() (e1->curve(),
|
|
||||||
e2->curve());
|
// We actually cannot use this function because the curves do not have
|
||||||
|
// to be interior disjoint. This function needs a review.
|
||||||
|
current_res = compare_y_at_end(e1->curve(), e2->curve(), ARR_MIN_END);
|
||||||
// Flip the result in case of an upper envelope.
|
// Flip the result in case of an upper envelope.
|
||||||
if (env_type == UPPER)
|
if (env_type == UPPER)
|
||||||
u_res = CGAL::opposite (u_res);
|
current_res = CGAL::opposite (current_res);
|
||||||
|
|
||||||
|
|
||||||
// Use the current rightmost of the two left vertices as a reference point.
|
// Use the current rightmost of the two left vertices as a reference point.
|
||||||
bool v_rm_exists = true;
|
// This is the rightmost vertex in the current minimization diagram (out_d).
|
||||||
Vertex_const_handle v_rm;
|
// The intersection points/curves that interest us are the ones in
|
||||||
Vertex_initializer<Vertex_const_handle> v_init;
|
// [v_leftmost, v].
|
||||||
v_init(v_rm);
|
boost::optional<Vertex_const_handle> v_leftmost;
|
||||||
|
|
||||||
if (is_leftmost1)
|
if (is_leftmost1 == true)
|
||||||
{
|
{
|
||||||
if (is_leftmost2)
|
if (is_leftmost2 == false)
|
||||||
v_rm_exists = false;
|
v_leftmost = e2->left();
|
||||||
else
|
|
||||||
v_rm = e2->left();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (is_leftmost2)
|
if (is_leftmost2 == true)
|
||||||
v_rm = e1->left();
|
v_leftmost = e1->left();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((traits->compare_xy_2_object() (e1->left()->point(),
|
if ((traits->compare_xy_2_object() (e1->left()->point(),
|
||||||
e2->left()->point()) == LARGER))
|
e2->left()->point()) == LARGER))
|
||||||
v_rm = e1->left();
|
v_leftmost = e1->left();
|
||||||
else
|
else
|
||||||
v_rm = e2->left();
|
v_leftmost = e2->left();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the next intersection of the envelopes to the right of the current
|
// Find the next intersection of the envelopes to the right of the current
|
||||||
// rightmost point in the merged diagram.
|
// rightmost point in the merged diagram.
|
||||||
|
// \todo Use the faster object_cast.
|
||||||
std::list<CGAL::Object> objects;
|
std::list<CGAL::Object> objects;
|
||||||
CGAL::Object obj;
|
CGAL::Object obj;
|
||||||
X_monotone_curve_2 intersection_curve;
|
X_monotone_curve_2 intersection_curve;
|
||||||
|
|
@ -537,83 +647,87 @@ _merge_two_intervals (Edge_const_handle e1, bool is_leftmost1,
|
||||||
if (CGAL::assign(intersection_point, obj))
|
if (CGAL::assign(intersection_point, obj))
|
||||||
{
|
{
|
||||||
// We have a simple intersection point.
|
// We have a simple intersection point.
|
||||||
if (v_rm_exists &&
|
bool is_in_x_range = true; // true if the intersection point is to the
|
||||||
|
// right of v_leftmost.
|
||||||
|
// check if we are before the leftmost point.
|
||||||
|
if (v_leftmost &&
|
||||||
traits->compare_xy_2_object() (intersection_point.first,
|
traits->compare_xy_2_object() (intersection_point.first,
|
||||||
v_rm->point()) != LARGER)
|
(*v_leftmost)->point()) != LARGER)
|
||||||
{
|
{
|
||||||
// The point is to the left of the current rightmost vertex in out_d,
|
// The point is to the left of the current rightmost vertex in out_d,
|
||||||
// so we skip it and continue examining the next intersections.
|
// so we skip it and continue examining the next intersections.
|
||||||
// However, we update the last intersection point observed.
|
// However, we update the last intersection point observed.
|
||||||
pu = intersection_point.first;
|
is_in_x_range = false;
|
||||||
pu_exists = true;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v_exists)
|
// check if we arrived at the rightmost point (stop if indeed we are
|
||||||
|
// there).
|
||||||
|
if (is_in_x_range && v_exists)
|
||||||
{
|
{
|
||||||
Comparison_result res = traits->compare_xy_2_object()
|
Comparison_result res = traits->compare_xy_2_object()
|
||||||
(intersection_point.first, v->point());
|
(intersection_point.first, v->point());
|
||||||
|
|
||||||
|
// v is an intersection points, so both curves are equal there:
|
||||||
if (res == EQUAL)
|
if (res == EQUAL)
|
||||||
// v is an intersection points, so both curves are equal there:
|
|
||||||
equal_at_v = true;
|
equal_at_v = true;
|
||||||
|
|
||||||
if (res != SMALLER)
|
// We passed the next vertex, so we can stop here.
|
||||||
|
if (res == LARGER)
|
||||||
{
|
{
|
||||||
// We passed the next vertex, so we can stop here.
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new vertex in the output diagram that corrsponds to the
|
// Create a new vertex in the output diagram that corrsponds to the
|
||||||
// current intersection point.
|
// current intersection point.
|
||||||
Vertex_handle new_v;
|
if (is_in_x_range)
|
||||||
|
|
||||||
if (pu_exists)
|
|
||||||
{
|
{
|
||||||
// Update the relative position of the two curves, which is their
|
Vertex_handle new_v;
|
||||||
// order immediately to the right of their last observed intersection
|
|
||||||
// point pu.
|
if (current_res == SMALLER)
|
||||||
u_res = traits->compare_y_at_x_right_2_object() (e1->curve(),
|
new_v = _append_vertex (out_d, intersection_point.first, e1);
|
||||||
e2->curve(),
|
else
|
||||||
pu);
|
new_v = _append_vertex (out_d, intersection_point.first, e2);
|
||||||
|
|
||||||
if (env_type == UPPER)
|
// if we are at v, then this is a special case that is handled after
|
||||||
u_res = CGAL::opposite (u_res);
|
// the loop. We need to add the curves from the original vertices.
|
||||||
|
if (equal_at_v == false)
|
||||||
|
{
|
||||||
|
// Note that the new vertex is incident to all curves in e1 and in e2.
|
||||||
|
new_v->add_curves (e1->curves_begin(), e1->curves_end());
|
||||||
|
new_v->add_curves (e2->curves_begin(), e2->curves_end());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the handle to the rightmost vertex in the output diagram.
|
||||||
|
v_leftmost = new_v;
|
||||||
}
|
}
|
||||||
CGAL_assertion (u_res != EQUAL);
|
|
||||||
|
|
||||||
if (u_res == SMALLER)
|
|
||||||
new_v = _append_vertex (out_d, intersection_point.first, e1);
|
|
||||||
else
|
|
||||||
new_v = _append_vertex (out_d, intersection_point.first, e2);
|
|
||||||
|
|
||||||
// Note that the new vertex is incident to all curves in e1 and in e2.
|
|
||||||
new_v->add_curves (e1->curves_begin(), e1->curves_end());
|
|
||||||
new_v->add_curves (e2->curves_begin(), e2->curves_end());
|
|
||||||
|
|
||||||
// Update the handle to the rightmost vertex in the output diagram.
|
|
||||||
v_rm = new_v;
|
|
||||||
v_rm_exists = true;
|
|
||||||
|
|
||||||
|
// Update the relative position of the two curves, which is their
|
||||||
|
// order immediately to the right of their last observed intersection
|
||||||
|
// point last_ip.
|
||||||
|
|
||||||
// Get the curve order immediately to the right of the intersection
|
// Get the curve order immediately to the right of the intersection
|
||||||
// point. Note that in case of even (non-zero) multiplicity the order
|
// point. Note that in case of even (non-zero) multiplicity the order
|
||||||
// remains the same.
|
// remains the same.
|
||||||
if (intersection_point.second % 2 == 1)
|
if (current_res != EQUAL && intersection_point.second % 2 == 1)
|
||||||
{
|
{
|
||||||
// Odd multiplicity: flip the current comparison result.
|
// Odd multiplicity: flip the current comparison result.
|
||||||
u_res = CGAL::opposite (u_res);
|
current_res = CGAL::opposite (current_res);
|
||||||
}
|
}
|
||||||
else if (intersection_point.second == 0)
|
else if (intersection_point.second == 0 && equal_at_v == false)
|
||||||
{
|
{
|
||||||
// The multiplicity is unknown, so we have to compare the curves to
|
// The multiplicity is unknown, so we have to compare the curves to
|
||||||
// the right of their intersection point.
|
// the right of their intersection point.
|
||||||
u_res = traits->compare_y_at_x_right_2_object()
|
current_res = traits->compare_y_at_x_right_2_object()
|
||||||
(e1->curve(),
|
(e1->curve(),
|
||||||
e2->curve(),
|
e2->curve(),
|
||||||
intersection_point.first);
|
intersection_point.first);
|
||||||
CGAL_assertion (u_res != EQUAL);
|
// Flip the result in case of an upper envelope.
|
||||||
|
if (env_type == UPPER)
|
||||||
|
current_res = CGAL::opposite (current_res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
last_ip = intersection_point.first;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -621,123 +735,140 @@ _merge_two_intervals (Edge_const_handle e1, bool is_leftmost1,
|
||||||
// curves.
|
// curves.
|
||||||
bool assign_success = CGAL::assign (intersection_curve, obj);
|
bool assign_success = CGAL::assign (intersection_curve, obj);
|
||||||
|
|
||||||
CGAL_assertion (assign_success);
|
|
||||||
if (! assign_success)
|
if (! assign_success)
|
||||||
continue;
|
CGAL_error_msg ("unrecognized intersection object.");
|
||||||
|
|
||||||
// Get the endpoints of the overlapping curves.
|
// Get the endpoints of the overlapping curves.
|
||||||
const bool has_left =
|
const bool has_left =
|
||||||
(traits->parameter_space_in_x_2_object() (intersection_curve, ARR_MIN_END) == ARR_INTERIOR);
|
(traits->parameter_space_in_x_2_object()
|
||||||
|
(intersection_curve, ARR_MIN_END) == ARR_INTERIOR);
|
||||||
const bool has_right =
|
const bool has_right =
|
||||||
(traits->parameter_space_in_x_2_object() (intersection_curve, ARR_MAX_END) == ARR_INTERIOR);
|
(traits->parameter_space_in_x_2_object()
|
||||||
Point_2 p1, p2;
|
(intersection_curve, ARR_MAX_END) == ARR_INTERIOR);
|
||||||
|
Point_2 p_left, p_right;
|
||||||
|
|
||||||
if (has_left)
|
if (has_left)
|
||||||
p1 = traits->construct_min_vertex_2_object() (intersection_curve);
|
p_left = traits->construct_min_vertex_2_object() (intersection_curve);
|
||||||
|
|
||||||
if (has_right)
|
if (has_right)
|
||||||
p2 = traits->construct_max_vertex_2_object() (intersection_curve);
|
p_right = traits->construct_max_vertex_2_object() (intersection_curve);
|
||||||
|
|
||||||
|
if (has_right)
|
||||||
|
{
|
||||||
|
last_ip = p_right;
|
||||||
|
}
|
||||||
|
else if (has_left)
|
||||||
|
last_ip = p_left;
|
||||||
|
|
||||||
|
bool is_in_x_range = true;
|
||||||
// Check if the overlapping curve is not relevant to our range.
|
// Check if the overlapping curve is not relevant to our range.
|
||||||
if (v_rm_exists && has_right &&
|
if (v_leftmost && has_right &&
|
||||||
traits->compare_xy_2_object() (p2,
|
traits->compare_xy_2_object() (p_right,
|
||||||
v_rm->point()) != LARGER)
|
(*v_leftmost)->point()) != LARGER)
|
||||||
{
|
{
|
||||||
// The right point of the overlappinf curve is to the left of the
|
// The right point of the overlappinf curve is to the left of the
|
||||||
// current rightmost vertex in out_d, so we skip it and continue
|
// current rightmost vertex in out_d, so we skip it and continue
|
||||||
// examining the next intersections.
|
// examining the next intersections.
|
||||||
// However, we update the last intersection point observed.
|
// However, we update the last intersection point observed.
|
||||||
pu = p2;
|
is_in_x_range = false;
|
||||||
pu_exists = true;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v_exists && has_right)
|
if (is_in_x_range && v_exists && has_left)
|
||||||
{
|
{
|
||||||
Comparison_result res = traits->compare_xy_2_object() (p1,
|
Comparison_result res = traits->compare_xy_2_object() (p_left,
|
||||||
v->point());
|
v->point());
|
||||||
|
|
||||||
|
// v is an intersection points, so both curves are equal there:
|
||||||
if (res == EQUAL)
|
if (res == EQUAL)
|
||||||
// v is an intersection points, so both curves are equal there:
|
|
||||||
equal_at_v = true;
|
|
||||||
|
|
||||||
if (res != SMALLER)
|
|
||||||
{
|
{
|
||||||
// We passed the next vertex, so we can stop here.
|
equal_at_v = true;
|
||||||
|
last_ip = p_left;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We passed the next vertex, so we can stop here.
|
||||||
|
if (res == LARGER)
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// There is an overlap between the range [u, v] and intersection_curve.
|
// There is an overlap between the range [u, v] and intersection_curve.
|
||||||
if (has_left &&
|
if (is_in_x_range && has_left &&
|
||||||
(! v_rm_exists ||
|
(! v_leftmost ||
|
||||||
traits->compare_xy_2_object() (p1,
|
traits->compare_xy_2_object() (p_left,
|
||||||
v_rm->point()) == LARGER))
|
(*v_leftmost)->point()) == LARGER))
|
||||||
{
|
{
|
||||||
// Create an output edge that represent the portion of [u, v] to the
|
// Create an output edge that represent the portion of [u, v] to the
|
||||||
// left of the overlapping curve.
|
// left of the overlapping curve.
|
||||||
Vertex_handle new_v;
|
Vertex_handle new_v;
|
||||||
|
|
||||||
if (pu_exists)
|
if (current_res == SMALLER)
|
||||||
{
|
new_v = _append_vertex (out_d, p_left, e1);
|
||||||
// Update the relative position of the two curves, which is their
|
|
||||||
// order immediately to the right of their last observed intersection
|
|
||||||
// point pu.
|
|
||||||
u_res = traits->compare_y_at_x_right_2_object() (e1->curve(),
|
|
||||||
e2->curve(),
|
|
||||||
pu);
|
|
||||||
|
|
||||||
if (env_type == UPPER)
|
|
||||||
u_res = CGAL::opposite (u_res);
|
|
||||||
}
|
|
||||||
CGAL_assertion (u_res != EQUAL);
|
|
||||||
|
|
||||||
if (u_res == SMALLER)
|
|
||||||
new_v = _append_vertex (out_d, intersection_point.first, e1);
|
|
||||||
else
|
else
|
||||||
new_v = _append_vertex (out_d, intersection_point.first, e2);
|
new_v = _append_vertex (out_d, p_left, e2);
|
||||||
|
|
||||||
|
// if we are at v, then this is a special case that is handled after
|
||||||
|
// the loop. We need to add the curves from the original vertices.
|
||||||
|
if (equal_at_v == false)
|
||||||
|
{
|
||||||
|
// Note that the new vertex is incident to all curves in e1 and
|
||||||
|
// in e2.
|
||||||
|
new_v->add_curves (e1->curves_begin(), e1->curves_end());
|
||||||
|
new_v->add_curves (e2->curves_begin(), e2->curves_end());
|
||||||
|
}
|
||||||
|
|
||||||
// Note that the new vertex is incident to all curves in e1 and
|
|
||||||
// in e2.
|
|
||||||
new_v->add_curves (e1->curves_begin(), e1->curves_end());
|
|
||||||
new_v->add_curves (e2->curves_begin(), e2->curves_end());
|
|
||||||
|
|
||||||
// Update the handle to the rightmost vertex in the output diagram.
|
// Update the handle to the rightmost vertex in the output diagram.
|
||||||
v_rm = new_v;
|
v_leftmost = new_v;
|
||||||
v_rm_exists = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_right &&
|
if (is_in_x_range && has_right &&
|
||||||
(! v_exists ||
|
(! v_exists ||
|
||||||
traits->compare_xy_2_object() (p2,
|
traits->compare_xy_2_object() (p_right,
|
||||||
v->point()) == SMALLER))
|
v->point()) == SMALLER))
|
||||||
{
|
{
|
||||||
// Create an edge that represents the overlapping curve.
|
// Create an edge that represents the overlapping curve.
|
||||||
Vertex_handle new_v;
|
Vertex_handle new_v;
|
||||||
|
|
||||||
new_v = _append_vertex (out_d, intersection_point.first, e1);
|
new_v = _append_vertex (out_d, p_right, e1);
|
||||||
new_v->left()->add_curves (e2->curves_begin(), e2->curves_end());
|
new_v->left()->add_curves (e2->curves_begin(), e2->curves_end());
|
||||||
|
|
||||||
new_v->add_curves (e1->curves_begin(), e1->curves_end());
|
// if we are at v, then this is a special case that is handled after
|
||||||
new_v->add_curves (e2->curves_begin(), e2->curves_end());
|
// the loop. We need to add the curves from the original vertices.
|
||||||
|
if (equal_at_v == false)
|
||||||
|
{
|
||||||
|
new_v->add_curves (e1->curves_begin(), e1->curves_end());
|
||||||
|
new_v->add_curves (e2->curves_begin(), e2->curves_end());
|
||||||
|
}
|
||||||
|
|
||||||
// Update the handle to the rightmost vertex in the output diagram.
|
// Update the handle to the rightmost vertex in the output diagram.
|
||||||
v_rm = new_v;
|
v_leftmost = new_v;
|
||||||
v_rm_exists = true;
|
|
||||||
|
|
||||||
// Compare the curves to the right of p2.
|
|
||||||
u_res = traits->compare_y_at_x_right_2_object() (e1->curve(),
|
|
||||||
e2->curve(),
|
|
||||||
p2);
|
|
||||||
CGAL_assertion (u_res != EQUAL);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (has_right == false ||
|
||||||
|
(v_exists && traits->compare_xy_2_object() (p_right,
|
||||||
|
v->point()) != SMALLER))
|
||||||
{
|
{
|
||||||
// The overlapping curves reaches v.
|
// The overlapping curves reaches v.
|
||||||
|
if (v_exists)
|
||||||
|
{
|
||||||
|
Vertex_handle new_v;
|
||||||
|
new_v = _append_vertex (out_d, v->point(), e1);
|
||||||
|
new_v->left()->add_curves (e2->curves_begin(), e2->curves_end());
|
||||||
|
last_ip = v->point();
|
||||||
|
}
|
||||||
|
|
||||||
equal_at_v = true;
|
equal_at_v = true;
|
||||||
u_res = EQUAL;
|
current_res = EQUAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compare the curves to the right of p_right.
|
||||||
|
current_res = traits->compare_y_at_x_right_2_object() (e1->curve(),
|
||||||
|
e2->curve(),
|
||||||
|
*last_ip);
|
||||||
|
// Flip the result in case of an upper envelope.
|
||||||
|
if (env_type == UPPER)
|
||||||
|
current_res = CGAL::opposite (current_res);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -748,26 +879,21 @@ _merge_two_intervals (Edge_const_handle e1, bool is_leftmost1,
|
||||||
if (equal_at_v)
|
if (equal_at_v)
|
||||||
{
|
{
|
||||||
CGAL_assertion (v_exists);
|
CGAL_assertion (v_exists);
|
||||||
|
|
||||||
// In this case the two urves intersect (or overlap) at v.
|
// v_leftmost should be our vertex at v.
|
||||||
Vertex_handle new_v;
|
// In this case the two curves intersect (or overlap) at v.
|
||||||
|
// We need to add the correct curves to v_leftmost.
|
||||||
if (u_res == SMALLER)
|
|
||||||
new_v = _append_vertex (out_d, v->point(), e1);
|
Vertex_handle v_to_be_updated = out_d.rightmost()->left();
|
||||||
else
|
|
||||||
new_v = _append_vertex (out_d, v->point(), e2);
|
|
||||||
|
|
||||||
if (u_res == EQUAL)
|
|
||||||
new_v->left()->add_curves (e1->curves_begin(), e1->curves_end());
|
|
||||||
|
|
||||||
if (origin_of_v == EQUAL)
|
if (origin_of_v == EQUAL)
|
||||||
{
|
{
|
||||||
// If the vertices of the edge are the same, we have to get the
|
// If the vertices of the edge are the same, we have to get the
|
||||||
// curves from there:
|
// curves from there:
|
||||||
new_v->add_curves (e1->right()->curves_begin(),
|
v_to_be_updated->add_curves (e1->right()->curves_begin(),
|
||||||
e1->right()->curves_end());
|
e1->right()->curves_end());
|
||||||
new_v->add_curves (e2->right()->curves_begin(),
|
v_to_be_updated->add_curves (e2->right()->curves_begin(),
|
||||||
e2->right()->curves_end());
|
e2->right()->curves_end());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -777,8 +903,8 @@ _merge_two_intervals (Edge_const_handle e1, bool is_leftmost1,
|
||||||
e2->right();
|
e2->right();
|
||||||
Edge_const_handle e = (origin_of_v == SMALLER) ? e2 : e1;
|
Edge_const_handle e = (origin_of_v == SMALLER) ? e2 : e1;
|
||||||
|
|
||||||
new_v->add_curves (v->curves_begin(), v->curves_end());
|
v_to_be_updated->add_curves (v->curves_begin(), v->curves_end());
|
||||||
new_v->add_curves (e->curves_begin(), e->curves_end());
|
v_to_be_updated->add_curves (e->curves_begin(), e->curves_end());
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
@ -788,32 +914,27 @@ _merge_two_intervals (Edge_const_handle e1, bool is_leftmost1,
|
||||||
{
|
{
|
||||||
// Both edges are unbounded from the right, so we simply have
|
// Both edges are unbounded from the right, so we simply have
|
||||||
// to update the rightmost edge in out_d.
|
// to update the rightmost edge in out_d.
|
||||||
CGAL_assertion (u_res != EQUAL);
|
switch (current_res)
|
||||||
|
{
|
||||||
if (u_res == SMALLER)
|
case SMALLER:
|
||||||
out_d.rightmost()->add_curves (e1->curves_begin(), e1->curves_end());
|
out_d.rightmost()->add_curves (e1->curves_begin(), e1->curves_end());
|
||||||
else
|
return;
|
||||||
|
case LARGER:
|
||||||
out_d.rightmost()->add_curves (e2->curves_begin(), e2->curves_end());
|
out_d.rightmost()->add_curves (e2->curves_begin(), e2->curves_end());
|
||||||
|
return;
|
||||||
return;
|
case EQUAL:
|
||||||
|
out_d.rightmost()->add_curves (e1->curves_begin(), e1->curves_end());
|
||||||
|
out_d.rightmost()->add_curves (e2->curves_begin(), e2->curves_end());
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
CGAL_error_msg("should not reach here.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we need to insert v into the diagram.
|
// Check if we need to insert v into the diagram.
|
||||||
if (pu_exists)
|
|
||||||
{
|
|
||||||
// Update the relative position of the two curves, which is their
|
|
||||||
// order immediately to the right of their last observed intersection
|
|
||||||
// point pu.
|
|
||||||
u_res = traits->compare_y_at_x_right_2_object() (e1->curve(),
|
|
||||||
e2->curve(),
|
|
||||||
pu);
|
|
||||||
|
|
||||||
if (env_type == UPPER)
|
|
||||||
u_res = CGAL::opposite (u_res);
|
|
||||||
}
|
|
||||||
CGAL_assertion (u_res != EQUAL);
|
|
||||||
|
|
||||||
if (u_res == SMALLER)
|
if (current_res == SMALLER)
|
||||||
{
|
{
|
||||||
// The final part of the interval is taken from e1.
|
// The final part of the interval is taken from e1.
|
||||||
Vertex_handle new_v;
|
Vertex_handle new_v;
|
||||||
|
|
@ -980,9 +1101,6 @@ _merge_vertical_segments (Curve_pointer_vector& vert_vec,
|
||||||
bool on_v;
|
bool on_v;
|
||||||
Point_2 p;
|
Point_2 p;
|
||||||
|
|
||||||
Vertex_initializer<Vertex_handle> v_init;
|
|
||||||
v_init(v);
|
|
||||||
|
|
||||||
while (iter != vert_vec.end())
|
while (iter != vert_vec.end())
|
||||||
{
|
{
|
||||||
// Check if the current vertical segment is on the x-range of the current
|
// Check if the current vertical segment is on the x-range of the current
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue