Merge pull request #2342 from sloriot/Argt-overlap_intersect_at_insertion

Reworking the handling of overlaps
This commit is contained in:
Laurent Rineau 2017-12-05 18:27:35 +01:00
commit 2cec8e6aca
33 changed files with 1078 additions and 281 deletions

View File

@ -2441,7 +2441,7 @@ protected:
{
x = x_left + x_jump*i;
disc = app_sqr_rad - CGAL::square(x - app_xcenter);
CGAL_precondition(disc >= 0);
if (disc < 0) disc = 0;
if(is_up)
y = app_ycenter + std::sqrt(disc);
else

View File

@ -450,8 +450,7 @@ protected:
* \param curve The subcurve to add.
* \return (true) if an overlap occured; (false) otherwise.
*/
virtual bool _add_curve_to_right(Event* event, Subcurve* curve,
bool overlap_exist = false);
virtual bool _add_curve_to_right(Event* event, Subcurve* curve);
/*! Remove a curve from the status line. */
void _remove_curve_from_status_line(Subcurve *leftCurve);

View File

@ -225,9 +225,19 @@ bool Construction_test<T_Geom_traits, T_Topol_traits>::are_same_results()
<< m_num_faces << ")" << std::endl;
}
if (m_arr->number_of_vertices() != m_num_vertices) return false;
if (m_arr->number_of_edges() != m_num_edges) return false;
if (m_arr->number_of_faces() != m_num_faces) return false;
if ((m_arr->number_of_vertices() != m_num_vertices) ||
(m_arr->number_of_edges() != m_num_edges) ||
(m_arr->number_of_faces() != m_num_faces)) {
std::cout << "# vertices, edge, faces obtained: ("
<< m_arr->number_of_vertices() << ","
<< m_arr->number_of_edges() << ","
<< m_arr->number_of_faces() << ")"
<< ", expected: ("
<< m_num_vertices << ","
<< m_num_edges << ","
<< m_num_faces << ")" << std::endl;
return false;
}
Point_container points_res(m_num_vertices);
typename Point_container::iterator pit = points_res.begin();
@ -239,13 +249,20 @@ bool Construction_test<T_Geom_traits, T_Topol_traits>::are_same_results()
std::sort(points_res.begin(), pit, pt_compare);
if (m_verbose_level > 2) {
std::copy(points_res.begin(), pit,
std::copy(points_res.begin(), points_res.end(),
std::ostream_iterator<Point_2>(std::cout, "\n"));
}
Point_equal point_eq(m_geom_traits);
if (! std::equal(points_res.begin(), pit, m_points.begin(), point_eq))
if (! std::equal(points_res.begin(), pit, m_points.begin(), point_eq)) {
std::cout << "Expected: " << std::endl;
std::copy(m_points.begin(), m_points.end(),
std::ostream_iterator<Point_2>(std::cout, "\n"));
std::cout << "Obtained: " << std::endl;
std::copy(points_res.begin(), points_res.end(),
std::ostream_iterator<Point_2>(std::cout, "\n"));
return false;
}
std::vector<X_monotone_curve_2> curves_res(m_arr->number_of_edges());
typename Xcurve_container::iterator xcit = curves_res.begin();
@ -259,13 +276,23 @@ bool Construction_test<T_Geom_traits, T_Topol_traits>::are_same_results()
std::sort(curves_res.begin(), xcit, curve_compare);
if (m_verbose_level > 2) {
std::copy(curves_res.begin(), xcit,
std::ostream_iterator<X_monotone_curve_2>(std::cout, "\n"));
for (typename Xcurve_container::iterator it = curves_res.begin();
it != curves_res.end(); ++it)
std::cout << *it << " " << it->data() << std::endl;
}
Curve_equal curve_eq(m_geom_traits);
if (! std::equal(curves_res.begin(), xcit, m_xcurves.begin(), curve_eq))
if (! std::equal(curves_res.begin(), xcit, m_xcurves.begin(), curve_eq)) {
std::cout << "Expected: " << std::endl;
for (typename Xcurve_container::iterator it = m_xcurves.begin();
it != m_xcurves.end(); ++it)
std::cout << *it << " " << it->data() << std::endl;
std::cout << "Obtained: " << std::endl;
for (typename Xcurve_container::iterator it = curves_res.begin();
it != curves_res.end(); ++it)
std::cout << *it << " " << it->data() << std::endl;
return false;
}
if (m_arr->number_of_faces() == 1) {
Face_const_iterator fit = m_arr->faces_begin();

View File

@ -686,6 +686,18 @@ function(test_construction_spherical_arcs)
compile_and_run_with_flags( test_construction geodesic_arcs_on_sphere "${flags}")
endfunction()
#---------------------------------------------------------------------#
# construction with polylines
#---------------------------------------------------------------------#
function(test_construction_polylines)
set(nt ${CGAL_GMPQ_NT})
set(kernel ${CARTESIAN_KERNEL})
set(geom_traits ${POLYLINE_GEOM_TRAITS})
set(flags "-DTEST_NT=${nt} -DTEST_KERNEL=${kernel} -DTEST_GEOM_TRAITS=${geom_traits}")
compile_and_run_with_flags( test_construction polylines "${flags}")
endfunction()
#---------------------------------------------------------------------#
# overlay with segments
#---------------------------------------------------------------------#
@ -1371,6 +1383,7 @@ compile_and_run(test_vert_ray_shoot_vert_segments)
test_construction_segments()
test_construction_linear_curves()
test_construction_spherical_arcs()
test_construction_polylines()
test_overlay_segments()
test_overlay_spherical_arcs()

View File

@ -873,6 +873,18 @@ test_construction_spherical_arcs()
compile_and_run_with_flags test_construction geodesic_arcs_on_sphere "$flags"
}
#---------------------------------------------------------------------#
# construction with polylines
#---------------------------------------------------------------------#
test_construction_polylines()
{
local nt=$CGAL_GMPQ_NT;
local kernel=$CARTESIAN_KERNEL;
local geom_traits=$POLYLINE_GEOM_TRAITS;
local flags="-DTEST_NT=$nt -DTEST_KERNEL=$kernel -DTEST_GEOM_TRAITS=$geom_traits";
compile_and_run_with_flags test_construction polylines "$flags"
}
#---------------------------------------------------------------------#
# overlay with segments
#---------------------------------------------------------------------#
@ -1699,6 +1711,7 @@ compile_and_run test_vert_ray_shoot_vert_segments
test_construction_segments
test_construction_linear
test_construction_spherical_arcs
test_construction_polylines
test_overlay_segments
test_overlay_spherical_arcs

View File

@ -0,0 +1 @@
test06 covers the case "Overlap with common ancestors"

View File

@ -0,0 +1,25 @@
3
2 0 0 7 0
3 3 1 4 0 6 0
3 1 0 3 2 5 0
0
7
7
2
0 0
1 0
3 1
4 0
5 0
6 0
7 0
2 0 0 1 0 1
2 1 0 4 0 1
3 1 0 3 2 5 0 1
2 3 1 4 0 1
2 4 0 5 0 2
2 5 0 6 0 2
2 6 0 7 0 1

View File

@ -0,0 +1,27 @@
3
2 0 0 7 0
4 1 0 3 1 4 0 6 0
3 0 -1 3 2 5 0
0
7
8
3
0 -1
0 0
1 0
4 0
5 0
6 0
7 0
2 0 -1 1 0 1
2 0 0 1 0 1
2 1 0 4 0 1
3 1 0 3 1 4 0 1
3 1 0 3 2 5 0 1
2 4 0 5 0 2
2 5 0 6 0 2
2 6 0 7 0 1

View File

@ -0,0 +1,19 @@
3
4 5 0 4 1 3 1 2 1
5 5 0 4 1 3 1 2 1 0 0
3 1 2 3 1 4 1
0
6
5
1
0 0
1 2
2 1
3 1
4 1
5 0
2 2 1 0 0 1
2 1 2 3 1 1
2 2 1 3 1 2
2 3 1 4 1 3
2 4 1 5 0 2

View File

@ -0,0 +1,17 @@
3
4 1 2 2 1 3 1 4 0
4 0 0 2 1 3 1 4 0
2 2 1 3 1
0
5
4
1
0 0
1 2
2 1
3 1
4 0
2 0 0 2 1 1
2 1 2 2 1 1
2 2 1 3 1 3
2 3 1 4 0 2

View File

@ -0,0 +1,25 @@
3
3 0 3 1 2 2 0
3 0 1 1 2 2 0
2 0 2 3 0
0
8
8
2
0 1
0 2
0 3
3/5 8/5
1 2
3/2 1
2 0
3 0
2 0 1 3/5 8/5 1
2 0 2 3/5 8/5 1
2 0 3 1 2 1
2 3/5 8/5 3/2 1 1
2 3/5 8/5 1 2 1
2 1 2 3/2 1 2
2 3/2 1 2 0 2
2 3/2 1 3 0 1

View File

@ -0,0 +1,35 @@
4
3 0 0 2 3 3 0
2 0 3 4 0
3 0 2 2 3 3 0
3 0 1 2 3 3 0
0
11
13
4
0 0
0 1
0 2
0 3
4/5 12/5
8/7 15/7
4/3 2
2 3
8/3 1
3 0
4 0
2 0 0 4/3 2 1
2 0 1 8/7 15/7 1
2 0 2 4/5 12/5 1
2 0 3 4/5 12/5 1
2 4/5 12/5 8/7 15/7 1
2 4/5 12/5 2 3 1
2 8/7 15/7 4/3 2 1
2 8/7 15/7 2 3 1
2 4/3 2 8/3 1 1
2 4/3 2 2 3 1
2 2 3 8/3 1 3
2 8/3 1 3 0 3
2 8/3 1 4 0 1

View File

@ -0,0 +1,54 @@
3
11 0 1 2 1 3 0 5 0 6 1 8 1 9 0 11 0 12 1 14 1 15 0
11 0 0 1 1 3 1 4 0 6 0 7 1 9 1 10 0 12 0 13 1 15 1
12 0 0 1 0 2 1 4 1 5 0 7 0 8 1 10 1 11 0 13 0 14 1 15 1
0
18
26
10
0 0
0 1
1 1
2 1
3 1
4 0
5 0
6 0
7 1
8 1
9 1
10 0
11 0
12 0
13 1
14 1
15 0
15 1
3 0 0 1 0 2 1 1
2 0 0 1 1 1
2 0 1 1 1 1
2 1 1 2 1 2
3 2 1 3 0 4 0 1
2 2 1 3 1 2
2 3 1 4 0 1
3 3 1 4 1 5 0 1
2 4 0 5 0 2
2 5 0 6 0 2
3 5 0 6 1 7 1 1
3 6 0 7 0 8 1 1
2 6 0 7 1 1
2 7 1 8 1 2
3 8 1 9 0 10 0 1
2 8 1 9 1 2
2 9 1 10 0 1
3 9 1 10 1 11 0 1
2 10 0 11 0 2
2 11 0 12 0 2
3 11 0 12 1 13 1 1
3 12 0 13 0 14 1 1
2 12 0 13 1 1
2 13 1 14 1 2
2 14 1 15 0 1
2 14 1 15 1 2

View File

@ -0,0 +1,41 @@
4
4 0 0 4 1 11 1 15 0
6 0 0 1 0 5 1 10 1 14 0 15 0
6 0 0 2 0 6 1 9 1 13 0 15 0
6 0 0 3 0 7 1 8 1 12 0 15 0
0
12
17
7
0 0
1 0
2 0
5 1
6 1
7 1
8 1
9 1
10 1
13 0
14 0
15 0
2 0 0 1 0 3
3 0 0 4 1 5 1 1
2 1 0 2 0 2
2 1 0 5 1 1
3 2 0 3 0 7 1 1
2 2 0 6 1 1
2 5 1 6 1 2
2 6 1 7 1 3
2 7 1 8 1 4
3 8 1 12 0 13 0 1
2 8 1 9 1 3
2 9 1 13 0 1
2 9 1 10 1 2
2 10 1 14 0 1
3 10 1 11 1 15 0 1
2 13 0 14 0 2
2 14 0 15 0 3

View File

@ -0,0 +1,75 @@
4
4 0 4 4 0 13 0 17 4
4 0 3 5 0 12 0 17 3
4 0 2 6 0 11 0 17 2
4 0 1 7 0 10 0 17 1
0
26
37
13
0 1
0 2
0 3
0 4
5/2 3/2
3 1
7/2 1/2
15/4 3/4
35/8 3/8
5 0
21/4 1/4
6 0
7 0
10 0
11 0
47/4 1/4
12 0
101/8 3/8
53/4 3/4
27/2 1/2
14 1
29/2 3/2
17 1
17 2
17 3
17 4
2 0 1 7/2 1/2 1
2 0 2 3 1 1
2 0 3 5/2 3/2 1
2 0 4 5/2 3/2 1
2 5/2 3/2 3 1 1
2 5/2 3/2 15/4 3/4 1
2 3 1 7/2 1/2 1
2 3 1 15/4 3/4 1
3 7/2 1/2 4 0 5 0 1
2 7/2 1/2 35/8 3/8 1
2 15/4 3/4 35/8 3/8 1
2 15/4 3/4 21/4 1/4 1
2 35/8 3/8 5 0 1
2 35/8 3/8 21/4 1/4 1
2 5 0 6 0 2
2 21/4 1/4 6 0 1
2 21/4 1/4 7 0 1
2 6 0 7 0 3
2 7 0 10 0 4
2 10 0 11 0 3
2 10 0 47/4 1/4 1
2 11 0 12 0 2
2 11 0 47/4 1/4 1
2 47/4 1/4 101/8 3/8 1
2 47/4 1/4 53/4 3/4 1
3 12 0 13 0 27/2 1/2 1
2 12 0 101/8 3/8 1
2 101/8 3/8 27/2 1/2 1
2 101/8 3/8 53/4 3/4 1
2 53/4 3/4 14 1 1
2 53/4 3/4 29/2 3/2 1
2 27/2 1/2 17 1 1
2 27/2 1/2 14 1 1
2 14 1 17 2 1
2 14 1 29/2 3/2 1
2 29/2 3/2 17 3 1
2 29/2 3/2 17 4 1

View File

@ -0,0 +1,48 @@
3
4 0 4 4 0 13 0 17 4
4 0 3 5 0 12 0 17 3
4 0 2 6 0 11 0 17 2
0
16
21
7
0 2
0 3
0 4
5/2 3/2
3 1
15/4 3/4
5 0
6 0
11 0
12 0
53/4 3/4
14 1
29/2 3/2
17 2
17 3
17 4
2 0 2 3 1 1
2 0 3 5/2 3/2 1
2 0 4 5/2 3/2 1
2 5/2 3/2 3 1 1
2 5/2 3/2 15/4 3/4 1
3 3 1 4 0 5 0 1
2 3 1 15/4 3/4 1
2 15/4 3/4 5 0 1
2 15/4 3/4 6 0 1
2 5 0 6 0 2
2 6 0 11 0 3
2 11 0 12 0 2
2 11 0 53/4 3/4 1
3 12 0 13 0 14 1 1
2 12 0 53/4 3/4 1
2 53/4 3/4 14 1 1
2 53/4 3/4 29/2 3/2 1
2 14 1 17 2 1
2 14 1 29/2 3/2 1
2 29/2 3/2 17 3 1
2 29/2 3/2 17 4 1

View File

@ -0,0 +1,34 @@
6
1 3 4 0
4 0 5 0
5 0 7 2
0 0 9 0
3 0 6 0
2 0 8 0
0
10
9
1
0 0
1 3
2 0
3 0
4 0
5 0
6 0
7 2
8 0
9 0
0 0 2 0 1
1 3 4 0 1
2 0 3 0 2
3 0 4 0 3
4 0 5 0 4
5 0 6 0 3
5 0 7 2 1
6 0 8 0 2
8 0 9 0 1

View File

@ -0,0 +1,31 @@
5
1 3 4 0
4 0 5 0
0 0 9 0
3 0 6 0
2 0 8 0
0
9
8
1
0 0
1 3
2 0
3 0
4 0
5 0
6 0
8 0
9 0
0 0 2 0 1
1 3 4 0 1
2 0 3 0 2
3 0 4 0 3
4 0 5 0 4
5 0 6 0 3
6 0 8 0 2
8 0 9 0 1

View File

@ -0,0 +1,34 @@
6
1 3 4 0
4 0 5 0
0 0 9 0
3 0 6 0
7 1 8 0
2 0 8 0
0
10
9
1
0 0
1 3
2 0
3 0
4 0
5 0
6 0
7 1
8 0
9 0
0 0 2 0 1
1 3 4 0 1
2 0 3 0 2
3 0 4 0 3
4 0 5 0 4
5 0 6 0 3
6 0 8 0 2
7 1 8 0 1
8 0 9 0 1

View File

@ -0,0 +1,24 @@
4
0 0 4 0
1 0 3 0
2 0 5 0
2 0 3 0
0
6
5
1
0 0
1 0
2 0
3 0
4 0
5 0
0 0 1 0 1
1 0 2 0 2
2 0 3 0 4
3 0 4 0 2
4 0 5 0 1

View File

@ -0,0 +1,9 @@
./data/test_construction/polylines/test01.txt
./data/test_construction/polylines/test02.txt
./data/test_construction/polylines/test03.txt
./data/test_construction/polylines/test04.txt
./data/test_construction/polylines/test05.txt
./data/test_construction/polylines/test06.txt
./data/test_construction/polylines/test07.txt
./data/test_construction/polylines/test08.txt
./data/test_construction/polylines/test09.txt

View File

@ -45,3 +45,6 @@
./data/test_construction/segments/test45.txt
./data/test_construction/segments/test46.txt
./data/test_construction/segments/test47.txt
./data/test_construction/segments/test48.txt
./data/test_construction/segments/test49.txt
./data/test_construction/segments/test50.txt

View File

@ -31,10 +31,13 @@
*/
#include <list>
#include <vector>
#include <CGAL/Object.h>
#include <CGAL/Basic_sweep_line_2.h>
#include <CGAL/Sweep_line_2/Sweep_line_curve_pair.h>
#include <CGAL/Arrangement_2/Open_hash.h>
#include <CGAL/algorithm.h>
namespace CGAL {
@ -155,6 +158,7 @@ public:
virtual ~Sweep_line_2() {}
protected:
typedef typename std::vector<Subcurve*> Subcurve_vector;
/*! Initialize the data structures for the sweep-line algorithm. */
virtual void _init_structures();
@ -171,22 +175,28 @@ protected:
/*! Add a subcurve to the right of an event point.
* \param event The event point.
* \param curve The subcurve to add.
* \return (true) if an overlap occured; (false) otherwise.
*/
virtual bool _add_curve_to_right(Event* event, Subcurve* curve,
bool overlap_exist = false);
virtual bool _add_curve_to_right(Event* event, Subcurve* curve);
/*! Fix overlapping subcurves before handling the current event. */
void _fix_overlap_subcurves();
/*! Handle overlap at right insertion to event.
* \param event The event point.
* \param curve The subcurve representing the overlap.
* \param iter An iterator for the curves.
* \param overlap_exist
/*! create an overlap subcurve from overlap_cv between c1 and c2.
* \param overlap_cv the overlapping curve.
* \param c1 first subcurve contributing to the overlap.
* \param c2 second subcurve contributing to the overlap.
* \param all_leaves_diff not empty in case c1 and c2 have common ancesters.
* It contains the set of curves not contained in first_parent
* that are in the other subcurve
* \param first_parent only used when c1 and c2 have common ancesters.
* It is either c1 or c2 (the one having the more leaves)
*
*/
void _handle_overlap(Event* event, Subcurve* curve,
Event_subcurve_iterator iter, bool overlap_exist);
void _create_overlapping_curve(const X_monotone_curve_2& overlap_cv,
Subcurve*& c1 , Subcurve*& c2,
const Subcurve_vector& all_leaves_diff,
Subcurve* first_parent,
Event* event_on_overlap);
/*! Compute intersections between the two given curves.
* If the two curves intersect, create a new event (or use the event that
@ -195,7 +205,7 @@ protected:
* \param curve1 The first curve.
* \param curve2 The second curve.
*/
void _intersect(Subcurve* c1, Subcurve* c2);
void _intersect(Subcurve* c1, Subcurve* c2, Event* event_for_overlap = NULL);
/*! When a curve is removed from the status line for good, its top and
* bottom neighbors become neighbors. This method finds these cases and
@ -211,13 +221,11 @@ protected:
* \param mult Its multiplicity.
* \param curve1 The first curve.
* \param curve2 The second curve.
* \param is_overlap Whether the two curves overlap at xp.
*/
void _create_intersection_point(const Point_2& xp,
unsigned int mult,
Subcurve*& c1,
Subcurve*& c2,
bool is_overlap = false);
Subcurve*& c2);
/*! Fix a subcurve that represents an overlap.
* \param sc The subcurve.

View File

@ -553,7 +553,9 @@ add_subcurve(const X_monotone_curve_2& cv, Subcurve* sc)
// In case the event has no more right subcurves associated with it, we can
// deallocate it. Note that we inform the helper class before deallocating
// the event.
if (last_event->dec_right_curves_counter() == 0) {
if (((Event*) sc->right_event())==this->current_event() &&
last_event->dec_right_curves_counter() == 0)
{
m_helper.before_deallocate_event(last_event);
this->deallocate_event(last_event);
}

View File

@ -108,7 +108,8 @@ public:
OutputIterator oi)
{
if(cv1.halfedge_handle() != invalid_he &&
cv2.halfedge_handle() != invalid_he)
cv2.halfedge_handle() != invalid_he &&
cv1.halfedge_handle()!=cv2.halfedge_handle())
{
// The curves are interior-disjoint as both of them are already in
// the arrangement.

View File

@ -466,6 +466,7 @@ void Basic_sweep_line_2<Tr, Vis, Subcv, Evnt, Alloc>::_sort_left_curves()
Subcurve* curve = *(m_currentEvent->left_curves_begin());
Status_line_iterator sl_iter = curve->hint();
CGAL_assertion(sl_iter != m_statusLine.end());
CGAL_assertion(*sl_iter == curve);
// Look for the first curve in the vertical ordering that is also in the
// left curve of the event
@ -559,7 +560,7 @@ void Basic_sweep_line_2<Tr, Vis, Subcv, Evnt, Alloc>::_handle_right_curves()
template <typename Tr, typename Vis, typename Subcv, typename Evnt,
typename Alloc>
bool Basic_sweep_line_2<Tr, Vis, Subcv, Evnt, Alloc>::
_add_curve_to_right(Event* event, Subcurve* curve, bool /* overlap_exist */)
_add_curve_to_right(Event* event, Subcurve* curve)
{
#if defined(CGAL_NO_ASSERTIONS)
(void) event->add_curve_to_right(curve, m_traits);
@ -592,6 +593,7 @@ _remove_curve_from_status_line(Subcurve* sc)
// The position of the next event can be right after the deleted subcurve.
m_status_line_insert_hint = sl_iter;
++m_status_line_insert_hint;
sc->set_hint(m_statusLine.end());
// Erase the subcurve from the status line.
CGAL_SL_PRINT_ERASE(*sl_iter);

View File

@ -96,12 +96,16 @@ void Sweep_line_2<Tr, Vis, Subcv, Evnt, Alloc>::_handle_left_curves()
CGAL_SL_PRINT_EOL();
this->_handle_event_without_left_curves();
Status_line_iterator sl_pos = this->m_status_line_insert_hint;
// Status_line_iterator sl_pos = this->m_status_line_insert_hint;
if (this->m_is_event_on_above) {
CGAL_SL_PRINT_TEXT("The event is on a curve in the status line");
CGAL_SL_PRINT_EOL();
// Obtain the subcurve that contains the current event
Subcurve* sc = static_cast<Subcurve*>(*(this->m_status_line_insert_hint));
// The current event point starts at the interior of a subcurve that
// already exists in the status line (this may also indicate an overlap).
if (! this->m_currentEvent->has_right_curves()) {
@ -117,37 +121,26 @@ void Sweep_line_2<Tr, Vis, Subcv, Evnt, Alloc>::_handle_left_curves()
// intersection.
CGAL_assertion(this->m_currentEvent->is_action());
this->m_currentEvent->set_weak_intersection();
}
// Obtain the subcurve that contains the current event, and add it to
// the left curves incident to the event.
Subcurve* sc = static_cast<Subcurve*>(*(this->m_status_line_insert_hint));
const X_monotone_curve_2& last_curve = sc->last_curve();
this->m_currentEvent->set_weak_intersection();
this->m_visitor->update_event(this->m_currentEvent, sc);
this->m_currentEvent->add_curve_to_left(sc);
// If necessary, add the subcurves as a right incident curve as well.
// We also check for overlaps.
bool is_overlap = _add_curve_to_right(this->m_currentEvent, sc);
this->m_traits->split_2_object()(last_curve,
this->m_currentEvent->point(),
sub_cv1, sub_cv2);
++(this->m_status_line_insert_hint);
if (is_overlap) {
// Handle overlaps.
this->m_visitor->before_handle_event(this->m_currentEvent);
this->m_visitor->add_subcurve(sub_cv1, sc);
CGAL_SL_PRINT_ERASE(*sl_pos);
this->m_statusLine.erase(sl_pos);
CGAL_SL_PRINT_END_EOL("handling left curves");
return;
this->m_currentEvent->push_back_curve_to_right(sc);
}
else
{
this->m_currentEvent->push_back_curve_to_left(sc);
this->m_currentEvent->set_weak_intersection();
this->m_visitor->update_event(this->m_currentEvent, sc);
_add_curve_to_right(this->m_currentEvent, sc);
}
// sc is now on the left
CGAL_SL_PRINT_TEXT("Event after update:");
CGAL_SL_PRINT_EOL();
CGAL_SL_PRINT_EVENT_INFO(this->m_currentEvent);
CGAL_SL_PRINT_EOL();
CGAL_assertion(std::distance(this->m_currentEvent->left_curves_begin(),
this->m_currentEvent->left_curves_end())==1);
}
else {
// The event is not located on any subcurve.
@ -189,7 +182,6 @@ void Sweep_line_2<Tr, Vis, Subcv, Evnt, Alloc>::_handle_left_curves()
else {
// curren event splits the subcurve.
const X_monotone_curve_2& lastCurve = leftCurve->last_curve();
this->m_traits->split_2_object()(lastCurve, this->m_currentEvent->point(),
sub_cv1, sub_cv2);
this->m_visitor->add_subcurve(sub_cv1, leftCurve);
@ -222,6 +214,34 @@ void Sweep_line_2<Tr, Vis, Subcv, Evnt, Alloc>::_handle_right_curves()
return;
}
// Some overlapping curves that are on the right might not be
// on the left (in case of overlap with other curves having common
// ancesters). Consequently, an overlapping curve on the right might
// not have been split.
// SL_SAYS: we should be able to do something better without geometric test
// (like having an additional boolean in subcurve that we can set in
// _handle_left_curves() after a split)
for( Event_subcurve_iterator cit = this->m_currentEvent->right_curves_begin(),
cit_end = this->m_currentEvent->right_curves_end();
cit!=cit_end; ++cit)
{
if ( (*cit)->originating_subcurve1()!=NULL &&
(Event*)(*cit)->left_event()!=this->m_currentEvent )
{
// split the subcurve.
const X_monotone_curve_2& lastCurve = (*cit)->last_curve();
if (!this->m_traits->equal_2_object()(
this->m_traits->construct_min_vertex_2_object()(lastCurve),
this->m_currentEvent->point()))
{
this->m_traits->split_2_object()(lastCurve, this->m_currentEvent->point(),
sub_cv1, sub_cv2);
(*cit)->set_last_curve(sub_cv2);
}
}
}
// Loop over the curves to the right of the status line and handle them:
// - If we are at the beginning of the curve, we insert it to the status
// line, then we look if it intersects any of its neighbors.
@ -290,7 +310,7 @@ void Sweep_line_2<Tr, Vis, Subcv, Evnt, Alloc>::_handle_right_curves()
template <typename Tr, typename Vis, typename Subcv, typename Evnt,
typename Alloc>
bool Sweep_line_2<Tr, Vis, Subcv, Evnt, Alloc>::
_add_curve_to_right(Event* event, Subcurve* curve, bool overlap_exist)
_add_curve_to_right(Event* event, Subcurve* curve)
{
CGAL_SL_PRINT_START("adding a Curve to the right of (");
CGAL_SL_DEBUG(this->PrintEvent(event));
@ -304,49 +324,19 @@ _add_curve_to_right(Event* event, Subcurve* curve, bool overlap_exist)
{
CGAL_SL_PRINT_CURVE(*iter);
CGAL_SL_PRINT_EOL();
if ((curve == *iter) || (*iter)->is_inner_node(curve)) {
if ((*iter)->are_all_leaves_contained(curve)) {
CGAL_SL_PRINT_END_EOL("adding a Curve to the right (curve exists)");
return false;
}
if ((curve)->is_inner_node(*iter)) {
if ((curve)->are_all_leaves_contained(*iter)) {
*iter = curve; // replace the current curve with the new one.
CGAL_SL_PRINT_END_EOL
("adding a Curve to the right (curve partially overlaps)");
return false;
}
/*! If the two curves have the exact same leaves, then use the new curve
* as a right curve instead of the existing one.
* \todo EF, this may not be a sufficient condition. It is possible that
* we also need to check whether the event at the right endpoint has a
* matching left curve, and only if it has, make the switch. If this is
* the case, then other modifications are necessary. I hope it's not.
*/
if ((curve)->has_same_leaves(*iter)) {
*iter = curve; // replace the current curve with the new one.
CGAL_SL_PRINT_END_EOL
("adding a Curve to the right (curve completely overlaps)");
return false;
}
if ((curve)->has_common_leaf(*iter)) {
/*! Collect all the distinct nodes of curves including the common nodes.
* \todo EF, common nodes should be excluded. It is not incorrect to
* include a common node, because in the recursive call it becomes
* 'curve', which is an inner node of iter, and it is discarded; see 2
* conditions above.
*/
std::list<Base_subcurve*> list_of_sc;
curve->distinct_nodes(*iter, std::back_inserter(list_of_sc));
typename std::list<Base_subcurve*>::iterator sc_iter;
for (sc_iter = list_of_sc.begin(); sc_iter != list_of_sc.end(); ++sc_iter)
_add_curve_to_right(event, static_cast<Subcurve*>(*sc_iter));
CGAL_SL_PRINT_END_EOL("adding a Curve to the right (common leaf)");
return true;
}
CGAL_assertion(!(curve)->has_same_leaves(*iter));
}
std::pair<bool, Event_subcurve_iterator> pair_res =
event->add_curve_to_right(curve, this->m_traits);
@ -357,9 +347,16 @@ _add_curve_to_right(Event* event, Subcurve* curve, bool overlap_exist)
return false;
}
_handle_overlap(event, curve, pair_res.second, overlap_exist);
// a new overlap needs to be computed
_intersect(static_cast<Subcurve*>(curve),
static_cast<Subcurve*>(*(pair_res.second)),
event);
// SL_SAYS: we need to be sure that the overlapping curve generated by
// `curve` and `*(pair_res.second)` has not yet been computed or
// that the overlapping curve will be added to the right of
// `event` because of an adjacency in the status line.
// Inidicate that an overlap has occured:
// Indicate that an overlap has occured:
CGAL_SL_PRINT_END_EOL("adding a Curve to the right (overlap)");
return true;
}
@ -380,6 +377,7 @@ _remove_curve_from_status_line(Subcurve* leftCurve, bool remove_for_good)
Status_line_iterator sliter = leftCurve->hint();
this->m_status_line_insert_hint = sliter;
++(this->m_status_line_insert_hint);
leftCurve->set_hint(this->m_statusLine.end());
if (! remove_for_good) {
// the subcurve is not removed for good, so we dont need to intersect
@ -417,7 +415,8 @@ _remove_curve_from_status_line(Subcurve* leftCurve, bool remove_for_good)
template <typename Tr, typename Vis, typename Subcv, typename Evnt,
typename Alloc>
void Sweep_line_2<Tr, Vis, Subcv, Evnt, Alloc>::_intersect(Subcurve* c1,
Subcurve* c2)
Subcurve* c2,
Event* event_for_overlap)
{
CGAL_SL_PRINT_START("computing intersection of ");
CGAL_SL_PRINT_CURVE(c1);
@ -432,7 +431,10 @@ void Sweep_line_2<Tr, Vis, Subcv, Evnt, Alloc>::_intersect(Subcurve* c1,
// look up for (c1,c2) in the table and insert if doesnt exist
Curve_pair cv_pair(c1,c2);
if (! (m_curves_pair_set.insert(cv_pair)).second)
{
CGAL_SL_PRINT_END_EOL("computing intersection (already computed)");
return; //the curves have already been checked for intersection
}
float load_factor = static_cast<float>(m_curves_pair_set.size()) /
m_curves_pair_set.bucket_count();
@ -440,8 +442,112 @@ void Sweep_line_2<Tr, Vis, Subcv, Evnt, Alloc>::_intersect(Subcurve* c1,
if (load_factor > 6.0f)
m_curves_pair_set.resize(m_curves_pair_set.size() * 6);
// handle overlapping curves with common ancesters
Subcurve_vector all_leaves_diff;
Subcurve* first_parent=NULL;
if (c1->originating_subcurve1()!=NULL || c2->originating_subcurve2()!=NULL)
{
// get the subcurve leaves of c1 and of c2. Then extract from the smallest set
// the subcurves leaves that are not in the other one. If empty, it means that
// a subcurves is completely contained in another one.
first_parent = c1;
Subcurve* second_parent = c2;
Subcurve_vector all_leaves_first;
Subcurve_vector all_leaves_second;
first_parent->template all_leaves<Subcurve>(std::back_inserter(all_leaves_first));
second_parent->template all_leaves<Subcurve>(std::back_inserter(all_leaves_second));
if (all_leaves_second.size() > all_leaves_first.size())
{
std::swap(first_parent,second_parent);
std::swap(all_leaves_first,all_leaves_second);
}
CGAL_assertion(!all_leaves_first.empty() && !all_leaves_second.empty());
std::sort(all_leaves_first.begin(), all_leaves_first.end());
std::sort(all_leaves_second.begin(), all_leaves_second.end());
std::set_difference(all_leaves_second.begin(), all_leaves_second.end(),
all_leaves_first.begin(), all_leaves_first.end(),
std::back_inserter(all_leaves_diff));
if (all_leaves_second.size()==all_leaves_diff.size())
all_leaves_diff.clear(); // clear so that it is not used by _create_overlapping_curve()
else
if (all_leaves_diff.empty())
{
CGAL_SL_PRINT_TEXT("One overlapping curve entirely contains the other one");
CGAL_SL_PRINT_EOL();
Event* left_event = (Event*) first_parent->left_event();
Event* right_event = (Event*) first_parent->right_event();
if (!second_parent->is_start_point(left_event))
left_event->add_curve_to_left(second_parent);
else
left_event->remove_curve_from_right(second_parent);
CGAL_SL_PRINT_CURVE(c1);
CGAL_SL_PRINT_TEXT(" + ");
CGAL_SL_PRINT_CURVE(c2);
CGAL_SL_PRINT_TEXT(" => ");
CGAL_SL_PRINT_EOL();
CGAL_SL_PRINT_TEXT(" ");
CGAL_SL_PRINT_CURVE(first_parent);
CGAL_SL_PRINT_EOL();
// Remove second_parent from the left curves of the right end
// and add it on the right otherwise
if (second_parent->is_end_point(right_event))
right_event->remove_curve_from_left(second_parent);
else
_add_curve_to_right(right_event, second_parent);
// add the overlapping curve kept of the right of the left end
_add_curve_to_right(left_event, first_parent);
right_event->add_curve_to_left(first_parent);
this->m_visitor->found_overlap(c1, c2, first_parent);
CGAL_SL_PRINT_END_EOL("computing intersection");
return;
}
else{
CGAL_SL_PRINT_TEXT("Overlap with common ancestors");
CGAL_SL_PRINT_EOL();
// iteratively create the final overlapping (geometric) curve.
// This is needed rather than simply computing the intersection of
// the last curves of first_parent and second_parent as some traits
// classes (such as Arr_curve_data_traits_2) override the Intersect_2
// functor and expects the curve to have no common ancesters
// (Arr_curve_data_traits_2 is used in the testsuite to sum up
// the overlapping degree of a curve)
X_monotone_curve_2 xc = first_parent->last_curve();
for (typename Subcurve_vector::iterator sc_it=all_leaves_diff.begin();
sc_it!=all_leaves_diff.end(); ++sc_it)
{
std::vector<CGAL::Object> inter_res;
;
this->m_traits->intersect_2_object()(xc,
(*sc_it)->last_curve(),
vector_inserter(inter_res));
CGAL_assertion(inter_res.size()==1);
CGAL_assertion( CGAL::object_cast< X_monotone_curve_2 >(&inter_res.front())!=NULL );
xc = *CGAL::object_cast< X_monotone_curve_2 >(&inter_res.front());
}
_create_overlapping_curve(xc, c1 , c2, all_leaves_diff, first_parent, event_for_overlap);
CGAL_SL_PRINT_END_EOL("computing intersection (overlap with common ancestors)");
return;
}
}
// do compute the intersection of the two curves
vector_inserter vi(m_x_objects) ;
vector_inserter vi_end(m_x_objects);
vi_end =
this->m_traits->intersect_2_object()(c1->last_curve(), c2->last_curve(), vi);
@ -451,7 +557,7 @@ void Sweep_line_2<Tr, Vis, Subcv, Evnt, Alloc>::_intersect(Subcurve* c1,
}
// The two subCurves may start at the same point, in that case we ignore the
// first intersection point (if we got to that stage, they cannot overlap).
// first intersection point.
const Arr_parameter_space ps_x1 =
this->m_traits->parameter_space_in_x_2_object()(c1->last_curve(),
@ -471,7 +577,8 @@ void Sweep_line_2<Tr, Vis, Subcv, Evnt, Alloc>::_intersect(Subcurve* c1,
this->m_traits->is_closed_2_object()(c1->last_curve(), ARR_MIN_END) &&
this->m_traits->is_closed_2_object()(c2->last_curve(), ARR_MIN_END))
{
if (this->m_traits->equal_2_object()
if ( object_cast<std::pair<Point_2, Multiplicity> >(&(*vi)) != NULL
&& this->m_traits->equal_2_object()
(this->m_traits->construct_min_vertex_2_object()(c1->last_curve()),
this->m_traits->construct_min_vertex_2_object()(c2->last_curve())))
{
@ -554,12 +661,11 @@ void Sweep_line_2<Tr, Vis, Subcv, Evnt, Alloc>::_intersect(Subcurve* c1,
for (; vi != vi_end; ++vi) {
const X_monotone_curve_2* icv;
Point_2 xp;
unsigned int multiplicity = 0;
xp_point = object_cast<std::pair<Point_2, Multiplicity> >(&(*vi));
if (xp_point != NULL) {
xp = xp_point->first;
Point_2 xp = xp_point->first;
multiplicity = xp_point->second;
CGAL_SL_PRINT_TEXT("Found an intersection point");
CGAL_SL_PRINT_EOL();
@ -570,14 +676,7 @@ void Sweep_line_2<Tr, Vis, Subcv, Evnt, Alloc>::_intersect(Subcurve* c1,
CGAL_assertion(icv != NULL);
CGAL_SL_PRINT_TEXT("Found an overlap");
CGAL_SL_PRINT_EOL();
// TODO EBEB: This code does not work with overlaps that reach the boundary
Point_2 left_xp = this->m_traits->construct_min_vertex_2_object()(*icv);
xp = this->m_traits->construct_max_vertex_2_object()(*icv);
sub_cv1 = *icv;
_create_intersection_point(xp, 0 , c1 , c2);
_create_intersection_point(left_xp, 0 , c1 ,c2, true);
_create_overlapping_curve(*icv, c1 , c2, all_leaves_diff, first_parent, event_for_overlap);
}
}
@ -592,10 +691,9 @@ template <typename Tr, typename Vis, typename Subcv, typename Evnt,
void Sweep_line_2<Tr, Vis, Subcv, Evnt, Alloc>::
_create_intersection_point(const Point_2& xp,
unsigned int multiplicity,
Subcurve*& c1, Subcurve*& c2,
bool is_overlap)
Subcurve*& c1, Subcurve*& c2)
{
CGAL_SL_PRINT_START_EOL("createing an intersection point netween");
CGAL_SL_PRINT_START_EOL("creating an intersection point between");
CGAL_SL_PRINT_CURVE(c1);
CGAL_SL_PRINT_EOL();
CGAL_SL_PRINT_CURVE(c2);
@ -607,7 +705,7 @@ _create_intersection_point(const Point_2& xp,
Event* e = pair_res.first;
if (pair_res.second) {
// a new event is creatd , which inidicates that the intersection point
// a new event is created , which indicates that the intersection point
// cannot be one of the end-points of two curves
CGAL_SL_PRINT_TEXT("A new event is created .. (");
CGAL_SL_PRINT(xp);
@ -623,11 +721,9 @@ _create_intersection_point(const Point_2& xp,
// Act according to the multiplicity:
if (multiplicity == 0) {
// The multiplicity of the intersection point is unkown or undefined:
_add_curve_to_right(e, c1, is_overlap);
_add_curve_to_right(e, c2, is_overlap);
if (! is_overlap) {
if (e->is_right_curve_bigger(c1, c2)) std::swap(c1, c2);
}
_add_curve_to_right(e, c1);
_add_curve_to_right(e, c2);
if (e->is_right_curve_bigger(c1, c2, this->m_traits)) std::swap(c1, c2);
}
else {
if ((multiplicity % 2) == 1) {
@ -650,42 +746,45 @@ _create_intersection_point(const Point_2& xp,
CGAL_SL_PRINT(xp);
CGAL_SL_PRINT_TEXT(")");
CGAL_SL_PRINT_EOL();
if (e == this->m_currentEvent) {
// This can happen when c1 starts at the interior of c2 (or vice versa).
return;
}
e->add_curve_to_left(c1);
e->add_curve_to_left(c2);
if (!c1->is_start_point(e)) e->add_curve_to_left(c1);
if (!c2->is_start_point(e)) e->add_curve_to_left(c2);
if (!c1->is_end_point(e) && !c2->is_end_point(e)) {
_add_curve_to_right(e, c1, is_overlap);
_add_curve_to_right(e, c2, is_overlap);
_add_curve_to_right(e, c1);
_add_curve_to_right(e, c2);
e->set_intersection();
this->m_visitor->update_event(e, c1, c2, false);
if (multiplicity==0)
{
if (e->is_right_curve_bigger(c1, c2, this->m_traits)) std::swap(c1, c2);
}
else
{
if (multiplicity%2==1) std::swap(c1, c2);
}
}
else {
if (!c1->is_end_point(e) && c2->is_end_point(e)) {
_add_curve_to_right(e, c1, is_overlap);
_add_curve_to_right(e, c1);
e->set_weak_intersection();
this->m_visitor->update_event(e, c1);
}
else {
if (c1->is_end_point(e) && !c2->is_end_point(e)) {
_add_curve_to_right(e, c2, is_overlap);
_add_curve_to_right(e, c2);
e->set_weak_intersection();
this->m_visitor->update_event(e, c2);
}
}
}
if (! is_overlap) {
if (e->is_right_curve_bigger(c1, c2)) std::swap(c1, c2);
}
CGAL_SL_PRINT_EVENT_INFO(e);
}
CGAL_SL_PRINT_END_EOL("Createing an intersection point");
CGAL_SL_PRINT_END_EOL("Creating an intersection point");
}
//-----------------------------------------------------------------------------
@ -701,7 +800,7 @@ void Sweep_line_2<Tr, Vis, Subcv, Evnt, Alloc>::_fix_overlap_subcurves()
Event_subcurve_iterator iter = this->m_currentEvent->left_curves_begin();
//special treatment for Subcuves that store overlaps
//special treatment for Subcurves that store overlaps
while (iter != this->m_currentEvent->left_curves_end()) {
Subcurve* leftCurve = *iter;
@ -722,160 +821,174 @@ void Sweep_line_2<Tr, Vis, Subcv, Evnt, Alloc>::_fix_overlap_subcurves()
CGAL_SL_PRINT_END_EOL("Fixing overlap subcurves");
}
/*! Handle overlap at right insertion to event.
* \param event the event where that overlap starts (the left end point of the
* overlap).
* \param curve the subcurve that its insertion to the list of right subcurves of
* 'event' causes the overlap (with *iter).
* \param iter the existing subcurve at the right subcurves of 'event'
* \param overlap_exist a flag indicates if the overlap X_monotone_curve_2 was
* computed already (is true than its stored at sub_cv1 data member).
*/
template <typename Tr, typename Vis, typename Subcv, typename Evnt,
typename Alloc>
void Sweep_line_2<Tr, Vis, Subcv, Evnt, Alloc>::
_handle_overlap(Event* event, Subcurve* curve, Event_subcurve_iterator iter,
bool overlap_exist)
_create_overlapping_curve(const X_monotone_curve_2& overlap_cv,
Subcurve*& c1 , Subcurve*& c2,
const Subcurve_vector& all_leaves_diff,
Subcurve* first_parent,
Event* event_on_overlap)
{
// An overlap occurs:
CGAL_SL_PRINT_START_EOL("handling overlap at right insertion");
CGAL_SL_PRINT_START_EOL("creating an overlapping curve");
X_monotone_curve_2 overlap_cv;
if (overlap_exist) overlap_cv = sub_cv1;
else {
// compute the overlap.
std::vector<Object> obj_vec;
vector_inserter vit(obj_vec);
this->m_traits->intersect_2_object()(curve->last_curve(),
(*iter)->last_curve(),
vit);
if (obj_vec.empty()) {
CGAL_SL_PRINT_END_EOL("handling overlap");
return;
}
overlap_cv = object_cast<X_monotone_curve_2>(obj_vec.front());
}
// Get the right end of overlap_cv (if it is closed from the right).
Event* right_end;
Arr_parameter_space ps_x_r =
this->m_traits->parameter_space_in_x_2_object()(overlap_cv, ARR_MAX_END);
Arr_parameter_space ps_y_r =
this->m_traits->parameter_space_in_y_2_object()(overlap_cv, ARR_MAX_END);
CGAL_assertion(ps_x_r != ARR_LEFT_BOUNDARY);
if ((ps_x_r != ARR_INTERIOR) || (ps_y_r != ARR_INTERIOR)) {
// The overlapping subcurve is either open from the right, or
// touches the boundary of the surface. In either case, the curves that
// are involved in the overlap must also be open or defined at the
// boundary, so the event associated with their right ends already exists,
// and we set it as the overlapping subcurve's right event.
CGAL_assertion((*iter)->right_event() == curve->right_event());
right_end = (Event*)(curve->right_event());
}
else {
// The overlapping subcurve has a valid right endpoint.
// Find the event associated with this point (or create a new event).
Point_2 end_overlap =
this->m_traits->construct_max_vertex_2_object()(overlap_cv);
const std::pair<Event*, bool>& pair_res =
this->_push_event(end_overlap, Base_event::OVERLAP, ps_x_r, ps_y_r);
right_end = pair_res.first;
}
// Get the left end of overlap_cv (if it is closed from the left).
// Get the left end of overlap_cv.
Event* left_event;
Arr_parameter_space ps_x_l =
this->m_traits->parameter_space_in_x_2_object()(overlap_cv, ARR_MIN_END);
Arr_parameter_space ps_y_l =
this->m_traits->parameter_space_in_y_2_object()(overlap_cv, ARR_MIN_END);
CGAL_assertion(ps_x_l != ARR_RIGHT_BOUNDARY);
if ((ps_x_l == ARR_INTERIOR) && (ps_y_l == ARR_INTERIOR)) {
// The left end of the overlapping subcurve is regular point, so in case
// the event is also associated with a regular point (not incident to the
// surface boundaries), we make sure that the overlapping subcurve does
// not start to the left of this event.
if (! event->is_on_boundary()) {
// If the left endpoint of the overlapping curve is to the left of the
// event, split the overlapping subcurve so its left endpoint equals
// the event point.
const Point_2& begin_overlap =
this->m_traits->construct_min_vertex_2_object()(overlap_cv);
Comparison_result res =
this->m_traits->compare_xy_2_object()(event->point(), begin_overlap);
CGAL_assertion(res != SMALLER);
if (res == LARGER) {
this->m_traits->split_2_object()(overlap_cv, event->point(),
sub_cv1, sub_cv2);
overlap_cv = sub_cv2;
}
}
if ((ps_x_l != ARR_INTERIOR) || (ps_y_l != ARR_INTERIOR)) {
CGAL_assertion(c1->left_event() == c2->left_event());
left_event=(Event*)(c1->left_event());
}
else{
// The left end of the overlapping subcurve is either open, or
// incident to the surface boundaries. In case the current event is
// associated with a regular point, it must lie to the right of this
// curve-end, so we clip the overlapping subcurve accordingly.
if (! event->is_on_boundary()) {
this->m_traits->split_2_object()(overlap_cv, event->point(),
sub_cv1, sub_cv2);
overlap_cv = sub_cv2;
Point_2 left_end = this->m_traits->construct_min_vertex_2_object()(overlap_cv);
left_event = this->_push_event(left_end, Base_event::DEFAULT, ARR_INTERIOR, ARR_INTERIOR).first;
}
// Get the right end of overlap_cv.
Event* right_event;
Arr_parameter_space ps_x_r =
this->m_traits->parameter_space_in_x_2_object()(overlap_cv, ARR_MAX_END);
Arr_parameter_space ps_y_r =
this->m_traits->parameter_space_in_y_2_object()(overlap_cv, ARR_MAX_END);
if ((ps_x_r != ARR_INTERIOR) || (ps_y_r != ARR_INTERIOR)) {
CGAL_assertion(c1->right_event() == c2->right_event());
right_event = (Event*)(c1->right_event());
}
else {
Point_2 right_end = this->m_traits->construct_max_vertex_2_object()(overlap_cv);
right_event = this->_push_event(right_end, Base_event::DEFAULT, ARR_INTERIOR, ARR_INTERIOR).first;
}
if (!c1->is_start_point(left_event))
{
// here we do not add a curve on the left if there wasn't a curve before
// it might happen that a curve will be added on the left while
// it should have been an overlapping curve (that will be detected
// upon handling of an event with no left curve).
// See for example data/test_construction/segments/test51.txt
if (!c2->is_start_point(left_event) || left_event->has_left_curves())
left_event->add_curve_to_left(c1);
}
else
left_event->remove_curve_from_right(c1);
if (!c2->is_start_point(left_event))
{
// same reason than just above
if (!c1->is_start_point(left_event) || left_event->has_left_curves())
left_event->add_curve_to_left(c2);
}
else
left_event->remove_curve_from_right(c2);
// Allocate the new Subcurve for the overlap
Subcurve* overlap_sc=NULL;
if (all_leaves_diff.empty())
{
// first check that an equivalent curve is not already in left_event
for (Subcurve_iterator iter = left_event->right_curves_begin(); iter != left_event->right_curves_end();
++iter)
{
if ( (*iter)->has_same_leaves(c1, c2) )
{
CGAL_SL_PRINT_TEXT("Reuse overlapping curve ");
CGAL_SL_PRINT_CURVE(*iter);
CGAL_SL_PRINT_EOL();
overlap_sc=*iter;
break;
}
}
// Alocate a new Subcure for the overlap
Subcurve* overlap_sc = this->m_subCurveAlloc.allocate(1);
if (overlap_sc==NULL)
{
CGAL_SL_PRINT_TEXT("Allocate a new subcurve for the overlap (no common subcurves)");
CGAL_SL_PRINT_EOL();
// no duplicate only one curve is needed
overlap_sc = this->m_subCurveAlloc.allocate(1);
this->m_subCurveAlloc.construct(overlap_sc, this->m_masterSubcurve);
overlap_sc->set_hint(this->m_statusLine.end());
overlap_sc->init(overlap_cv);
overlap_sc->set_left_event(event);
overlap_sc->set_right_event(right_end);
overlap_sc->set_left_event(left_event);
overlap_sc->set_right_event(right_event);
m_overlap_subCurves.push_back(overlap_sc);
// Set the two events' attribute to overlap.
event->set_overlap();
//right_end->set_overlap();
// sets the two originating subcurves of overlap_sc
overlap_sc->set_originating_subcurve1(*iter);
overlap_sc->set_originating_subcurve2(curve);
overlap_sc->set_originating_subcurve1(c1);
overlap_sc->set_originating_subcurve2(c2);
}
}
else{
CGAL_SL_PRINT_TEXT("Allocate new subcurves for the overlap (common subcurves)");
CGAL_SL_PRINT_EOL();
CGAL_SL_PRINT_CURVE(curve);
// create an overlapping curve per subcurve in second_parent that is not in first_parent
for (typename std::vector<Subcurve*>::const_iterator sc_it=all_leaves_diff.begin();
sc_it!=all_leaves_diff.end();
++sc_it)
{
overlap_sc = this->m_subCurveAlloc.allocate(1);
this->m_subCurveAlloc.construct(overlap_sc, this->m_masterSubcurve);
overlap_sc->set_hint(this->m_statusLine.end());
overlap_sc->init(overlap_cv);
overlap_sc->set_left_event(left_event);
overlap_sc->set_right_event(right_event);
m_overlap_subCurves.push_back(overlap_sc);
// sets the two originating subcurves of overlap_sc
overlap_sc->set_originating_subcurve1(first_parent);
overlap_sc->set_originating_subcurve2(*sc_it);
first_parent=overlap_sc;
}
}
left_event->set_overlap();
CGAL_SL_PRINT_CURVE(c1);
CGAL_SL_PRINT_TEXT(" + ");
CGAL_SL_PRINT_CURVE(*iter);
CGAL_SL_PRINT_CURVE(c2);
CGAL_SL_PRINT_TEXT(" => ");
CGAL_SL_PRINT_EOL();
CGAL_SL_PRINT_TEXT(" ");
CGAL_SL_PRINT_CURVE(overlap_sc);
CGAL_SL_PRINT_EOL();
// Remove curve, *iter from the left curves of end_overlap event
right_end->remove_curve_from_left(curve);
right_end->remove_curve_from_left(*iter);
// Remove curves from the left curves of the right end
// and add them on the right otherwise
if (c1->is_end_point(right_event))
right_event->remove_curve_from_left(c1);
else
_add_curve_to_right(right_event, c1);
// Add overlap_sc to the left curves
right_end->add_curve_to_left(overlap_sc);
if (c2->is_end_point(right_event))
right_event->remove_curve_from_left(c2);
else
_add_curve_to_right(right_event, c2);
// If one of the originating subcurves (or both), does not end
// at the right end of the overlap, add them to the right subcurves
// of the event associated with the right end of the overlap.
if ((Event*)curve->right_event() != right_end)
_add_curve_to_right(right_end, curve);
// add the overlapping curve of the right of the left end
_add_curve_to_right(left_event, overlap_sc);
right_event->add_curve_to_left(overlap_sc);
if ((Event*)(*iter)->right_event() != right_end)
_add_curve_to_right(right_end, (*iter));
this->m_visitor->found_overlap(c1, c2, overlap_sc);
this->m_visitor->found_overlap(curve, *iter, overlap_sc);
if (!c1->is_end_point(right_event) && !c2->is_end_point(right_event))
if (right_event->is_right_curve_bigger(c1, c2, this->m_traits))
std::swap(c1, c2);
// Replace current sub-curve (*iter) with the new sub-curve
(*iter) = overlap_sc;
CGAL_SL_PRINT_END_EOL("handling overlap");
if (event_on_overlap != NULL && event_on_overlap!=left_event)
{
// first check that event_on_overlap is in that overlapping curve as it
// can be on another overlapping part of the generating curves
if ( this->m_queueEventLess(event_on_overlap, left_event) == LARGER &&
this->m_queueEventLess(right_event, event_on_overlap) == LARGER )
{
CGAL_SL_PRINT_TEXT("An overlapping curve starts before the event inducing its creation");
CGAL_SL_PRINT_EOL();
// an overlapping curve is involved in an intersection
_add_curve_to_right(event_on_overlap, overlap_sc);
event_on_overlap->add_curve_to_left(overlap_sc);
}
}
CGAL_SL_PRINT_END_EOL("creating an overlapping curve");
}
//-----------------------------------------------------------------------------

View File

@ -149,6 +149,8 @@ public:
//std::cout << "add_curve_to_left, curve: ";
//curve->Print();
bool curve_added = false;
std::vector<Subcurve_iterator> left_curves_to_remove;
for (iter = m_leftCurves.begin(); iter != m_leftCurves.end(); ++iter) {
//std::cout << "add_curve_to_left, iter: ";
//(*iter)->Print();
@ -159,15 +161,42 @@ public:
return;
}
// Replace the existing curve in case of overlap.
// EBEB 2011-10-27: Fixed to detect overlaps correctly
if ((curve != *iter) && (curve->has_common_leaf(*iter))) {
// Replace the existing curve in case of overlap, only if the set of ancesters
// of curve contains the set of ancesters of *iter
if (curve->has_common_leaf(*iter))
{
//std::cout << "add_curve_to_left, curve overlaps" << std::endl;
if ( curve->number_of_original_curves() > (*iter)->number_of_original_curves() )
{
if (curve->are_all_leaves_contained(*iter))
{
if (curve_added)
{
left_curves_to_remove.push_back(iter);
continue;
}
*iter = curve;
curve_added=true;
}
}
else{
if ((*iter)->are_all_leaves_contained(curve))
{
CGAL_assertion(!curve_added);
return;
}
}
}
}
for (typename std::vector<Subcurve_iterator>::iterator itit =
left_curves_to_remove.begin(); itit!=left_curves_to_remove.end(); ++itit)
{
m_leftCurves.erase(*itit);
}
if (curve_added) return;
// The curve does not exist - insert it to the container.
m_leftCurves.push_back(curve);
// std::cout << "add_curve_to_left, pushed back" << std::endl;
@ -179,6 +208,10 @@ public:
void push_back_curve_to_left(Subcurve* curve)
{ m_leftCurves.push_back(curve); }
/*! Add a subcurve to the container of right curves (without checks). */
void push_back_curve_to_right(Subcurve* curve)
{ m_rightCurves.push_back(curve); }
/*! Add a subcurve to the container of right curves. */
std::pair<bool, Subcurve_iterator>
add_curve_to_right(Subcurve* curve, const Traits_2* tr)
@ -237,13 +270,25 @@ public:
{
Subcurve_iterator iter;
for (iter = m_leftCurves.begin(); iter!= m_leftCurves.end(); ++iter) {
if (curve->has_common_leaf(*iter)) {
if (curve == *iter || curve->are_all_leaves_contained(*iter)) {
m_leftCurves.erase(iter);
return;
}
}
}
/*! Remove a curve from the set of right curves. */
void remove_curve_from_right(Subcurve* curve)
{
Subcurve_iterator iter;
for (iter = m_rightCurves.begin(); iter!= m_rightCurves.end(); ++iter) {
if (curve == *iter || curve->are_all_leaves_contained(*iter)) {
m_rightCurves.erase(iter);
return;
}
}
}
/*! Returns an iterator to the first curve to the left of the event. */
Subcurve_iterator left_curves_begin() { return (m_leftCurves.begin()); }
@ -408,22 +453,33 @@ public:
m_leftCurves.erase(left_iter, m_leftCurves.end());
}
bool is_right_curve_bigger(Subcurve* c1, Subcurve* c2)
bool is_right_curve_bigger(Subcurve* c1, Subcurve* c2, const Traits_2* tr)
{
bool found_c1=false, found_c2=false;
Subcurve_iterator iter;
for (iter = m_rightCurves.begin(); iter != m_rightCurves.end(); ++iter) {
if ((*iter == c1) ||
(static_cast<Subcurve*>((*iter)->originating_subcurve1()) == c1) ||
(static_cast<Subcurve*>((*iter)->originating_subcurve2()) == c1))
return false;
if ((*iter == c2) ||
(static_cast<Subcurve*>((*iter)->originating_subcurve1()) == c2) ||
(static_cast<Subcurve*>((*iter)->originating_subcurve2()) == c2))
if (!found_c1 && ( (*iter == c1) ||
(static_cast<Subcurve*>(*iter)->are_all_leaves_contained(c1))))
{
if (found_c2)
return true;
else
found_c1=true;
}
return true;
if (!found_c2 && ( (*iter == c2) ||
(static_cast<Subcurve*>(*iter)->are_all_leaves_contained(c2))))
{
if (found_c1)
return false;
else
found_c2=true;
}
}
CGAL_assertion(!found_c1 || !found_c2);
return tr->compare_y_at_x_right_2_object()
(c1->last_curve(), c2->last_curve(), m_point) == LARGER;
}
/*! Check if the two curves are negihbors to the left of the event. */

View File

@ -35,6 +35,7 @@
#include <CGAL/Sweep_line_2/Sweep_line_event.h>
#include <CGAL/Multiset.h>
#include <CGAL/assertions.h>
#include <set>
namespace CGAL {
@ -115,6 +116,11 @@ public:
/*! Set the last intersecing curve so far. */
void set_last_curve(const X_monotone_curve_2& cv) { m_lastCurve = cv; }
/*! Check if the given event is the matches the left-end event. */
template <typename SweepEvent>
bool is_start_point(const SweepEvent* event) const
{ return (m_left_event == (Event*)event); }
/*! Check if the given event is the matches the right-end event. */
template <typename SweepEvent>
bool is_end_point(const SweepEvent* event) const
@ -153,16 +159,16 @@ public:
{ m_orig_subcurve2 = orig_subcurve2; }
/*! Get all the leaf-nodes in the hierarchy of overlapping subcurves. */
template <typename OutputIterator>
template <typename Subcurve, typename OutputIterator>
OutputIterator all_leaves(OutputIterator oi)
{
if (m_orig_subcurve1 == NULL) {
*oi++ = this;
*oi++ = static_cast<Subcurve*>(this);
return oi;
}
oi = m_orig_subcurve1->all_leaves(oi);
oi = m_orig_subcurve2->all_leaves(oi);
oi = m_orig_subcurve1->template all_leaves<Subcurve>(oi);
oi = m_orig_subcurve2->template all_leaves<Subcurve>(oi);
return oi;
}
@ -182,14 +188,60 @@ public:
return (m_orig_subcurve1->is_leaf(s) || m_orig_subcurve2->is_leaf(s));
}
/*! Check if other is entirely contained in the hierarchy of subcurves of this*/
bool are_all_leaves_contained(Self* other)
{
std::set<Self*> leaves_of_this;
this->template all_leaves<Self>(std::inserter(leaves_of_this, leaves_of_this.begin()));
std::vector<Self*> leaves_of_other;
other->template all_leaves<Self>(std::back_inserter(leaves_of_other));
if (leaves_of_other.size() > leaves_of_this.size())
return false;
for (typename std::vector<Self*>::iterator it=leaves_of_other.begin();
it!=leaves_of_other.end();
++it)
{
if (leaves_of_this.count(*it)==0)
return false;
}
return true;
}
/*! Check if the two hierarchies contain the same leaf nodes. */
bool has_same_leaves(Self* s)
{
std::list<Self*> my_leaves;
std::list<Self*> other_leaves;
this->all_leaves(std::back_inserter(my_leaves));
s->all_leaves(std::back_inserter(other_leaves));
this->template all_leaves<Self>(std::back_inserter(my_leaves));
s->template all_leaves<Self>(std::back_inserter(other_leaves));
typename std::list<Self*>::iterator iter;
for (iter = my_leaves.begin(); iter != my_leaves.end(); ++iter) {
if (std::find(other_leaves.begin(), other_leaves.end(), *iter) ==
other_leaves.end())
return false;
}
for (iter = other_leaves.begin(); iter != other_leaves.end(); ++iter) {
if (std::find(my_leaves.begin(), my_leaves.end(), *iter) ==
my_leaves.end())
return false;
}
return true;
}
/*! Check if the two hierarchies (s1+s2 considered as an overlapping curve not already created) contain the same leaf nodes. */
bool has_same_leaves(Self* s1, Self* s2)
{
std::list<Self*> my_leaves;
std::list<Self*> other_leaves;
this->template all_leaves<Self>(std::back_inserter(my_leaves));
s1->template all_leaves<Self>(std::back_inserter(other_leaves));
s2->template all_leaves<Self>(std::back_inserter(other_leaves));
typename std::list<Self*>::iterator iter;
for (iter = my_leaves.begin(); iter != my_leaves.end(); ++iter) {
@ -213,8 +265,8 @@ public:
std::list<Self*> my_leaves;
std::list<Self*> other_leaves;
this->all_leaves(std::back_inserter(my_leaves));
s->all_leaves(std::back_inserter(other_leaves));
this->template all_leaves<Self>(std::back_inserter(my_leaves));
s->template all_leaves<Self>(std::back_inserter(other_leaves));
typename std::list<Self*>::iterator iter;
for (iter = my_leaves.begin(); iter != my_leaves.end(); ++iter) {
@ -254,6 +306,15 @@ public:
else return (depth2 + 1);
}
/*! Get the number of input curves contributing to the subcurve */
unsigned int number_of_original_curves() const
{
if (m_orig_subcurve1 == NULL) return 1;
unsigned int d1 = m_orig_subcurve1->number_of_original_curves();
unsigned int d2 = m_orig_subcurve2->number_of_original_curves();
return d1+d2;
}
#ifdef CGAL_SL_VERBOSE
void Print() const;
#endif
@ -266,7 +327,7 @@ public:
std::cout << "Curve " << this
<< " (" << m_lastCurve << ") "
<< " [sc1: " << m_orig_subcurve1
<< ", sc2: " << m_orig_subcurve2 << "]";
<< ", sc2: " << m_orig_subcurve2 << "]" << " " << number_of_original_curves() ;
}
#endif