diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Circle_segment_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Circle_segment_2.h index 3a863de2b8a..82b40648ecb 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Circle_segment_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Circle_segment_2.h @@ -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 diff --git a/Arrangement_on_surface_2/include/CGAL/Basic_sweep_line_2.h b/Arrangement_on_surface_2/include/CGAL/Basic_sweep_line_2.h index 113fc21c018..78ba4448ca3 100644 --- a/Arrangement_on_surface_2/include/CGAL/Basic_sweep_line_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Basic_sweep_line_2.h @@ -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); diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/Construction_test.h b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/Construction_test.h index b3334e9f8f2..b6958af15fa 100644 --- a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/Construction_test.h +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/Construction_test.h @@ -225,9 +225,19 @@ bool Construction_test::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::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(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(std::cout, "\n")); + std::cout << "Obtained: " << std::endl; + std::copy(points_res.begin(), points_res.end(), + std::ostream_iterator(std::cout, "\n")); return false; + } std::vector curves_res(m_arr->number_of_edges()); typename Xcurve_container::iterator xcit = curves_res.begin(); @@ -259,13 +276,23 @@ bool Construction_test::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(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(); diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/cgal_test.cmake b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/cgal_test.cmake index d5a1f31d677..3d1c81422e4 100644 --- a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/cgal_test.cmake +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/cgal_test.cmake @@ -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() diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/cgal_test_base b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/cgal_test_base index 7718ab59338..bab62c14217 100755 --- a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/cgal_test_base +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/cgal_test_base @@ -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 diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/spec.txt b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/spec.txt new file mode 100644 index 00000000000..aff1ae02e48 --- /dev/null +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/spec.txt @@ -0,0 +1 @@ +test06 covers the case "Overlap with common ancestors" diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test01.txt b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test01.txt new file mode 100644 index 00000000000..1ec5ed13060 --- /dev/null +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test01.txt @@ -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 diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test02.txt b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test02.txt new file mode 100644 index 00000000000..da8479558dd --- /dev/null +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test02.txt @@ -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 diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test03.txt b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test03.txt new file mode 100644 index 00000000000..de59d514e0e --- /dev/null +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test03.txt @@ -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 diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test04.txt b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test04.txt new file mode 100644 index 00000000000..dc0c3039d79 --- /dev/null +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test04.txt @@ -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 diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test05.txt b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test05.txt new file mode 100644 index 00000000000..79061951b3e --- /dev/null +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test05.txt @@ -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 diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test06.pdf b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test06.pdf new file mode 100644 index 00000000000..3489398982b Binary files /dev/null and b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test06.pdf differ diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test06.txt b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test06.txt new file mode 100644 index 00000000000..0a74c2b93bb --- /dev/null +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test06.txt @@ -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 diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test07.pdf b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test07.pdf new file mode 100644 index 00000000000..44b03fdbd18 Binary files /dev/null and b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test07.pdf differ diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test07.txt b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test07.txt new file mode 100644 index 00000000000..c0018179a55 --- /dev/null +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test07.txt @@ -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 diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test08.pdf b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test08.pdf new file mode 100644 index 00000000000..422d6ebf9bf Binary files /dev/null and b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test08.pdf differ diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test08.txt b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test08.txt new file mode 100644 index 00000000000..6d7152dc0d4 --- /dev/null +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test08.txt @@ -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 diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test09.pdf b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test09.pdf new file mode 100644 index 00000000000..61d89b83b6f Binary files /dev/null and b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test09.pdf differ diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test09.txt b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test09.txt new file mode 100644 index 00000000000..115af13d4e3 --- /dev/null +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test09.txt @@ -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 diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test10.txt b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test10.txt new file mode 100644 index 00000000000..50a3a1aa0dc --- /dev/null +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test10.txt @@ -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 diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/segments/test48.txt b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/segments/test48.txt new file mode 100644 index 00000000000..52ad6c8979a --- /dev/null +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/segments/test48.txt @@ -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 diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/segments/test49.txt b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/segments/test49.txt new file mode 100644 index 00000000000..fcfa42b50b5 --- /dev/null +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/segments/test49.txt @@ -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 diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/segments/test50.txt b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/segments/test50.txt new file mode 100644 index 00000000000..1114ce12da1 --- /dev/null +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/segments/test50.txt @@ -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 diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/segments/test51.txt b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/segments/test51.txt new file mode 100644 index 00000000000..d05b8f0fe0e --- /dev/null +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/segments/test51.txt @@ -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 diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_construction.polylines.cmd b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_construction.polylines.cmd new file mode 100644 index 00000000000..91908142c6d --- /dev/null +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_construction.polylines.cmd @@ -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 diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_construction.segments.cmd b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_construction.segments.cmd index 4e20bb65871..30d9155bc40 100644 --- a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_construction.segments.cmd +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_construction.segments.cmd @@ -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 diff --git a/Sweep_line_2/include/CGAL/Sweep_line_2.h b/Sweep_line_2/include/CGAL/Sweep_line_2.h index 3851e3e9f48..c3c56259d79 100644 --- a/Sweep_line_2/include/CGAL/Sweep_line_2.h +++ b/Sweep_line_2/include/CGAL/Sweep_line_2.h @@ -31,10 +31,13 @@ */ #include +#include + #include #include #include #include +#include namespace CGAL { @@ -155,6 +158,7 @@ public: virtual ~Sweep_line_2() {} protected: + typedef typename std::vector 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. diff --git a/Sweep_line_2/include/CGAL/Sweep_line_2/Arr_construction_sl_visitor.h b/Sweep_line_2/include/CGAL/Sweep_line_2/Arr_construction_sl_visitor.h index 1ddca02b8ea..e9eb3747e9d 100644 --- a/Sweep_line_2/include/CGAL/Sweep_line_2/Arr_construction_sl_visitor.h +++ b/Sweep_line_2/include/CGAL/Sweep_line_2/Arr_construction_sl_visitor.h @@ -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); } diff --git a/Sweep_line_2/include/CGAL/Sweep_line_2/Arr_insertion_traits_2.h b/Sweep_line_2/include/CGAL/Sweep_line_2/Arr_insertion_traits_2.h index 026351de989..bd8b5852e08 100644 --- a/Sweep_line_2/include/CGAL/Sweep_line_2/Arr_insertion_traits_2.h +++ b/Sweep_line_2/include/CGAL/Sweep_line_2/Arr_insertion_traits_2.h @@ -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. diff --git a/Sweep_line_2/include/CGAL/Sweep_line_2/Basic_sweep_line_2_impl.h b/Sweep_line_2/include/CGAL/Sweep_line_2/Basic_sweep_line_2_impl.h index f7aaa486147..42cfb32aa13 100644 --- a/Sweep_line_2/include/CGAL/Sweep_line_2/Basic_sweep_line_2_impl.h +++ b/Sweep_line_2/include/CGAL/Sweep_line_2/Basic_sweep_line_2_impl.h @@ -466,6 +466,7 @@ void Basic_sweep_line_2::_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::_handle_right_curves() template bool Basic_sweep_line_2:: -_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); diff --git a/Sweep_line_2/include/CGAL/Sweep_line_2/Sweep_line_2_impl.h b/Sweep_line_2/include/CGAL/Sweep_line_2/Sweep_line_2_impl.h index 5c74ff989b0..4c9bfdb01b4 100644 --- a/Sweep_line_2/include/CGAL/Sweep_line_2/Sweep_line_2_impl.h +++ b/Sweep_line_2/include/CGAL/Sweep_line_2/Sweep_line_2_impl.h @@ -96,12 +96,16 @@ void Sweep_line_2::_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(*(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::_handle_left_curves() // intersection. CGAL_assertion(this->m_currentEvent->is_action()); this->m_currentEvent->set_weak_intersection(); + this->m_visitor->update_event(this->m_currentEvent, sc); + + this->m_currentEvent->add_curve_to_left(sc); + 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); } - // Obtain the subcurve that contains the current event, and add it to - // the left curves incident to the event. - Subcurve* sc = static_cast(*(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; - } + // 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::_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::_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::_handle_right_curves() template bool Sweep_line_2:: -_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 list_of_sc; - curve->distinct_nodes(*iter, std::back_inserter(list_of_sc)); - - typename std::list::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(*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 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(curve), + static_cast(*(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 void Sweep_line_2::_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::_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(m_curves_pair_set.size()) / m_curves_pair_set.bucket_count(); @@ -440,8 +442,112 @@ void Sweep_line_2::_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(std::back_inserter(all_leaves_first)); + second_parent->template all_leaves(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 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::_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::_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 >(&(*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::_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 >(&(*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::_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 :: _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::_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::_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 void Sweep_line_2:: -_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 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(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& 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); + 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{ + 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; + } - 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; - } - } + // 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 { - // 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 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; } - // Alocate a new Subcure for the overlap - Subcurve* 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); - m_overlap_subCurves.push_back(overlap_sc); + 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); - // Set the two events' attribute to overlap. - event->set_overlap(); - //right_end->set_overlap(); + // 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; + } + } - // sets the two originating subcurves of overlap_sc - overlap_sc->set_originating_subcurve1(*iter); - overlap_sc->set_originating_subcurve2(curve); + 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(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(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::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"); } //----------------------------------------------------------------------------- diff --git a/Sweep_line_2/include/CGAL/Sweep_line_2/Sweep_line_event.h b/Sweep_line_2/include/CGAL/Sweep_line_2/Sweep_line_event.h index af93827abf7..062e65c59e4 100644 --- a/Sweep_line_2/include/CGAL/Sweep_line_2/Sweep_line_event.h +++ b/Sweep_line_2/include/CGAL/Sweep_line_2/Sweep_line_event.h @@ -149,6 +149,8 @@ public: //std::cout << "add_curve_to_left, curve: "; //curve->Print(); + bool curve_added = false; + std::vector 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; - *iter = curve; - return; + 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::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 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((*iter)->originating_subcurve1()) == c1) || - (static_cast((*iter)->originating_subcurve2()) == c1)) - return false; + if (!found_c1 && ( (*iter == c1) || + (static_cast(*iter)->are_all_leaves_contained(c1)))) + { + if (found_c2) + return true; + else + found_c1=true; + } - if ((*iter == c2) || - (static_cast((*iter)->originating_subcurve1()) == c2) || - (static_cast((*iter)->originating_subcurve2()) == c2)) - return true; + if (!found_c2 && ( (*iter == c2) || + (static_cast(*iter)->are_all_leaves_contained(c2)))) + { + if (found_c1) + return false; + else + found_c2=true; + } } + CGAL_assertion(!found_c1 || !found_c2); - return true; + 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. */ diff --git a/Sweep_line_2/include/CGAL/Sweep_line_2/Sweep_line_subcurve.h b/Sweep_line_2/include/CGAL/Sweep_line_2/Sweep_line_subcurve.h index 35773693885..387d5a83b3f 100644 --- a/Sweep_line_2/include/CGAL/Sweep_line_2/Sweep_line_subcurve.h +++ b/Sweep_line_2/include/CGAL/Sweep_line_2/Sweep_line_subcurve.h @@ -35,6 +35,7 @@ #include #include #include +#include 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 + 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 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 + template OutputIterator all_leaves(OutputIterator oi) { if (m_orig_subcurve1 == NULL) { - *oi++ = this; + *oi++ = static_cast(this); return oi; } - oi = m_orig_subcurve1->all_leaves(oi); - oi = m_orig_subcurve2->all_leaves(oi); + oi = m_orig_subcurve1->template all_leaves(oi); + oi = m_orig_subcurve2->template all_leaves(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 leaves_of_this; + this->template all_leaves(std::inserter(leaves_of_this, leaves_of_this.begin())); + std::vector leaves_of_other; + other->template all_leaves(std::back_inserter(leaves_of_other)); + if (leaves_of_other.size() > leaves_of_this.size()) + return false; + for (typename std::vector::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 my_leaves; std::list other_leaves; - this->all_leaves(std::back_inserter(my_leaves)); - s->all_leaves(std::back_inserter(other_leaves)); + this->template all_leaves(std::back_inserter(my_leaves)); + s->template all_leaves(std::back_inserter(other_leaves)); + + typename std::list::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 my_leaves; + std::list other_leaves; + + this->template all_leaves(std::back_inserter(my_leaves)); + s1->template all_leaves(std::back_inserter(other_leaves)); + s2->template all_leaves(std::back_inserter(other_leaves)); typename std::list::iterator iter; for (iter = my_leaves.begin(); iter != my_leaves.end(); ++iter) { @@ -213,8 +265,8 @@ public: std::list my_leaves; std::list other_leaves; - this->all_leaves(std::back_inserter(my_leaves)); - s->all_leaves(std::back_inserter(other_leaves)); + this->template all_leaves(std::back_inserter(my_leaves)); + s->template all_leaves(std::back_inserter(other_leaves)); typename std::list::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