mirror of https://github.com/CGAL/cgal
fix bug when curve have a joint endpoint + improvement of tests
This commit is contained in:
parent
0d3ba40341
commit
9e8befe6e1
|
|
@ -1370,6 +1370,7 @@ Envelope_2/doc_tex/Envelope_2/fig/min_diag.gif -text svneol=unset#image/gif
|
||||||
Envelope_2/doc_tex/Envelope_2/fig/min_diag.pdf -text svneol=unset#application/pdf
|
Envelope_2/doc_tex/Envelope_2/fig/min_diag.pdf -text svneol=unset#application/pdf
|
||||||
Envelope_2/examples/Envelope_2/ch_points.dat -text
|
Envelope_2/examples/Envelope_2/ch_points.dat -text
|
||||||
Envelope_2/test/Envelope_2/data/Europe.dat -text
|
Envelope_2/test/Envelope_2/data/Europe.dat -text
|
||||||
|
Envelope_2/test/Envelope_2/data/bug_r49069.dat -text
|
||||||
Envelope_2/test/Envelope_2/data/onebig_100.dat -text
|
Envelope_2/test/Envelope_2/data/onebig_100.dat -text
|
||||||
Envelope_2/test/Envelope_2/data/random_500.dat -text
|
Envelope_2/test/Envelope_2/data/random_500.dat -text
|
||||||
Envelope_2/test/Envelope_2/data/segs_4.dat -text
|
Envelope_2/test/Envelope_2/data/segs_4.dat -text
|
||||||
|
|
|
||||||
|
|
@ -255,8 +255,9 @@ protected:
|
||||||
* \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,
|
||||||
Vertex_const_handle v, bool v_exists,
|
Vertex_const_handle v, bool v_exists,
|
||||||
bool same_org,
|
Comparison_result origin_of_v,
|
||||||
Envelope_diagram_1& out_d);
|
Envelope_diagram_1& out_d);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -267,13 +268,16 @@ protected:
|
||||||
* \param is_leftmost2 Is it the leftmost edge in its diagram.
|
* \param is_leftmost2 Is it the leftmost edge in its diagram.
|
||||||
* \param v The next vertex.
|
* \param v The next vertex.
|
||||||
* \param v_exists Whether such a vertex exists.
|
* \param v_exists Whether such a vertex exists.
|
||||||
* \param org_v The origin of v: 1 if it is from e1, 2 if it is from e2.
|
* \param origin_of_v The origin of v: SMALLER if it is from e1,
|
||||||
|
* otherwise it is from e2. EQUAL result means that
|
||||||
|
* both diagram have vertex at the same place (but v
|
||||||
|
* 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,
|
||||||
int org_v,
|
Comparison_result origin_of_v,
|
||||||
Envelope_diagram_1& out_d);
|
Envelope_diagram_1& out_d);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
||||||
|
|
@ -299,24 +299,33 @@ _merge_envelopes (const Envelope_diagram_1& d1,
|
||||||
_merge_two_intervals (e1, is_leftmost1,
|
_merge_two_intervals (e1, is_leftmost1,
|
||||||
e2, is_leftmost2,
|
e2, is_leftmost2,
|
||||||
next_v, next_exists,
|
next_v, next_exists,
|
||||||
(res_v == SMALLER) ? 1 : 2,
|
res_v, out_d);
|
||||||
out_d);
|
|
||||||
}
|
}
|
||||||
else if (! e1->is_empty() && e2->is_empty())
|
else if (! e1->is_empty() && e2->is_empty())
|
||||||
{
|
{
|
||||||
// e1 is not empty but e2 is empty:
|
// e1 is not empty but e2 is empty:
|
||||||
_merge_single_interval (e1,
|
_merge_single_interval (e1, e2,
|
||||||
next_v, next_exists,
|
next_v, next_exists,
|
||||||
(res_v == SMALLER),
|
res_v,
|
||||||
out_d);
|
out_d);
|
||||||
}
|
}
|
||||||
else if (e1->is_empty() && ! e2->is_empty())
|
else if (e1->is_empty() && ! e2->is_empty())
|
||||||
{
|
{
|
||||||
// e1 is empty and e2 is not empty:
|
// e1 is empty and e2 is not empty:
|
||||||
_merge_single_interval (e2,
|
_merge_single_interval (e2, e1,
|
||||||
next_v, next_exists,
|
next_v, next_exists,
|
||||||
(res_v != SMALLER),
|
CGAL::opposite(res_v),
|
||||||
out_d);
|
out_d);
|
||||||
|
|
||||||
|
/* // Bug fix: */
|
||||||
|
/* // If (res_v == EQUAL) then the _merge_single_interval will not */
|
||||||
|
/* // add the curves from v1 to the set of curves of the newly created */
|
||||||
|
/* // vertex (rightmost vertex). We handle it here though there maybe */
|
||||||
|
/* // a better design for this code. */
|
||||||
|
/* if (res_v == EQUAL) */
|
||||||
|
/* out_d.rightmost()->left()->add_curves */
|
||||||
|
/* (v1->curves_begin(), v1->curves_end()); */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -324,7 +333,17 @@ _merge_envelopes (const Envelope_diagram_1& d1,
|
||||||
if (next_exists)
|
if (next_exists)
|
||||||
{
|
{
|
||||||
Vertex_handle new_v = _append_vertex (out_d, next_v->point(), e1);
|
Vertex_handle new_v = _append_vertex (out_d, next_v->point(), e1);
|
||||||
new_v->add_curves (next_v->curves_begin(), next_v->curves_end());
|
switch(res_v)
|
||||||
|
{
|
||||||
|
case SMALLER:
|
||||||
|
new_v->add_curves (v1->curves_begin(), v1->curves_end()); break;
|
||||||
|
case LARGER:
|
||||||
|
new_v->add_curves (v2->curves_begin(), v2->curves_end()); break;
|
||||||
|
case EQUAL:
|
||||||
|
new_v->add_curves (v1->curves_begin(), v1->curves_end());
|
||||||
|
new_v->add_curves (v2->curves_begin(), v2->curves_end());
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -332,6 +351,7 @@ _merge_envelopes (const Envelope_diagram_1& d1,
|
||||||
if (next_exists)
|
if (next_exists)
|
||||||
{
|
{
|
||||||
// Check if we should proceed on d1 or on d2.
|
// Check if we should proceed on d1 or on d2.
|
||||||
|
// \todo: we do not need 3 cases, only two.
|
||||||
if (res_v == SMALLER)
|
if (res_v == SMALLER)
|
||||||
{
|
{
|
||||||
e1 = v1->right();
|
e1 = v1->right();
|
||||||
|
|
@ -395,15 +415,10 @@ _compare_vertices (Vertex_const_handle v1,
|
||||||
res = traits->compare_xy_2_object() (v1->point(),
|
res = traits->compare_xy_2_object() (v1->point(),
|
||||||
v2->point());
|
v2->point());
|
||||||
|
|
||||||
if ((env_type == LOWER && res == SMALLER) ||
|
// In case of upper envlope we take the opposite result
|
||||||
(env_type == UPPER && res == LARGER))
|
if (env_type == UPPER)
|
||||||
return (SMALLER);
|
return CGAL::opposite (res);
|
||||||
else if ((env_type == LOWER && res == LARGER) ||
|
return res;
|
||||||
(env_type == UPPER && res == SMALLER))
|
|
||||||
return (LARGER);
|
|
||||||
|
|
||||||
// The two vertices represent equal points:
|
|
||||||
return (EQUAL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
@ -412,9 +427,9 @@ _compare_vertices (Vertex_const_handle v1,
|
||||||
//
|
//
|
||||||
template <class Traits, class Diagram>
|
template <class Traits, class Diagram>
|
||||||
void Envelope_divide_and_conquer_2<Traits,Diagram>::
|
void Envelope_divide_and_conquer_2<Traits,Diagram>::
|
||||||
_merge_single_interval (Edge_const_handle e,
|
_merge_single_interval (Edge_const_handle e, Edge_const_handle other_edge,
|
||||||
Vertex_const_handle v, bool v_exists,
|
Vertex_const_handle v, bool v_exists,
|
||||||
bool same_org,
|
Comparison_result origin_of_v,
|
||||||
Envelope_diagram_1& out_d)
|
Envelope_diagram_1& out_d)
|
||||||
{
|
{
|
||||||
if (! v_exists)
|
if (! v_exists)
|
||||||
|
|
@ -427,7 +442,7 @@ _merge_single_interval (Edge_const_handle e,
|
||||||
|
|
||||||
Vertex_handle new_v;
|
Vertex_handle new_v;
|
||||||
|
|
||||||
if (same_org)
|
if (origin_of_v == SMALLER)
|
||||||
{
|
{
|
||||||
// The non-empty edge ends at v, so we simply insert it to out_d.
|
// The non-empty edge ends at v, so we simply insert it to out_d.
|
||||||
new_v = _append_vertex (out_d, v->point(), e);
|
new_v = _append_vertex (out_d, v->point(), e);
|
||||||
|
|
@ -436,6 +451,15 @@ _merge_single_interval (Edge_const_handle e,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (origin_of_v == EQUAL) // the edges have vertices at the same place.
|
||||||
|
{
|
||||||
|
new_v = _append_vertex (out_d, v->point(), e);
|
||||||
|
new_v->add_curves (e->right()->curves_begin(), e->right()->curves_end());
|
||||||
|
new_v->add_curves (other_edge->right()->curves_begin(),
|
||||||
|
other_edge->right()->curves_end());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// If v is not on e, we should insert it to the merged diagram only if it
|
// If v is not on e, we should insert it to the merged diagram only if it
|
||||||
// is below (or above, in case of an upper envelope) the curves of e.
|
// is below (or above, in case of an upper envelope) the curves of e.
|
||||||
Comparison_result res = traits->compare_y_at_x_2_object() (v->point(),
|
Comparison_result res = traits->compare_y_at_x_2_object() (v->point(),
|
||||||
|
|
@ -466,7 +490,7 @@ void Envelope_divide_and_conquer_2<Traits,Diagram>::
|
||||||
_merge_two_intervals (Edge_const_handle e1, bool is_leftmost1,
|
_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,
|
||||||
int org_v,
|
Comparison_result origin_of_v,
|
||||||
Envelope_diagram_1& out_d)
|
Envelope_diagram_1& out_d)
|
||||||
{
|
{
|
||||||
// Get the relative position of two curves associated with e1 and e2
|
// Get the relative position of two curves associated with e1 and e2
|
||||||
|
|
@ -514,8 +538,8 @@ _merge_two_intervals (Edge_const_handle e1, bool is_leftmost1,
|
||||||
// rightmost point in the merged diagram.
|
// rightmost point in the merged diagram.
|
||||||
std::list<CGAL::Object> objects;
|
std::list<CGAL::Object> objects;
|
||||||
CGAL::Object obj;
|
CGAL::Object obj;
|
||||||
X_monotone_curve_2 icv;
|
X_monotone_curve_2 intersection_curve;
|
||||||
std::pair<Point_2, unsigned int> ipt;
|
std::pair<Point_2, typename Traits::Multiplicity> intersection_point;
|
||||||
|
|
||||||
traits->intersect_2_object() (e1->curve(), e2->curve(),
|
traits->intersect_2_object() (e1->curve(), e2->curve(),
|
||||||
std::back_inserter(objects));
|
std::back_inserter(objects));
|
||||||
|
|
@ -526,25 +550,25 @@ _merge_two_intervals (Edge_const_handle e1, bool is_leftmost1,
|
||||||
obj = objects.front();
|
obj = objects.front();
|
||||||
objects.pop_front();
|
objects.pop_front();
|
||||||
|
|
||||||
if (CGAL::assign(ipt, obj))
|
if (CGAL::assign(intersection_point, obj))
|
||||||
{
|
{
|
||||||
// We have a simple intersection point.
|
// We have a simple intersection point.
|
||||||
if (v_rm_exists &&
|
if (v_rm_exists &&
|
||||||
traits->compare_xy_2_object() (ipt.first,
|
traits->compare_xy_2_object() (intersection_point.first,
|
||||||
v_rm->point()) != LARGER)
|
v_rm->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 = ipt.first;
|
pu = intersection_point.first;
|
||||||
pu_exists = true;
|
pu_exists = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v_exists)
|
if (v_exists)
|
||||||
{
|
{
|
||||||
Comparison_result res = traits->compare_xy_2_object() (ipt.first,
|
Comparison_result res = traits->compare_xy_2_object()
|
||||||
v->point());
|
(intersection_point.first, v->point());
|
||||||
|
|
||||||
if (res == EQUAL)
|
if (res == EQUAL)
|
||||||
// v is an intersection points, so both curves are equal there:
|
// v is an intersection points, so both curves are equal there:
|
||||||
|
|
@ -576,9 +600,9 @@ _merge_two_intervals (Edge_const_handle e1, bool is_leftmost1,
|
||||||
CGAL_assertion (u_res != EQUAL);
|
CGAL_assertion (u_res != EQUAL);
|
||||||
|
|
||||||
if (u_res == SMALLER)
|
if (u_res == SMALLER)
|
||||||
new_v = _append_vertex (out_d, ipt.first, e1);
|
new_v = _append_vertex (out_d, intersection_point.first, e1);
|
||||||
else
|
else
|
||||||
new_v = _append_vertex (out_d, ipt.first, e2);
|
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.
|
// 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 (e1->curves_begin(), e1->curves_end());
|
||||||
|
|
@ -591,18 +615,19 @@ _merge_two_intervals (Edge_const_handle e1, bool is_leftmost1,
|
||||||
// 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 (ipt.second % 2 == 1)
|
if (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);
|
u_res = CGAL::opposite (u_res);
|
||||||
}
|
}
|
||||||
else if (ipt.second == 0)
|
else if (intersection_point.second == 0)
|
||||||
{
|
{
|
||||||
// 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() (e1->curve(),
|
u_res = traits->compare_y_at_x_right_2_object()
|
||||||
|
(e1->curve(),
|
||||||
e2->curve(),
|
e2->curve(),
|
||||||
ipt.first);
|
intersection_point.first);
|
||||||
CGAL_assertion (u_res != EQUAL);
|
CGAL_assertion (u_res != EQUAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -610,7 +635,7 @@ _merge_two_intervals (Edge_const_handle e1, bool is_leftmost1,
|
||||||
{
|
{
|
||||||
// We have an x-monotone curve representing an overlap of the two
|
// We have an x-monotone curve representing an overlap of the two
|
||||||
// curves.
|
// curves.
|
||||||
bool assign_success = CGAL::assign (icv, obj);
|
bool assign_success = CGAL::assign (intersection_curve, obj);
|
||||||
|
|
||||||
CGAL_assertion (assign_success);
|
CGAL_assertion (assign_success);
|
||||||
if (! assign_success)
|
if (! assign_success)
|
||||||
|
|
@ -618,16 +643,16 @@ _merge_two_intervals (Edge_const_handle e1, bool is_leftmost1,
|
||||||
|
|
||||||
// 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() (icv, 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() (icv, ARR_MAX_END) == ARR_INTERIOR);
|
(traits->parameter_space_in_x_2_object() (intersection_curve, ARR_MAX_END) == ARR_INTERIOR);
|
||||||
Point_2 p1, p2;
|
Point_2 p1, p2;
|
||||||
|
|
||||||
if (has_left)
|
if (has_left)
|
||||||
p1 = traits->construct_min_vertex_2_object() (icv);
|
p1 = traits->construct_min_vertex_2_object() (intersection_curve);
|
||||||
|
|
||||||
if (has_right)
|
if (has_right)
|
||||||
p2 = traits->construct_max_vertex_2_object() (icv);
|
p2 = traits->construct_max_vertex_2_object() (intersection_curve);
|
||||||
|
|
||||||
// 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_rm_exists && has_right &&
|
||||||
|
|
@ -659,7 +684,7 @@ _merge_two_intervals (Edge_const_handle e1, bool is_leftmost1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// There is an overlap between the range [u, v] and icv.
|
// There is an overlap between the range [u, v] and intersection_curve.
|
||||||
if (has_left &&
|
if (has_left &&
|
||||||
(! v_rm_exists ||
|
(! v_rm_exists ||
|
||||||
traits->compare_xy_2_object() (p1,
|
traits->compare_xy_2_object() (p1,
|
||||||
|
|
@ -684,9 +709,9 @@ _merge_two_intervals (Edge_const_handle e1, bool is_leftmost1,
|
||||||
CGAL_assertion (u_res != EQUAL);
|
CGAL_assertion (u_res != EQUAL);
|
||||||
|
|
||||||
if (u_res == SMALLER)
|
if (u_res == SMALLER)
|
||||||
new_v = _append_vertex (out_d, ipt.first, e1);
|
new_v = _append_vertex (out_d, intersection_point.first, e1);
|
||||||
else
|
else
|
||||||
new_v = _append_vertex (out_d, ipt.first, e2);
|
new_v = _append_vertex (out_d, intersection_point.first, e2);
|
||||||
|
|
||||||
// Note that the new vertex is incident to all curves in e1 and
|
// Note that the new vertex is incident to all curves in e1 and
|
||||||
// in e2.
|
// in e2.
|
||||||
|
|
@ -706,7 +731,7 @@ _merge_two_intervals (Edge_const_handle e1, bool is_leftmost1,
|
||||||
// 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, ipt.first, e1);
|
new_v = _append_vertex (out_d, intersection_point.first, 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());
|
new_v->add_curves (e1->curves_begin(), e1->curves_end());
|
||||||
|
|
@ -734,6 +759,7 @@ _merge_two_intervals (Edge_const_handle e1, bool is_leftmost1,
|
||||||
|
|
||||||
} // End of the traversal over the intersection objects.
|
} // End of the traversal over the intersection objects.
|
||||||
|
|
||||||
|
|
||||||
// Handle the portion after the intersection objects.
|
// Handle the portion after the intersection objects.
|
||||||
if (equal_at_v)
|
if (equal_at_v)
|
||||||
{
|
{
|
||||||
|
|
@ -750,9 +776,21 @@ _merge_two_intervals (Edge_const_handle e1, bool is_leftmost1,
|
||||||
if (u_res == EQUAL)
|
if (u_res == EQUAL)
|
||||||
new_v->left()->add_curves (e1->curves_begin(), e1->curves_end());
|
new_v->left()->add_curves (e1->curves_begin(), e1->curves_end());
|
||||||
|
|
||||||
|
if (origin_of_v == EQUAL)
|
||||||
|
{
|
||||||
|
// If the vertices of the edge are the same, we have to get the
|
||||||
|
// curves from there:
|
||||||
|
new_v->add_curves (e1->right()->curves_begin(),
|
||||||
|
e1->right()->curves_end());
|
||||||
|
new_v->add_curves (e2->right()->curves_begin(),
|
||||||
|
e2->right()->curves_end());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// Note that the new vertex is incident to all curves in e1 and in 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 (e1->curves_begin(), e1->curves_end());
|
||||||
new_v->add_curves (e2->curves_begin(), e2->curves_end());
|
new_v->add_curves (e2->curves_begin(), e2->curves_end());
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -791,13 +829,27 @@ _merge_two_intervals (Edge_const_handle e1, bool is_leftmost1,
|
||||||
// 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;
|
||||||
|
|
||||||
if (org_v == 1)
|
if (origin_of_v == SMALLER)
|
||||||
{
|
{
|
||||||
// In case v is also from e1, append it to the merged diagram.
|
// In case v is also from e1, append it to the merged diagram.
|
||||||
new_v = _append_vertex (out_d, v->point(), e1);
|
new_v = _append_vertex (out_d, v->point(), e1);
|
||||||
new_v->add_curves (v->curves_begin(), v->curves_end());
|
new_v->add_curves (v->curves_begin(), v->curves_end());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
// if origin_of_v is EQUAL then the two diagram have a vertex at
|
||||||
|
// exact same place.
|
||||||
|
if (origin_of_v == EQUAL)
|
||||||
|
{
|
||||||
|
new_v = _append_vertex (out_d, v->point(), e1);
|
||||||
|
new_v->add_curves (v->curves_begin(), v->curves_end());
|
||||||
|
|
||||||
|
// adding the curves of the vertex of the first diagram (vertices are
|
||||||
|
// equal...)
|
||||||
|
new_v->add_curves (e1->right()->curves_begin(),
|
||||||
|
e1->right()->curves_end());
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// If v is from e2, check if it below (or above, in case of an upper
|
// If v is from e2, check if it below (or above, in case of an upper
|
||||||
// envelope) cv1 to insert it.
|
// envelope) cv1 to insert it.
|
||||||
|
|
@ -817,16 +869,27 @@ _merge_two_intervals (Edge_const_handle e1, bool is_leftmost1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// The final part of the interval is taken from e2.
|
// The final part of the interval is taken from e2.
|
||||||
Vertex_handle new_v;
|
Vertex_handle new_v;
|
||||||
|
|
||||||
if (org_v == 2)
|
if (origin_of_v != SMALLER)
|
||||||
{
|
{
|
||||||
// In case v is also from e2, append it to the merged diagram.
|
// In case v is also from e2, append it to the merged diagram.
|
||||||
new_v = _append_vertex (out_d, v->point(), e2);
|
new_v = _append_vertex (out_d, v->point(), e2);
|
||||||
new_v->add_curves (v->curves_begin(), v->curves_end());
|
new_v->add_curves (v->curves_begin(), v->curves_end());
|
||||||
|
|
||||||
|
// if origin_of_v is EQUAL then the two diagram have a vertex at
|
||||||
|
// exact same place.
|
||||||
|
if (origin_of_v == EQUAL)
|
||||||
|
{
|
||||||
|
// adding the curves of the vertex of the first diagram (vertices are
|
||||||
|
// equal...)
|
||||||
|
new_v->add_curves (e1->right()->curves_begin(),
|
||||||
|
e1->right()->curves_end());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
9
|
||||||
|
|
||||||
|
3 1 -1 1
|
||||||
|
2 0 1 0
|
||||||
|
0 0 1 0
|
||||||
|
|
||||||
|
0 0 1 1
|
||||||
|
0 0 1 -1
|
||||||
|
|
||||||
|
4 0 3 1
|
||||||
|
2 0 3 1
|
||||||
|
|
||||||
|
5 1 6 0
|
||||||
|
5 -1 6 0
|
||||||
|
|
@ -2,3 +2,4 @@
|
||||||
./data/random_500.dat -i
|
./data/random_500.dat -i
|
||||||
./data/onebig_100.dat -i
|
./data/onebig_100.dat -i
|
||||||
./data/Europe.dat -d
|
./data/Europe.dat -d
|
||||||
|
./data/bug_r49069.dat -i
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include <CGAL/Cartesian.h>
|
#include <CGAL/Cartesian.h>
|
||||||
#include <CGAL/Arr_segment_traits_2.h>
|
#include <CGAL/Arr_segment_traits_2.h>
|
||||||
|
#include <CGAL/Arr_curve_data_traits_2.h>
|
||||||
#include <CGAL/Env_default_diagram_1.h>
|
#include <CGAL/Env_default_diagram_1.h>
|
||||||
#include <CGAL/envelope_2.h>
|
#include <CGAL/envelope_2.h>
|
||||||
|
|
||||||
|
|
@ -23,11 +24,14 @@ using std::strcmp;
|
||||||
|
|
||||||
typedef CGAL::Gmpq NT;
|
typedef CGAL::Gmpq NT;
|
||||||
typedef CGAL::Cartesian<NT> Kernel;
|
typedef CGAL::Cartesian<NT> Kernel;
|
||||||
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
typedef CGAL::Arr_segment_traits_2<Kernel> Segment_traits_2;
|
||||||
|
typedef CGAL::Arr_curve_data_traits_2<Segment_traits_2,
|
||||||
|
int> Traits_2;
|
||||||
typedef Traits_2::Point_2 Point_2;
|
typedef Traits_2::Point_2 Point_2;
|
||||||
typedef Traits_2::Curve_2 Segment_2;
|
typedef Segment_traits_2::Curve_2 Segment_2;
|
||||||
|
typedef Traits_2::Curve_2 Curve_2;
|
||||||
typedef CGAL::Env_default_diagram_1<Traits_2> Diagram_1;
|
typedef CGAL::Env_default_diagram_1<Traits_2> Diagram_1;
|
||||||
typedef std::list<Segment_2> Segment_list;
|
typedef std::list<Curve_2> Curve_list;
|
||||||
|
|
||||||
enum Coord_input_format
|
enum Coord_input_format
|
||||||
{
|
{
|
||||||
|
|
@ -45,7 +49,7 @@ enum Coord_input_format
|
||||||
*/
|
*/
|
||||||
bool read_segments (const char *filename,
|
bool read_segments (const char *filename,
|
||||||
Coord_input_format format,
|
Coord_input_format format,
|
||||||
Segment_list& segs)
|
Curve_list& segs)
|
||||||
{
|
{
|
||||||
segs.clear();
|
segs.clear();
|
||||||
|
|
||||||
|
|
@ -94,13 +98,33 @@ bool read_segments (const char *filename,
|
||||||
}
|
}
|
||||||
|
|
||||||
seg = Segment_2 (Point_2 (x1, y1), Point_2 (x2, y2));
|
seg = Segment_2 (Point_2 (x1, y1), Point_2 (x2, y2));
|
||||||
segs.push_back (seg);
|
segs.push_back (Curve_2(seg, segs.size()));
|
||||||
}
|
}
|
||||||
ifile.close();
|
ifile.close();
|
||||||
|
|
||||||
return (true);
|
return (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Check if a $x$-monotone curve with the same associated data as the input
|
||||||
|
* curve is in the given range.
|
||||||
|
* \param begin The begining of the range.
|
||||||
|
* \param end Passed-the-end iterator.
|
||||||
|
* \param c The curve, the data of which we are searching.
|
||||||
|
* \return True if we found an $x$-monotone curve with the same data.
|
||||||
|
*/
|
||||||
|
template<class I>
|
||||||
|
bool find_curve(I begin, I end, const Curve_2 &c)
|
||||||
|
{
|
||||||
|
while (begin != end)
|
||||||
|
{
|
||||||
|
if (begin->data() == c.data())
|
||||||
|
return true;
|
||||||
|
++begin;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Check the envelope of a given set of segments.
|
* Check the envelope of a given set of segments.
|
||||||
* \param segs The segments.
|
* \param segs The segments.
|
||||||
|
|
@ -108,7 +132,7 @@ bool read_segments (const char *filename,
|
||||||
* \param is_lower Does the diagram reprsent the lower or the upper envelope.
|
* \param is_lower Does the diagram reprsent the lower or the upper envelope.
|
||||||
* \return Whether the diagram structure is correct.
|
* \return Whether the diagram structure is correct.
|
||||||
*/
|
*/
|
||||||
bool check_envelope (const Segment_list& segs,
|
bool check_envelope (const Curve_list& segs,
|
||||||
const Diagram_1& diag,
|
const Diagram_1& diag,
|
||||||
bool is_lower)
|
bool is_lower)
|
||||||
{
|
{
|
||||||
|
|
@ -130,9 +154,10 @@ bool check_envelope (const Segment_list& segs,
|
||||||
Point_2 p_mid;
|
Point_2 p_mid;
|
||||||
CGAL::Comparison_result res1, res2;
|
CGAL::Comparison_result res1, res2;
|
||||||
CGAL::Comparison_result y_res;
|
CGAL::Comparison_result y_res;
|
||||||
Segment_list::const_iterator sit;
|
Curve_list::const_iterator sit;
|
||||||
|
|
||||||
e = e->right()->right();
|
v = e->right();
|
||||||
|
e = v->right();
|
||||||
while (e != diag.rightmost())
|
while (e != diag.rightmost())
|
||||||
{
|
{
|
||||||
// Get the midpoint of the current edge.
|
// Get the midpoint of the current edge.
|
||||||
|
|
@ -143,15 +168,10 @@ bool check_envelope (const Segment_list& segs,
|
||||||
{
|
{
|
||||||
// Check if p_mid lies in the x-range of the current segment.
|
// Check if p_mid lies in the x-range of the current segment.
|
||||||
res1 = compare_x (p_mid, min_ver(*sit));
|
res1 = compare_x (p_mid, min_ver(*sit));
|
||||||
|
|
||||||
if (res1 == CGAL::SMALLER)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
res2 = compare_x (p_mid, max_ver(*sit));
|
res2 = compare_x (p_mid, max_ver(*sit));
|
||||||
|
|
||||||
if (res2 == CGAL::LARGER)
|
if (res1 != CGAL::SMALLER && res2 != CGAL::LARGER)
|
||||||
continue;
|
{
|
||||||
|
|
||||||
// Check the diagram edge.
|
// Check the diagram edge.
|
||||||
if (e->is_empty())
|
if (e->is_empty())
|
||||||
{
|
{
|
||||||
|
|
@ -180,8 +200,71 @@ bool check_envelope (const Segment_list& segs,
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
return (false);
|
return (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If it is equal, the segment should be in the diagram.
|
||||||
|
if (y_res == CGAL::EQUAL &&
|
||||||
|
find_curve(e->curves_begin(), e->curves_end(), *sit) == false)
|
||||||
|
{
|
||||||
|
std::cerr << "The edge (" << e->left()->point()
|
||||||
|
<< ") -> (" << e->right()->point()
|
||||||
|
<< ") is associated with the segment ["
|
||||||
|
<< e->curve() << "], but the segment ["
|
||||||
|
<< *sit << "] is not in the list of its curves."
|
||||||
|
<< std::endl;
|
||||||
|
return (false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Check if v lies in the x-range of the current segment.
|
||||||
|
res1 = compare_x (v->point(), min_ver(*sit));
|
||||||
|
res2 = compare_x (v->point(), max_ver(*sit));
|
||||||
|
|
||||||
|
if (res1 != CGAL::SMALLER && res2 != CGAL::LARGER)
|
||||||
|
{
|
||||||
|
// Check the diagram vertex.
|
||||||
|
if (v->number_of_curves() == 0)
|
||||||
|
{
|
||||||
|
// If v is in the x-range of the given segment, the current vertex
|
||||||
|
// cannot by empty.
|
||||||
|
std::cerr << "The vertex (" << v->point()
|
||||||
|
<< ") is empty, "
|
||||||
|
<< "but the segment [" << *sit << "] is defined over it."
|
||||||
|
<< std::endl;
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Compare the segment with the segment associated with the edge.
|
||||||
|
y_res = comp_y_at_x (v->point(), *sit);
|
||||||
|
|
||||||
|
// Check for violations of the diagram properties.
|
||||||
|
if ((is_lower && y_res == CGAL::LARGER) ||
|
||||||
|
(! is_lower && y_res == CGAL::SMALLER))
|
||||||
|
{
|
||||||
|
std::cerr << "The vertex (" << v->point()
|
||||||
|
<< ") and the segment ["
|
||||||
|
<< *sit << "] violate the envelope properties."
|
||||||
|
<< std::endl;
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it is equal, the segment should be in the diagram.
|
||||||
|
if (y_res == CGAL::EQUAL &&
|
||||||
|
find_curve(v->curves_begin(), v->curves_end(), *sit) == false)
|
||||||
|
{
|
||||||
|
std::cerr << "The vertex (" << v->point()
|
||||||
|
<< ") does not contain the segment ["
|
||||||
|
<< *sit << "] in the list of its curves, but they have"
|
||||||
|
<< " equal values."
|
||||||
|
<< std::endl;
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
v = e->right();
|
v = e->right();
|
||||||
e = v->right();
|
e = v->right();
|
||||||
}
|
}
|
||||||
|
|
@ -196,28 +279,30 @@ bool check_envelope (const Segment_list& segs,
|
||||||
*/
|
*/
|
||||||
int main (int argc, char **argv)
|
int main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
if (argc < 2)
|
if (argc % 2 == 0 || argc == 1)
|
||||||
{
|
{
|
||||||
std::cerr << "Usage: " << argv[0]
|
std::cerr << "Usage: " << argv[0]
|
||||||
<< "<input file> [ -q | -i | -d ]" << std::endl;
|
<< "<input file> [ -q | -i | -d ]" << std::endl;
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int number_of_tests = (argc - 1) / 2;
|
||||||
|
for (int i = 0; i < number_of_tests; ++i)
|
||||||
|
{
|
||||||
|
std::cout << "Checking input file: " << argv[2*i + 1] << std::endl;
|
||||||
|
|
||||||
// Determine the input format.
|
// Determine the input format.
|
||||||
Coord_input_format format = F_RATIONAL;
|
Coord_input_format format = F_RATIONAL;
|
||||||
|
|
||||||
if (argc > 2)
|
if (strcmp (argv[2*i + 2], "-i") || strcmp (argv[2*i + 2], "-I"))
|
||||||
{
|
|
||||||
if (strcmp (argv[2], "-i") || strcmp (argv[2], "-I"))
|
|
||||||
format = F_INTEGER;
|
format = F_INTEGER;
|
||||||
else if (strcmp (argv[2], "-d") || strcmp (argv[2], "-D"))
|
else if (strcmp (argv[2*i + 2], "-d") || strcmp (argv[2*i + 2], "-D"))
|
||||||
format = F_DOUBLE;
|
format = F_DOUBLE;
|
||||||
}
|
|
||||||
|
|
||||||
// Read the input segments.
|
// Read the input segments.
|
||||||
Segment_list segments;
|
Curve_list segments;
|
||||||
|
|
||||||
if (! read_segments (argv[1], format, segments))
|
if (! read_segments (argv[2*i + 1], format, segments))
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
// Compute their lower envelope.
|
// Compute their lower envelope.
|
||||||
|
|
@ -253,6 +338,6 @@ int main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
std::cout << "The upper envelope is valid." << std::endl;
|
std::cout << "The upper envelope is valid." << std::endl;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue