From a20eb3c7485e6170734d4dc638baee75e03efd91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 7 Jun 2017 11:14:34 +0200 Subject: [PATCH 01/44] add debug function to get the number of curves overlapping on a subcurve --- .../include/CGAL/Sweep_line_2/Sweep_line_subcurve.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) 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 dd31aa4636e..063b033663c 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 @@ -250,6 +250,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 @@ -262,7 +271,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 From 782b6310da1f5c91d2244aa9efd64ddeebfd99ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 8 Jun 2017 20:49:29 +0200 Subject: [PATCH 02/44] compute all overlap curves in _intersect and handle them in _add_curve_to_right --- Sweep_line_2/include/CGAL/Sweep_line_2.h | 20 +- .../Sweep_line_2/Basic_sweep_line_2_impl.h | 1 + .../CGAL/Sweep_line_2/Sweep_line_2_impl.h | 315 ++++++------------ .../CGAL/Sweep_line_2/Sweep_line_event.h | 4 + .../CGAL/Sweep_line_2/Sweep_line_subcurve.h | 5 + 5 files changed, 117 insertions(+), 228 deletions(-) diff --git a/Sweep_line_2/include/CGAL/Sweep_line_2.h b/Sweep_line_2/include/CGAL/Sweep_line_2.h index 2408d387768..c7f0c74c784 100644 --- a/Sweep_line_2/include/CGAL/Sweep_line_2.h +++ b/Sweep_line_2/include/CGAL/Sweep_line_2.h @@ -167,22 +167,18 @@ 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. */ - 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); /*! Compute intersections between the two given curves. * If the two curves intersect, create a new event (or use the event that @@ -207,13 +203,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/Basic_sweep_line_2_impl.h b/Sweep_line_2/include/CGAL/Sweep_line_2/Basic_sweep_line_2_impl.h index 7e9b92520f2..ad6b41c1809 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 @@ -462,6 +462,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 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 460316a29f8..8725e272e2f 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 @@ -98,6 +98,10 @@ void Sweep_line_2::_handle_left_curves() 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()) { @@ -113,37 +117,21 @@ 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 + _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. @@ -286,7 +274,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)); @@ -300,7 +288,7 @@ _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)->is_inner_node(curve)) { CGAL_SL_PRINT_END_EOL("adding a Curve to the right (curve exists)"); return false; } @@ -312,19 +300,7 @@ _add_curve_to_right(Event* event, Subcurve* curve, bool overlap_exist) 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; - } + CGAL_assertion(!(curve)->has_same_leaves(*iter)); if ((curve)->has_common_leaf(*iter)) { /*! Collect all the distinct nodes of curves including the common nodes. @@ -336,7 +312,12 @@ _add_curve_to_right(Event* event, Subcurve* curve, bool overlap_exist) std::list list_of_sc; curve->distinct_nodes(*iter, std::back_inserter(list_of_sc)); - typename std::list::iterator sc_iter; +//SL_SAYS +// the pb here is that the curve that will be put on the right of the right end of the overlapping curve +// will be the filtered curves and not the overlap that is actually on the right. Two solutions: I manage +// to pass curve or I pass all the curves of the overlap to the right of the end of the new overlap + + 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)); @@ -353,7 +334,9 @@ _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))); // Inidicate that an overlap has occured: CGAL_SL_PRINT_END_EOL("adding a Curve to the right (overlap)"); @@ -428,7 +411,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("end 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(); @@ -534,28 +520,28 @@ void Sweep_line_2::_intersect(Subcurve* c1, const std::pair* xp_point; - // Efi: why not skipping in a loop?check only one (that is, why not in a loop)? - if (vi != vi_end) { - xp_point = object_cast >(&(*vi)); - if (xp_point != NULL) { - // Skip the intersection point if it is not larger than the current - // event. - if (this->m_queueEventLess(xp_point->first, this->m_currentEvent) != - LARGER) - { - ++vi; - } - } - } +// SL_SAYS : replace with assertions + //~ // Efi: why not skipping in a loop?check only one (that is, why not in a loop)? + //~ if (vi != vi_end) { + //~ xp_point = object_cast >(&(*vi)); + //~ if (xp_point != NULL) { + //~ // Skip the intersection point if it is not larger than the current + //~ // event. + //~ if (this->m_queueEventLess(xp_point->first, this->m_currentEvent) != + //~ LARGER) + //~ { + //~ ++vi; + //~ } + //~ } + //~ } 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(); @@ -566,14 +552,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); } } @@ -588,10 +567,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); @@ -603,7 +581,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); @@ -619,11 +597,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)) std::swap(c1, c2); } else { if ((multiplicity % 2) == 1) { @@ -646,42 +622,36 @@ _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); } 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); - } + 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"); } //----------------------------------------------------------------------------- @@ -724,154 +694,69 @@ void Sweep_line_2::_fix_overlap_subcurves() * \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) { // 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); + // TODO EBEB: This code does not work with overlaps that reach the boundary + Point_2 left_end = this->m_traits->construct_min_vertex_2_object()(overlap_cv); + Point_2 right_end = this->m_traits->construct_max_vertex_2_object()(overlap_cv); + + Event* left_event = + this->_push_event(left_end, Base_event::DEFAULT, ARR_INTERIOR, ARR_INTERIOR).first; + Event* right_event = + this->_push_event(right_end, Base_event::DEFAULT, ARR_INTERIOR, ARR_INTERIOR).first; - 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). - 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; - } - } - } - 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; - } - } - - // Alocate a new Subcure for the overlap + if (!c1->is_start_point(left_event)) + left_event->add_curve_to_left(c1); + if (!c2->is_start_point(left_event)) + left_event->add_curve_to_left(c2); + + // Allocate a new Subcurve 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); + 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(); - + left_event->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); - CGAL_SL_PRINT_CURVE(curve); + 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); + if (c2->is_end_point(right_event)) + right_event->remove_curve_from_left(c2); + else + _add_curve_to_right(right_event, c2); - // Add overlap_sc to the left curves - right_end->add_curve_to_left(overlap_sc); + // add the overlapping curve of the right of the left end + _add_curve_to_right(left_event, overlap_sc); + right_event->push_back_curve_to_left(overlap_sc); - // 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); + this->m_visitor->found_overlap(c1, c2, overlap_sc); - if ((Event*)(*iter)->right_event() != right_end) - _add_curve_to_right(right_end, (*iter)); - - this->m_visitor->found_overlap(curve, *iter, overlap_sc); - - // Replace current sub-curve (*iter) with the new sub-curve - (*iter) = overlap_sc; - - CGAL_SL_PRINT_END_EOL("handling overlap"); + 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 eaaa1fbc085..29f85872731 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 @@ -175,6 +175,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) 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 063b033663c..a5c66512f3d 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 @@ -111,6 +111,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 From d1e257f7cfa6d6240db5f7bae65fa16f64439236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 9 Jun 2017 07:26:54 +0200 Subject: [PATCH 03/44] small fix --- Arrangement_on_surface_2/include/CGAL/Basic_sweep_line_2.h | 3 +-- .../include/CGAL/Sweep_line_2/Basic_sweep_line_2_impl.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) 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 e3653b882f7..b2ca01b8a25 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 @@ -446,8 +446,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/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 ad6b41c1809..0cc93082487 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 @@ -556,7 +556,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); From 7800ac5e4d6071899060b4364114443208cf5a7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 12 Jun 2017 15:57:20 +0200 Subject: [PATCH 04/44] fix the order of the right curves after an overlap + add todo about how to create overlapping curves having common input curves --- Sweep_line_2/include/CGAL/Sweep_line_2.h | 2 +- .../CGAL/Sweep_line_2/Sweep_line_2_impl.h | 89 ++++++++++++------- .../CGAL/Sweep_line_2/Sweep_line_subcurve.h | 6 ++ 3 files changed, 62 insertions(+), 35 deletions(-) diff --git a/Sweep_line_2/include/CGAL/Sweep_line_2.h b/Sweep_line_2/include/CGAL/Sweep_line_2.h index c7f0c74c784..04e373a5471 100644 --- a/Sweep_line_2/include/CGAL/Sweep_line_2.h +++ b/Sweep_line_2/include/CGAL/Sweep_line_2.h @@ -178,7 +178,7 @@ protected: * \param c1 first subcurve contributing to the overlap. * \param c2 second subcurve contributing to the overlap. */ - void _create_overlapping_curve(const X_monotone_curve_2& overlap_cv, Subcurve* c1 , Subcurve* c2); + void _create_overlapping_curve(const X_monotone_curve_2& overlap_cv, Subcurve*& c1 , Subcurve*& c2); /*! Compute intersections between the two given curves. * If the two curves intersect, create a new event (or use the event that 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 8725e272e2f..c59bbbf82ed 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 @@ -123,7 +123,13 @@ void Sweep_line_2::_handle_left_curves() this->m_currentEvent->push_back_curve_to_right(sc); } else - _add_curve_to_right(this->m_currentEvent, sc); + { + if (!_add_curve_to_right(this->m_currentEvent, sc)) + { + // no overlap + this->m_currentEvent->push_back_curve_to_left(sc); + } + } // sc is now on the left CGAL_SL_PRINT_TEXT("Event after update:"); @@ -300,30 +306,30 @@ _add_curve_to_right(Event* event, Subcurve* curve) return false; } - CGAL_assertion(!(curve)->has_same_leaves(*iter)); + CGAL_assertion(!(curve)->has_same_leaves(*iter)); // SL_SAYS I'm not 100% sure this precondition is valid - 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)); + //~ 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)); //SL_SAYS // the pb here is that the curve that will be put on the right of the right end of the overlapping curve // will be the filtered curves and not the overlap that is actually on the right. Two solutions: I manage // to pass curve or I pass all the curves of the overlap to the right of the end of the new overlap - 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)); + //~ 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_SL_PRINT_END_EOL("adding a Curve to the right (common leaf)"); + //~ return true; + //~ } } std::pair pair_res = event->add_curve_to_right(curve, this->m_traits); @@ -338,7 +344,7 @@ _add_curve_to_right(Event* event, Subcurve* curve) _intersect(static_cast(curve), static_cast(*(pair_res.second))); - // 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; } @@ -521,19 +527,19 @@ void Sweep_line_2::_intersect(Subcurve* c1, const std::pair* xp_point; // SL_SAYS : replace with assertions - //~ // Efi: why not skipping in a loop?check only one (that is, why not in a loop)? - //~ if (vi != vi_end) { - //~ xp_point = object_cast >(&(*vi)); - //~ if (xp_point != NULL) { - //~ // Skip the intersection point if it is not larger than the current - //~ // event. - //~ if (this->m_queueEventLess(xp_point->first, this->m_currentEvent) != - //~ LARGER) - //~ { - //~ ++vi; - //~ } - //~ } - //~ } + // Efi: why not skipping in a loop?check only one (that is, why not in a loop)? + if (vi != vi_end) { + xp_point = object_cast >(&(*vi)); + if (xp_point != NULL) { + // Skip the intersection point if it is not larger than the current + // event. + if (this->m_queueEventLess(xp_point->first, this->m_currentEvent) != + LARGER) + { + ++vi; + } + } + } for (; vi != vi_end; ++vi) { const X_monotone_curve_2* icv; @@ -698,7 +704,7 @@ void Sweep_line_2::_fix_overlap_subcurves() template void Sweep_line_2:: -_create_overlapping_curve(const X_monotone_curve_2& overlap_cv, Subcurve* c1 , Subcurve* c2) +_create_overlapping_curve(const X_monotone_curve_2& overlap_cv, Subcurve*& c1 , Subcurve*& c2) { // An overlap occurs: CGAL_SL_PRINT_START_EOL("creating an overlapping curve"); @@ -729,6 +735,8 @@ _create_overlapping_curve(const X_monotone_curve_2& overlap_cv, Subcurve* c1 , S // sets the two originating subcurves of overlap_sc overlap_sc->set_originating_subcurve1(c1); overlap_sc->set_originating_subcurve2(c2); + // la courbe overlap peut contenir des duplicates... il faudrait appeler la fonction du dessous + //~ overlap_sc->set_originating_subcurves(c1, c2, right_event); CGAL_SL_PRINT_CURVE(c1); CGAL_SL_PRINT_TEXT(" + "); @@ -745,6 +753,7 @@ _create_overlapping_curve(const X_monotone_curve_2& overlap_cv, Subcurve* c1 , S right_event->remove_curve_from_left(c1); else _add_curve_to_right(right_event, c1); + if (c2->is_end_point(right_event)) right_event->remove_curve_from_left(c2); else @@ -752,10 +761,14 @@ _create_overlapping_curve(const X_monotone_curve_2& overlap_cv, Subcurve* c1 , S // add the overlapping curve of the right of the left end _add_curve_to_right(left_event, overlap_sc); - right_event->push_back_curve_to_left(overlap_sc); + right_event->add_curve_to_left(overlap_sc); this->m_visitor->found_overlap(c1, c2, overlap_sc); + if (!c1->is_end_point(right_event) && !c2->is_end_point(right_event)) + if (right_event->is_right_curve_bigger(c1, c2)) + std::swap(c1, c2); + CGAL_SL_PRINT_END_EOL("creating an overlapping curve"); } @@ -776,7 +789,15 @@ _fix_finished_overlap_subcurve(Subcurve* sc) CGAL_assertion(sc != NULL); // split 'sc' if necessary and update to event as weak intersection - if ((Event*)sc->right_event() != this->m_currentEvent) { + if ((Event*)sc->right_event() != this->m_currentEvent + + && //SL_SAYS this is a temporary condition while set_originating_subcurves is not implemented + //(because a curve could be tried to be split several times) + !this->m_traits->equal_2_object()( + this->m_traits->construct_min_vertex_2_object()(sc->last_curve()), + this->m_currentEvent->point()) + + ) { this->m_traits->split_2_object()(sc->last_curve(), this->m_currentEvent->point(), sub_cv1, sub_cv2); 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 a5c66512f3d..79c22939259 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 @@ -263,6 +263,12 @@ public: unsigned int d2 = m_orig_subcurve2->number_of_original_curves(); return d1+d2; } + + //~ void set_originating_subcurves(Subcurve* c1, Subcurve* c2, Event* right_event) + //~ { + + //~ } + #ifdef CGAL_SL_VERBOSE void Print() const; From 627b88fc31d152dff5c80fd7c50a6d0cfed57a05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 16 Jun 2017 16:40:20 +0200 Subject: [PATCH 05/44] generate overlapping curves without duplicates --- .../CGAL/Sweep_line_2/Sweep_line_2_impl.h | 87 ++++++++++++++++--- .../CGAL/Sweep_line_2/Sweep_line_event.h | 12 +++ .../CGAL/Sweep_line_2/Sweep_line_subcurve.h | 22 ++--- 3 files changed, 94 insertions(+), 27 deletions(-) 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 c59bbbf82ed..b7e72ecc916 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 @@ -722,21 +722,82 @@ _create_overlapping_curve(const X_monotone_curve_2& overlap_cv, Subcurve*& c1 , left_event->add_curve_to_left(c1); if (!c2->is_start_point(left_event)) left_event->add_curve_to_left(c2); + if (c1->is_start_point(left_event)) + left_event->remove_curve_from_right(c1); + if (c2->is_start_point(left_event)) + left_event->remove_curve_from_right(c2); - // Allocate a new Subcurve 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(left_event); - overlap_sc->set_right_event(right_event); - m_overlap_subCurves.push_back(overlap_sc); + // Allocate the new Subcurve for the overlap + Subcurve* first_parent = c1; + Subcurve* second_parent = c2; + + std::vector all_leaves_first; + std::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); + } + + std::vector all_leaves_diff; + if (!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)); + } + + Subcurve* overlap_sc; + if (all_leaves_second.size()==all_leaves_diff.size()) + { + 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{ + if (all_leaves_diff.empty()) + { + CGAL_SL_PRINT_TEXT("One overlapping curve entirely contains the other one"); + CGAL_SL_PRINT_EOL(); + overlap_sc=first_parent; + } + else + { + // create an overlapping curve per subcurve in second_parent that is not in first_parent + for (typename std::vector::iterator sc_it=all_leaves_diff.begin(); + sc_it!=all_leaves_diff.end(); + ++sc_it) + { + overlap_sc = this->m_subCurveAlloc.allocate(1); // \todo allocate all at once? + 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(); - // sets the two originating subcurves of overlap_sc - overlap_sc->set_originating_subcurve1(c1); - overlap_sc->set_originating_subcurve2(c2); - // la courbe overlap peut contenir des duplicates... il faudrait appeler la fonction du dessous - //~ overlap_sc->set_originating_subcurves(c1, c2, right_event); CGAL_SL_PRINT_CURVE(c1); CGAL_SL_PRINT_TEXT(" + "); 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 29f85872731..3a61775a448 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 @@ -244,6 +244,18 @@ public: } } + /*! 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->has_common_leaf(*iter)) { + m_leftCurves.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()); } 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 79c22939259..b4882505654 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 @@ -154,16 +154,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; } @@ -189,8 +189,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) { @@ -214,8 +214,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) { @@ -263,12 +263,6 @@ public: unsigned int d2 = m_orig_subcurve2->number_of_original_curves(); return d1+d2; } - - //~ void set_originating_subcurves(Subcurve* c1, Subcurve* c2, Event* right_event) - //~ { - - //~ } - #ifdef CGAL_SL_VERBOSE void Print() const; From a4f91b1028a3fabd46aff036eeb1440280499a28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Sat, 17 Jun 2017 07:41:05 +0200 Subject: [PATCH 06/44] add missing visitor call + always add curve to left --- Sweep_line_2/include/CGAL/Sweep_line_2/Sweep_line_2_impl.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 b7e72ecc916..de0c92ef607 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 @@ -124,10 +124,12 @@ void Sweep_line_2::_handle_left_curves() } else { + this->m_currentEvent->push_back_curve_to_left(sc); + this->m_currentEvent->set_weak_intersection(); if (!_add_curve_to_right(this->m_currentEvent, sc)) { // no overlap - this->m_currentEvent->push_back_curve_to_left(sc); + this->m_visitor->update_event(this->m_currentEvent, sc); } } From a11f1da495753aaf6d632f2307b9d70069b0a413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 19 Jun 2017 11:40:21 +0200 Subject: [PATCH 07/44] remove commented code and temporary fix --- .../CGAL/Sweep_line_2/Sweep_line_2_impl.h | 36 ++----------------- 1 file changed, 2 insertions(+), 34 deletions(-) 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 de0c92ef607..3d450c010de 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 @@ -308,30 +308,7 @@ _add_curve_to_right(Event* event, Subcurve* curve) return false; } - CGAL_assertion(!(curve)->has_same_leaves(*iter)); // SL_SAYS I'm not 100% sure this precondition is valid - - //~ 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)); - -//SL_SAYS -// the pb here is that the curve that will be put on the right of the right end of the overlapping curve -// will be the filtered curves and not the overlap that is actually on the right. Two solutions: I manage -// to pass curve or I pass all the curves of the overlap to the right of the end of the new overlap - - //~ 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); @@ -528,7 +505,6 @@ void Sweep_line_2::_intersect(Subcurve* c1, const std::pair* xp_point; -// SL_SAYS : replace with assertions // Efi: why not skipping in a loop?check only one (that is, why not in a loop)? if (vi != vi_end) { xp_point = object_cast >(&(*vi)); @@ -852,15 +828,7 @@ _fix_finished_overlap_subcurve(Subcurve* sc) CGAL_assertion(sc != NULL); // split 'sc' if necessary and update to event as weak intersection - if ((Event*)sc->right_event() != this->m_currentEvent - - && //SL_SAYS this is a temporary condition while set_originating_subcurves is not implemented - //(because a curve could be tried to be split several times) - !this->m_traits->equal_2_object()( - this->m_traits->construct_min_vertex_2_object()(sc->last_curve()), - this->m_currentEvent->point()) - - ) { + if ((Event*)sc->right_event() != this->m_currentEvent) { this->m_traits->split_2_object()(sc->last_curve(), this->m_currentEvent->point(), sub_cv1, sub_cv2); From 9d3e77d8c6d0657532a33d24ec33546e689ef452 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 19 Jun 2017 11:40:45 +0200 Subject: [PATCH 08/44] split last_curve of overlapping curves on the right of an event if not done This happens when the curve on the left and on the right are different (thus not split in _handle_left_curves()). This happens when there is an additional overlapping on the left and this overlapping was detected with overlapping curves having common ancesters --- .../CGAL/Sweep_line_2/Sweep_line_2_impl.h | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) 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 3d450c010de..9ce09c87d75 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 @@ -214,6 +214,33 @@ 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) + 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. From fa0bab49285930b6bddb6a7697174fa36975e37d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 20 Jun 2017 09:27:09 +0200 Subject: [PATCH 09/44] update the filtering mecanism of intersections for overlaps --- .../include/CGAL/Sweep_line_2/Arr_insertion_traits_2.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 e8b16b382a0..65ba5ba1f46 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 @@ -107,7 +107,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()) //SL_SAYS check with Efi { // The curves are interior-disjoint as both of them are already in // the arrangement. From c67cd489679f1abe11c29d9d7c88faaf0322ddaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 20 Jun 2017 17:21:45 +0200 Subject: [PATCH 10/44] add comment + debug info --- Sweep_line_2/include/CGAL/Sweep_line_2/Sweep_line_2_impl.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) 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 9ce09c87d75..324c207f24b 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 @@ -219,7 +219,8 @@ void Sweep_line_2::_handle_right_curves() // 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) + // (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) @@ -436,6 +437,7 @@ void Sweep_line_2::_intersect(Subcurve* c1, 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); @@ -783,6 +785,9 @@ _create_overlapping_curve(const X_monotone_curve_2& overlap_cv, Subcurve*& c1 , } else { + CGAL_SL_PRINT_TEXT("Allocate new subcurves for the overlap (common subcurves)"); + CGAL_SL_PRINT_EOL(); + // create an overlapping curve per subcurve in second_parent that is not in first_parent for (typename std::vector::iterator sc_it=all_leaves_diff.begin(); sc_it!=all_leaves_diff.end(); From e2d380d14fad24e8cfafaeb076a222d5117cd5a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 21 Jun 2017 15:22:34 +0200 Subject: [PATCH 11/44] call update event in all cases (overlap or not) --- .../include/CGAL/Sweep_line_2/Sweep_line_2_impl.h | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) 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 324c207f24b..db46f03aeef 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 @@ -126,11 +126,8 @@ void Sweep_line_2::_handle_left_curves() { this->m_currentEvent->push_back_curve_to_left(sc); this->m_currentEvent->set_weak_intersection(); - if (!_add_curve_to_right(this->m_currentEvent, sc)) - { - // no overlap - this->m_visitor->update_event(this->m_currentEvent, sc); - } + this->m_visitor->update_event(this->m_currentEvent, sc); + _add_curve_to_right(this->m_currentEvent, sc); } // sc is now on the left @@ -181,7 +178,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); @@ -425,7 +421,7 @@ void Sweep_line_2::_intersect(Subcurve* c1, Curve_pair cv_pair(c1,c2); if (! (m_curves_pair_set.insert(cv_pair)).second) { - CGAL_SL_PRINT_END_EOL("end computing intersection (already computed)"); + CGAL_SL_PRINT_END_EOL("computing intersection (already computed)"); return; //the curves have already been checked for intersection } From 757d698aa20c6511b6f99a9930823a25673c59dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 22 Jun 2017 14:35:18 +0200 Subject: [PATCH 12/44] really remove the curve from the right... copy-paste error --- Sweep_line_2/include/CGAL/Sweep_line_2/Sweep_line_event.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 3a61775a448..35eea401adc 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 @@ -250,7 +250,7 @@ public: Subcurve_iterator iter; for (iter = m_rightCurves.begin(); iter!= m_rightCurves.end(); ++iter) { if (curve->has_common_leaf(*iter)) { - m_leftCurves.erase(iter); + m_rightCurves.erase(iter); return; } } From 00bcb717d22357fb8584296d2555867966a09c56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 26 Jun 2017 15:08:56 +0200 Subject: [PATCH 13/44] fix detection of overlap on the boundary of the domain --- Sweep_line_2/include/CGAL/Sweep_line_2/Sweep_line_2_impl.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 db46f03aeef..e32ce9e3bb1 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 @@ -443,7 +443,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(), @@ -463,7 +463,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()))) { From f6412c786e2b0600f65dfbb72074d91ce4ceaffa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 26 Jun 2017 15:11:59 +0200 Subject: [PATCH 14/44] handle event on boundary when dealing with overlaps --- .../CGAL/Sweep_line_2/Sweep_line_2_impl.h | 37 +++++++++++++++---- 1 file changed, 30 insertions(+), 7 deletions(-) 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 e32ce9e3bb1..20f5afa4578 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 @@ -713,14 +713,37 @@ _create_overlapping_curve(const X_monotone_curve_2& overlap_cv, Subcurve*& c1 , // An overlap occurs: CGAL_SL_PRINT_START_EOL("creating an overlapping curve"); - // TODO EBEB: This code does not work with overlaps that reach the boundary - Point_2 left_end = this->m_traits->construct_min_vertex_2_object()(overlap_cv); - Point_2 right_end = this->m_traits->construct_max_vertex_2_object()(overlap_cv); + // 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)) { + // SL_SAYS check with Efi + 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; + } - Event* left_event = - this->_push_event(left_end, Base_event::DEFAULT, ARR_INTERIOR, ARR_INTERIOR).first; - Event* right_event = - this->_push_event(right_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)) { + // SL_SAYS check with Efi + 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)) left_event->add_curve_to_left(c1); From 4b7b5e5a9c6110e326c10880eec8c948df22db72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 23 Jun 2017 14:46:21 +0200 Subject: [PATCH 15/44] deal with overlapping curves with common ancesters before calling Intersec_2 Depending on the arrangement visitors and of the traits class used, it is assumed in some cases that X_monotone_curves are created without duplicates (for example some compute the multiplicity of overlap in Intersect_2 and store the info in X_monotone_curve). In Boolean Operations, Intersect_2 is overriden and two curves having a common ancester will never be detected as intersecting This is WIP, partial overlap is not yet handled fully correctly --- Sweep_line_2/include/CGAL/Sweep_line_2.h | 11 +- .../CGAL/Sweep_line_2/Sweep_line_2_impl.h | 184 +++++++++++------- 2 files changed, 129 insertions(+), 66 deletions(-) diff --git a/Sweep_line_2/include/CGAL/Sweep_line_2.h b/Sweep_line_2/include/CGAL/Sweep_line_2.h index 04e373a5471..9b8bb579475 100644 --- a/Sweep_line_2/include/CGAL/Sweep_line_2.h +++ b/Sweep_line_2/include/CGAL/Sweep_line_2.h @@ -177,8 +177,17 @@ protected: * \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 _create_overlapping_curve(const X_monotone_curve_2& overlap_cv, Subcurve*& c1 , Subcurve*& c2); + void _create_overlapping_curve(const X_monotone_curve_2& overlap_cv, + Subcurve*& c1 , Subcurve*& c2, + const std::vector& all_leaves_diff, + Subcurve* first_parent); /*! Compute intersections between the two given curves. * If the two curves intersect, create a new event (or use the event that 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 20f5afa4578..a6832fa1e32 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 @@ -431,6 +431,97 @@ 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 + std::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 extact 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; + + std::vector all_leaves_first; + std::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); // SL_SAYS check with Efi + + CGAL_SL_PRINT_END_EOL("computing intersection"); + return; + } + else{ + X_monotone_curve_2 xc = first_parent->last_curve(); + for (typename std::vector::iterator sc_it=all_leaves_diff.begin(); + sc_it!=all_leaves_diff.end(); ++sc_it) + { + std::vector inter_res; + vector_inserter vi(inter_res) ; + vector_inserter vi_end(inter_res); + + this->m_traits->intersect_2_object()(xc, (*sc_it)->last_curve(), vi); + CGAL_assertion(inter_res.empty() || inter_res.size()==1); //TMP for debug + CGAL_assertion( CGAL::object_cast< X_monotone_curve_2 >(&inter_res.front())!=NULL );// TMP for debug + xc = *CGAL::object_cast< X_monotone_curve_2 >(&inter_res.front()); + } + _create_overlapping_curve(xc, c1 , c2, all_leaves_diff, first_parent); + return; + } + } + + // do compute the intersection of the two curves vector_inserter vi(m_x_objects) ; vector_inserter vi_end(m_x_objects); @@ -562,7 +653,7 @@ void Sweep_line_2::_intersect(Subcurve* c1, CGAL_assertion(icv != NULL); CGAL_SL_PRINT_TEXT("Found an overlap"); CGAL_SL_PRINT_EOL(); - _create_overlapping_curve(*icv, c1 , c2); + _create_overlapping_curve(*icv, c1 , c2, all_leaves_diff, first_parent); } } @@ -698,17 +789,13 @@ 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' - */ template void Sweep_line_2:: -_create_overlapping_curve(const X_monotone_curve_2& overlap_cv, Subcurve*& c1 , Subcurve*& c2) +_create_overlapping_curve(const X_monotone_curve_2& overlap_cv, + Subcurve*& c1 , Subcurve*& c2, + const std::vector& all_leaves_diff, + Subcurve* first_parent) { // An overlap occurs: CGAL_SL_PRINT_START_EOL("creating an overlapping curve"); @@ -747,40 +834,16 @@ _create_overlapping_curve(const X_monotone_curve_2& overlap_cv, Subcurve*& c1 , if (!c1->is_start_point(left_event)) left_event->add_curve_to_left(c1); + else + left_event->remove_curve_from_right(c1); if (!c2->is_start_point(left_event)) left_event->add_curve_to_left(c2); - if (c1->is_start_point(left_event)) - left_event->remove_curve_from_right(c1); - if (c2->is_start_point(left_event)) + else left_event->remove_curve_from_right(c2); - + // Allocate the new Subcurve for the overlap - Subcurve* first_parent = c1; - Subcurve* second_parent = c2; - - std::vector all_leaves_first; - std::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); - } - - std::vector all_leaves_diff; - if (!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)); - } - Subcurve* overlap_sc; - if (all_leaves_second.size()==all_leaves_diff.size()) + if (all_leaves_diff.empty()) { CGAL_SL_PRINT_TEXT("Allocate a new subcurve for the overlap (no common subcurves)"); CGAL_SL_PRINT_EOL(); @@ -797,34 +860,25 @@ _create_overlapping_curve(const X_monotone_curve_2& overlap_cv, Subcurve*& c1 , overlap_sc->set_originating_subcurve2(c2); } else{ - if (all_leaves_diff.empty()) - { - CGAL_SL_PRINT_TEXT("One overlapping curve entirely contains the other one"); - CGAL_SL_PRINT_EOL(); - overlap_sc=first_parent; - } - else - { - CGAL_SL_PRINT_TEXT("Allocate new subcurves for the overlap (common subcurves)"); - CGAL_SL_PRINT_EOL(); + CGAL_SL_PRINT_TEXT("Allocate new subcurves for the overlap (common subcurves)"); + CGAL_SL_PRINT_EOL(); - // create an overlapping curve per subcurve in second_parent that is not in first_parent - for (typename std::vector::iterator sc_it=all_leaves_diff.begin(); - sc_it!=all_leaves_diff.end(); - ++sc_it) - { - overlap_sc = this->m_subCurveAlloc.allocate(1); // \todo allocate all at once? - 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; - } + // 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); // \todo allocate all at once? + 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(); From 68f76598fa8e8aed22be064e132b5d5af105f84f Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 25 Jan 2017 13:52:19 +0200 Subject: [PATCH 16/44] Added test cases for testing the construction of arrangements of segments (based on the finding of a user called vladaburian) --- .../test_construction/segments/test48.txt | 34 +++++++++++++++++++ .../test_construction/segments/test49.txt | 31 +++++++++++++++++ .../test_construction/segments/test50.txt | 34 +++++++++++++++++++ .../test_construction.segments.cmd | 3 ++ 4 files changed, 102 insertions(+) create mode 100644 Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/segments/test48.txt create mode 100644 Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/segments/test49.txt create mode 100644 Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/segments/test50.txt 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/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 From 126ed74256f339fa84652a723a382295411f1949 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 25 Jan 2017 13:55:24 +0200 Subject: [PATCH 17/44] Added test cases for testing the construction of arrangements of overlapping polylines --- .../Arrangement_on_surface_2/cgal_test_base | 13 +++++++++ .../test_construction/polylines/test01.txt | 25 +++++++++++++++++ .../test_construction/polylines/test02.txt | 27 +++++++++++++++++++ .../test_construction.polylines.cmd | 2 ++ 4 files changed, 67 insertions(+) create mode 100644 Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test01.txt create mode 100644 Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test02.txt create mode 100644 Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_construction.polylines.cmd 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 6d659f7bf1c..0957aa42d4d 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 #---------------------------------------------------------------------# @@ -1674,6 +1686,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/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/test_construction.polylines.cmd b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_construction.polylines.cmd new file mode 100644 index 00000000000..b5eed0dace4 --- /dev/null +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_construction.polylines.cmd @@ -0,0 +1,2 @@ +./data/test_construction/polylines/test01.txt +./data/test_construction/polylines/test02.txt From bf33219cf81405c3f8bddcf42acd859e66a4a2ad Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Mon, 30 Jan 2017 11:30:12 +0200 Subject: [PATCH 18/44] Enhanced messages when an error occurs --- .../Construction_test.h | 43 +++++++++++++++---- 1 file changed, 35 insertions(+), 8 deletions(-) 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..31b7c7c58d8 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 << "Obtained: " << std::endl; + std::copy(m_points.begin(), m_points.end(), + std::ostream_iterator(std::cout, "\n")); + std::cout << "Expected: " << 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 << "Obtained: " << 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 << "Expected: " << 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(); From c4a25fddfb280a78c5e8899494d0c75d4692708f Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Mon, 30 Jan 2017 11:30:45 +0200 Subject: [PATCH 19/44] Added a test case --- .../test_construction/polylines/test03.txt | 19 +++++++++++++++++++ .../test_construction.polylines.cmd | 1 + 2 files changed, 20 insertions(+) create mode 100644 Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test03.txt 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/test_construction.polylines.cmd b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_construction.polylines.cmd index b5eed0dace4..a826289decb 100644 --- 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 @@ -1,2 +1,3 @@ ./data/test_construction/polylines/test01.txt ./data/test_construction/polylines/test02.txt +./data/test_construction/polylines/test03.txt From 51a729a73c03f2d85cac90eda4d449a2f8870f3f Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Thu, 2 Feb 2017 11:34:35 +0200 Subject: [PATCH 20/44] Added test with overlaps --- .../data/test_construction/polylines/test04.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test04.txt 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 From 5bbbf2eb3a6baed77e344f6e8733feced217b388 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Sun, 5 Feb 2017 09:26:15 +0200 Subject: [PATCH 21/44] New tests --- .../test_construction/polylines/test05.txt | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test05.txt 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 From ec291f8502fec9d07240499120bbeba31afd5998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 26 Jun 2017 16:15:38 +0200 Subject: [PATCH 22/44] update cmake script to test polylines --- .../test/Arrangement_on_surface_2/cgal_test.cmake | 13 +++++++++++++ 1 file changed, 13 insertions(+) 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 9439aa934ce..16d3d2b1376 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 @@ -669,6 +669,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 #---------------------------------------------------------------------# @@ -1329,6 +1341,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() From 29ce8330aed2a252c9a8e0c432243258dba63688 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 26 Jun 2017 16:56:19 +0200 Subject: [PATCH 23/44] add all test cases --- .../Arrangement_on_surface_2/test_construction.polylines.cmd | 2 ++ 1 file changed, 2 insertions(+) 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 index a826289decb..7c0952457f3 100644 --- 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 @@ -1,3 +1,5 @@ ./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 From 55bb4d208c50540af96ab2bee999022f05ebd002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 27 Jun 2017 13:49:07 +0200 Subject: [PATCH 24/44] a curve no longer needs an event when it is no longer swept --- .../include/CGAL/Sweep_line_2/Arr_construction_sl_visitor.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 935c6bb9476..aecc86e3842 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 @@ -552,7 +552,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); } From 7fa251e3e8740584e087f9ffc80ac92c0839ba4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 28 Jun 2017 09:57:04 +0200 Subject: [PATCH 25/44] make debug output more robust in case of loss of precision --- .../include/CGAL/Arr_geometry_traits/Circle_segment_2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 eb5e4aa9885..ae61e1ae363 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 @@ -2440,7 +2440,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 From c31e8596a69d60834eb3baa4f9370737bcbf2477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 28 Jun 2017 10:15:42 +0200 Subject: [PATCH 26/44] add missing END of --- Sweep_line_2/include/CGAL/Sweep_line_2/Sweep_line_2_impl.h | 1 + 1 file changed, 1 insertion(+) 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 a6832fa1e32..0c1e98b526c 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 @@ -517,6 +517,7 @@ void Sweep_line_2::_intersect(Subcurve* c1, xc = *CGAL::object_cast< X_monotone_curve_2 >(&inter_res.front()); } _create_overlapping_curve(xc, c1 , c2, all_leaves_diff, first_parent); + CGAL_SL_PRINT_END_EOL("computing intersection (overlap with common ancesters)"); return; } } From b3435d28c4e57ba306357a097a77ffdbfd3e1cff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 28 Jun 2017 10:16:48 +0200 Subject: [PATCH 27/44] replace a curve on the left if the new one contains all ancesters of the old one --- .../CGAL/Sweep_line_2/Sweep_line_event.h | 16 +++++++++++---- .../CGAL/Sweep_line_2/Sweep_line_subcurve.h | 20 +++++++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) 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 35eea401adc..d0e6adc4ea6 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 @@ -155,11 +155,19 @@ 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 != *iter) && (curve->has_common_leaf(*iter))) + { //std::cout << "add_curve_to_left, curve overlaps" << std::endl; - *iter = curve; + if ( curve->number_of_original_curves() > (*iter)->number_of_original_curves() ) + { + CGAL_assertion( curve->are_all_leaves_contained(*iter) ); + *iter = curve; + } + else{ + CGAL_assertion( (*iter)->are_all_leaves_contained(curve) ); + } return; } } 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 b4882505654..ec1e233d192 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 @@ -183,6 +183,26 @@ 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) { From f07e0670561955a878abc52ab9caa3da38eb0b3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 7 Aug 2017 15:34:21 +0200 Subject: [PATCH 28/44] fix swapt expected/obtained --- .../test/Arrangement_on_surface_2/Construction_test.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 31b7c7c58d8..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 @@ -255,10 +255,10 @@ bool Construction_test::are_same_results() Point_equal point_eq(m_geom_traits); if (! std::equal(points_res.begin(), pit, m_points.begin(), point_eq)) { - std::cout << "Obtained: " << std::endl; + std::cout << "Expected: " << std::endl; std::copy(m_points.begin(), m_points.end(), std::ostream_iterator(std::cout, "\n")); - std::cout << "Expected: " << std::endl; + std::cout << "Obtained: " << std::endl; std::copy(points_res.begin(), points_res.end(), std::ostream_iterator(std::cout, "\n")); return false; @@ -283,11 +283,11 @@ bool Construction_test::are_same_results() Curve_equal curve_eq(m_geom_traits); if (! std::equal(curves_res.begin(), xcit, m_xcurves.begin(), curve_eq)) { - std::cout << "Obtained: " << std::endl; + 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 << "Expected: " << 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; From 973af4dc31116e80797ee3b1ab633f3b1218ce34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 9 Aug 2017 13:27:06 +0200 Subject: [PATCH 29/44] add missing include directive --- Sweep_line_2/include/CGAL/Sweep_line_2/Sweep_line_subcurve.h | 1 + 1 file changed, 1 insertion(+) 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 ec1e233d192..3efbb9b7be5 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 @@ -31,6 +31,7 @@ #include #include #include +#include namespace CGAL { From a8f5a4c19d1099581f14cc56ca85282fc9414c39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 9 Aug 2017 16:35:52 +0200 Subject: [PATCH 30/44] Mainly two changes: - make sure left of an event curves removed by the addition of an overlapping curve are by an overlapping curve that has them as a leaf. As a consequence we leave more curves on the left but several can be removed by the addition of one curve. Similarly for right curves of an event, the replacement of a curve on the right is done only when all subcurves are contained by an overlapping curve. - In case of overlapping of two curves detected when inserting one of the two curves on the right of an event, it might happen that the current event is not the left end point of the overlapping curve to be computed. In such a case, the new overlapping curve will not be added in the current event. The modification here pass the current event to the intersection function that will pass it to the overlap creation function so that the overlapping curve will also be added on the right and on the left of the current event. --- Sweep_line_2/include/CGAL/Sweep_line_2.h | 6 ++- .../CGAL/Sweep_line_2/Sweep_line_2_impl.h | 46 ++++++++++++++----- .../CGAL/Sweep_line_2/Sweep_line_event.h | 35 +++++++++++--- 3 files changed, 66 insertions(+), 21 deletions(-) diff --git a/Sweep_line_2/include/CGAL/Sweep_line_2.h b/Sweep_line_2/include/CGAL/Sweep_line_2.h index 9b8bb579475..b85dce1997c 100644 --- a/Sweep_line_2/include/CGAL/Sweep_line_2.h +++ b/Sweep_line_2/include/CGAL/Sweep_line_2.h @@ -31,6 +31,7 @@ #include #include #include +#include namespace CGAL { @@ -187,7 +188,8 @@ protected: void _create_overlapping_curve(const X_monotone_curve_2& overlap_cv, Subcurve*& c1 , Subcurve*& c2, const std::vector& all_leaves_diff, - Subcurve* first_parent); + 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 @@ -196,7 +198,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 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 0c1e98b526c..4597e14d19e 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 @@ -320,12 +320,12 @@ _add_curve_to_right(Event* event, Subcurve* curve) { CGAL_SL_PRINT_CURVE(*iter); CGAL_SL_PRINT_EOL(); - if ((*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)"); @@ -345,7 +345,12 @@ _add_curve_to_right(Event* event, Subcurve* curve) // a new overlap needs to be computed _intersect(static_cast(curve), - static_cast(*(pair_res.second))); + 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 that overlapping curve will be added to the right of + // `event` because of an adjacency in the status line. // Indicate that an overlap has occured: CGAL_SL_PRINT_END_EOL("adding a Curve to the right (overlap)"); @@ -405,7 +410,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); @@ -436,7 +442,7 @@ void Sweep_line_2::_intersect(Subcurve* c1, Subcurve* first_parent=NULL; if (c1->originating_subcurve1()!=NULL || c2->originating_subcurve2()!=NULL) { - // get the subcurve leaves of c1 and of c2. Then extact from the smallest set + // 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; @@ -512,11 +518,12 @@ void Sweep_line_2::_intersect(Subcurve* c1, vector_inserter vi_end(inter_res); this->m_traits->intersect_2_object()(xc, (*sc_it)->last_curve(), vi); - CGAL_assertion(inter_res.empty() || inter_res.size()==1); //TMP for debug - CGAL_assertion( CGAL::object_cast< X_monotone_curve_2 >(&inter_res.front())!=NULL );// TMP for debug + // SL_SAYS: we need to check that the following assertions are always valid + CGAL_assertion(inter_res.empty() || 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); + _create_overlapping_curve(xc, c1 , c2, all_leaves_diff, first_parent, event_for_overlap); CGAL_SL_PRINT_END_EOL("computing intersection (overlap with common ancesters)"); return; } @@ -654,7 +661,7 @@ void Sweep_line_2::_intersect(Subcurve* c1, CGAL_assertion(icv != NULL); CGAL_SL_PRINT_TEXT("Found an overlap"); CGAL_SL_PRINT_EOL(); - _create_overlapping_curve(*icv, c1 , c2, all_leaves_diff, first_parent); + _create_overlapping_curve(*icv, c1 , c2, all_leaves_diff, first_parent, event_for_overlap); } } @@ -769,7 +776,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; @@ -796,7 +803,8 @@ void Sweep_line_2:: _create_overlapping_curve(const X_monotone_curve_2& overlap_cv, Subcurve*& c1 , Subcurve*& c2, const std::vector& all_leaves_diff, - Subcurve* first_parent) + Subcurve* first_parent, + Event* event_on_overlap) { // An overlap occurs: CGAL_SL_PRINT_START_EOL("creating an overlapping curve"); @@ -869,7 +877,7 @@ _create_overlapping_curve(const X_monotone_curve_2& overlap_cv, sc_it!=all_leaves_diff.end(); ++sc_it) { - overlap_sc = this->m_subCurveAlloc.allocate(1); // \todo allocate all at once? + overlap_sc = this->m_subCurveAlloc.allocate(1); // SL_SAYS: allocate all at once? this->m_subCurveAlloc.construct(overlap_sc, this->m_masterSubcurve); overlap_sc->set_hint(this->m_statusLine.end()); overlap_sc->init(overlap_cv); @@ -915,6 +923,20 @@ _create_overlapping_curve(const X_monotone_curve_2& overlap_cv, if (right_event->is_right_curve_bigger(c1, c2)) std::swap(c1, c2); + 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 d0e6adc4ea6..fdaaa538665 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 @@ -145,6 +145,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(); @@ -157,21 +159,40 @@ public: // 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 != *iter) && (curve->has_common_leaf(*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() ) { - CGAL_assertion( curve->are_all_leaves_contained(*iter) ); - *iter = curve; + if (curve->are_all_leaves_contained(*iter)) + { + if (curve_added) + { + left_curves_to_remove.push_back(iter); + continue; + } + + *iter = curve; + curve_added=true; + } } else{ - CGAL_assertion( (*iter)->are_all_leaves_contained(curve) ); + if ((*iter)->are_all_leaves_contained(curve)) + { + CGAL_assertion(!curve_added); + return; + } } - 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; @@ -245,7 +266,7 @@ 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; } @@ -257,7 +278,7 @@ public: { Subcurve_iterator iter; for (iter = m_rightCurves.begin(); iter!= m_rightCurves.end(); ++iter) { - if (curve->has_common_leaf(*iter)) { + if (curve == *iter || curve->are_all_leaves_contained(*iter)) { m_rightCurves.erase(iter); return; } From 458ca21e3b8c24552c5f48fe9609aa6a5e3b91f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 10 Aug 2017 10:59:21 +0200 Subject: [PATCH 31/44] fix unused variable warning --- Sweep_line_2/include/CGAL/Sweep_line_2/Sweep_line_2_impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 4597e14d19e..3d3cca419ed 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 @@ -92,7 +92,7 @@ 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"); From 88f85cb438891595b349bc5c0a85b9591859e8e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 25 Aug 2017 16:42:32 +0200 Subject: [PATCH 32/44] handle case when the left curve of an event shouldn't be filled ... ... as it prevents from detecting it is on an overlapping curve --- .../test_construction/segments/test51.txt | 24 +++++++++++++++++++ .../CGAL/Sweep_line_2/Sweep_line_2_impl.h | 20 ++++++++++++---- 2 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/segments/test51.txt 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/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 3d3cca419ed..e7b33dd499e 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 @@ -841,12 +841,24 @@ _create_overlapping_curve(const X_monotone_curve_2& overlap_cv, right_event = this->_push_event(right_end, Base_event::DEFAULT, ARR_INTERIOR, ARR_INTERIOR).first; } - if (!c1->is_start_point(left_event)) - left_event->add_curve_to_left(c1); + if (!c1->is_start_point(left_event)) + { + // here we do no 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)) - left_event->add_curve_to_left(c2); + 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); From 76f4de545d5ab12251af35b73670bcaf2c86c395 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 30 Aug 2017 15:01:27 +0300 Subject: [PATCH 33/44] Introduced Subcurve_vector type and used it --- Sweep_line_2/include/CGAL/Sweep_line_2.h | 5 ++++- .../CGAL/Sweep_line_2/Sweep_line_2_impl.h | 17 +++++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/Sweep_line_2/include/CGAL/Sweep_line_2.h b/Sweep_line_2/include/CGAL/Sweep_line_2.h index b85dce1997c..c399d6fc63f 100644 --- a/Sweep_line_2/include/CGAL/Sweep_line_2.h +++ b/Sweep_line_2/include/CGAL/Sweep_line_2.h @@ -27,6 +27,8 @@ */ #include +#include + #include #include #include @@ -152,6 +154,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(); @@ -187,7 +190,7 @@ protected: */ void _create_overlapping_curve(const X_monotone_curve_2& overlap_cv, Subcurve*& c1 , Subcurve*& c2, - const std::vector& all_leaves_diff, + const Subcurve_vector& all_leaves_diff, Subcurve* first_parent, Event* event_on_overlap); 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 e7b33dd499e..3f8adb85600 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 @@ -101,7 +101,7 @@ void Sweep_line_2::_handle_left_curves() // 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()) { @@ -438,7 +438,7 @@ void Sweep_line_2::_intersect(Subcurve* c1, m_curves_pair_set.resize(m_curves_pair_set.size() * 6); // handle overlapping curves with common ancesters - std::vector all_leaves_diff; + Subcurve_vector all_leaves_diff; Subcurve* first_parent=NULL; if (c1->originating_subcurve1()!=NULL || c2->originating_subcurve2()!=NULL) { @@ -448,8 +448,8 @@ void Sweep_line_2::_intersect(Subcurve* c1, first_parent = c1; Subcurve* second_parent = c2; - std::vector all_leaves_first; - std::vector all_leaves_second; + 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()) @@ -509,9 +509,10 @@ void Sweep_line_2::_intersect(Subcurve* c1, return; } else{ + CGAL_SL_PRINT_TEXT("Overlap with common ancesters"); X_monotone_curve_2 xc = first_parent->last_curve(); - for (typename std::vector::iterator sc_it=all_leaves_diff.begin(); - sc_it!=all_leaves_diff.end(); ++sc_it) + for (typename Subcurve_vector::iterator sc_it=all_leaves_diff.begin(); + sc_it!=all_leaves_diff.end(); ++sc_it) { std::vector inter_res; vector_inserter vi(inter_res) ; @@ -802,7 +803,7 @@ template :: _create_overlapping_curve(const X_monotone_curve_2& overlap_cv, Subcurve*& c1 , Subcurve*& c2, - const std::vector& all_leaves_diff, + const Subcurve_vector& all_leaves_diff, Subcurve* first_parent, Event* event_on_overlap) { @@ -824,7 +825,7 @@ _create_overlapping_curve(const X_monotone_curve_2& overlap_cv, 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 = From 898451f7435b99e64699dfa90c29cd0d175fb30b Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 30 Aug 2017 15:03:26 +0300 Subject: [PATCH 34/44] Introduced a new test that tests the case 'Overlap with common ancesters' --- .../data/test_construction/polylines/spec.txt | 1 + .../test_construction/polylines/test06.pdf | Bin 0 -> 3012 bytes .../test_construction/polylines/test06.txt | 35 ++++++++++++++++++ .../test_construction.polylines.cmd | 1 + 4 files changed, 37 insertions(+) create mode 100644 Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/spec.txt create mode 100644 Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test06.pdf create mode 100644 Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test06.txt 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..aac947be291 --- /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 ancesters" 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 0000000000000000000000000000000000000000..3489398982b942678e10d0a8544d37f594fb24b1 GIT binary patch literal 3012 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 K+}zF29rI5+Rb2-F literal 0 HcmV?d00001 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/test_construction.polylines.cmd b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_construction.polylines.cmd index 7c0952457f3..e4b43902d31 100644 --- 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 @@ -3,3 +3,4 @@ ./data/test_construction/polylines/test03.txt ./data/test_construction/polylines/test04.txt ./data/test_construction/polylines/test05.txt +./data/test_construction/polylines/test06.txt From f0dd482a28771f82c4fd1c1e32e3adcc03ed5c97 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 30 Aug 2017 15:06:21 +0300 Subject: [PATCH 35/44] Fixed spelling --- .../data/test_construction/polylines/spec.txt | 2 +- Sweep_line_2/include/CGAL/Sweep_line_2/Sweep_line_2_impl.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) 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 index aac947be291..aff1ae02e48 100644 --- 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 @@ -1 +1 @@ -test06 covers the case "Overlap with common ancesters" +test06 covers the case "Overlap with common ancestors" 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 3f8adb85600..26cf9eb84b0 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 @@ -509,7 +509,7 @@ void Sweep_line_2::_intersect(Subcurve* c1, return; } else{ - CGAL_SL_PRINT_TEXT("Overlap with common ancesters"); + CGAL_SL_PRINT_TEXT("Overlap with common ancestors"); 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) @@ -525,7 +525,7 @@ void Sweep_line_2::_intersect(Subcurve* c1, 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 ancesters)"); + CGAL_SL_PRINT_END_EOL("computing intersection (overlap with common ancestors)"); return; } } From 4a93ac421bff77b3ad2fd21b97a8faa4bd2b46f2 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Thu, 28 Sep 2017 15:40:25 +0300 Subject: [PATCH 36/44] Added some test cases for plane sweep of polylines --- .../test_construction/polylines/test07.pdf | Bin 0 -> 13549 bytes .../test_construction/polylines/test07.txt | 54 +++++++++++++ .../test_construction/polylines/test08.pdf | Bin 0 -> 13486 bytes .../test_construction/polylines/test08.txt | 41 ++++++++++ .../test_construction/polylines/test09.pdf | Bin 0 -> 2537 bytes .../test_construction/polylines/test09.txt | 75 ++++++++++++++++++ .../test_construction/polylines/test10.txt | 48 +++++++++++ 7 files changed, 218 insertions(+) create mode 100644 Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test07.pdf create mode 100644 Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test07.txt create mode 100644 Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test08.pdf create mode 100644 Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test08.txt create mode 100644 Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test09.pdf create mode 100644 Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test09.txt create mode 100644 Arrangement_on_surface_2/test/Arrangement_on_surface_2/data/test_construction/polylines/test10.txt 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 0000000000000000000000000000000000000000..44b03fdbd18cfdf5ee2f8d2dade88841c5862610 GIT binary patch literal 13549 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 W4o-j8nwgcEgA0*@LQGy9@qYnhWN%pj literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..422d6ebf9bfc5929f4f3e5172fc3c0f63a000d14 GIT binary patch literal 13486 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 EU#GeI8vp Date: Mon, 2 Oct 2017 11:28:09 +0300 Subject: [PATCH 37/44] Added missing debugging end-of-line --- Sweep_line_2/include/CGAL/Sweep_line_2/Sweep_line_2_impl.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 26cf9eb84b0..b1ad937d986 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 @@ -349,7 +349,7 @@ _add_curve_to_right(Event* event, Subcurve* curve) 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 that overlapping curve will be added to the right of + // that the overlapping curve will be added to the right of // `event` because of an adjacency in the status line. // Indicate that an overlap has occured: @@ -510,6 +510,7 @@ void Sweep_line_2::_intersect(Subcurve* c1, } else{ CGAL_SL_PRINT_TEXT("Overlap with common ancestors"); + CGAL_SL_PRINT_EOL(); 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) From dee84a26e9ffb8cf64fdf2eb3db96f363da08e2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 14 Nov 2017 10:14:50 +0100 Subject: [PATCH 38/44] avoid creating a new overlapping curve if it has already been created this avoid some mismatch issues in the left events and the status line --- .../CGAL/Sweep_line_2/Sweep_line_2_impl.h | 45 +++++++++++++------ .../CGAL/Sweep_line_2/Sweep_line_subcurve.h | 26 +++++++++++ 2 files changed, 57 insertions(+), 14 deletions(-) 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 b1ad937d986..c8c332753f2 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 @@ -865,22 +865,39 @@ _create_overlapping_curve(const X_monotone_curve_2& overlap_cv, left_event->remove_curve_from_right(c2); // Allocate the new Subcurve for the overlap - Subcurve* overlap_sc; + Subcurve* overlap_sc=NULL; if (all_leaves_diff.empty()) { - 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); + // 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; + } + } + + 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)"); 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 3efbb9b7be5..5120ba27486 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 @@ -229,6 +229,32 @@ public: 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) { + 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 contain a common leaf node. */ bool has_common_leaf(Self *s) { From 9dcf23d490383c81a60f05bc7f5c21cb2d51658c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 14 Nov 2017 10:18:17 +0100 Subject: [PATCH 39/44] improve is_right_curve_bigger make sure all the curves were in the set of right curve of the event to compare them, fall back on geometric test if not --- .../CGAL/Sweep_line_2/Sweep_line_2_impl.h | 6 ++-- .../CGAL/Sweep_line_2/Sweep_line_event.h | 31 +++++++++++++------ 2 files changed, 24 insertions(+), 13 deletions(-) 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 c8c332753f2..509a8afa99a 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 @@ -710,7 +710,7 @@ _create_intersection_point(const Point_2& xp, // The multiplicity of the intersection point is unkown or undefined: _add_curve_to_right(e, c1); _add_curve_to_right(e, c2); - if (e->is_right_curve_bigger(c1, c2)) std::swap(c1, c2); + if (e->is_right_curve_bigger(c1, c2, this->m_traits)) std::swap(c1, c2); } else { if ((multiplicity % 2) == 1) { @@ -757,7 +757,7 @@ _create_intersection_point(const Point_2& xp, } } } - if (e->is_right_curve_bigger(c1, c2)) std::swap(c1, c2); + if (e->is_right_curve_bigger(c1, c2, this->m_traits)) std::swap(c1, c2); CGAL_SL_PRINT_EVENT_INFO(e); } @@ -951,7 +951,7 @@ _create_overlapping_curve(const X_monotone_curve_2& overlap_cv, this->m_visitor->found_overlap(c1, c2, overlap_sc); if (!c1->is_end_point(right_event) && !c2->is_end_point(right_event)) - if (right_event->is_right_curve_bigger(c1, c2)) + if (right_event->is_right_curve_bigger(c1, c2, this->m_traits)) std::swap(c1, c2); if (event_on_overlap != NULL && event_on_overlap!=left_event) 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 fdaaa538665..b2f2fc13f90 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 @@ -449,22 +449,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. */ From 7aa680c66ac3f4145f1a0b69007fa59c0cf98a55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 14 Nov 2017 10:20:58 +0100 Subject: [PATCH 40/44] only call _is_right_curve_bigger only when needed --- .../include/CGAL/Sweep_line_2/Sweep_line_2_impl.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) 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 509a8afa99a..a659e4adf39 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 @@ -742,6 +742,15 @@ _create_intersection_point(const Point_2& xp, _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)) { @@ -757,7 +766,7 @@ _create_intersection_point(const Point_2& xp, } } } - if (e->is_right_curve_bigger(c1, c2, this->m_traits)) std::swap(c1, c2); + CGAL_SL_PRINT_EVENT_INFO(e); } From a42566fd015675b0802d01262dc6da0bf350a3e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 14 Nov 2017 10:28:16 +0100 Subject: [PATCH 41/44] enable new tests --- .../Arrangement_on_surface_2/test_construction.polylines.cmd | 3 +++ 1 file changed, 3 insertions(+) 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 index e4b43902d31..91908142c6d 100644 --- 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 @@ -4,3 +4,6 @@ ./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 From 261bd95fc7bbf348ea77b36759d3e3650786d44f Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Tue, 14 Nov 2017 17:52:15 +0200 Subject: [PATCH 42/44] Initialize the hint (pointer to the status line) when the curve is removed from the status line --- Sweep_line_2/include/CGAL/Sweep_line_2/Basic_sweep_line_2_impl.h | 1 + Sweep_line_2/include/CGAL/Sweep_line_2/Sweep_line_2_impl.h | 1 + 2 files changed, 2 insertions(+) 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 0cc93082487..9a56082cb72 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 @@ -589,6 +589,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 a659e4adf39..1e9dac1e9e1 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 @@ -373,6 +373,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 From 5fbd297a8985b80dfbe34b5e82ee7a2d59d85418 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 14 Nov 2017 18:04:16 +0100 Subject: [PATCH 43/44] remove comments --- .../include/CGAL/Sweep_line_2/Arr_insertion_traits_2.h | 2 +- .../include/CGAL/Sweep_line_2/Sweep_line_2_impl.h | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) 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 65ba5ba1f46..f42dcfdb572 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,7 @@ public: { if(cv1.halfedge_handle() != invalid_he && cv2.halfedge_handle() != invalid_he && - cv1.halfedge_handle()!=cv2.halfedge_handle()) //SL_SAYS check with Efi + 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/Sweep_line_2_impl.h b/Sweep_line_2/include/CGAL/Sweep_line_2/Sweep_line_2_impl.h index 1e9dac1e9e1..b2939e28037 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 @@ -504,7 +504,7 @@ void Sweep_line_2::_intersect(Subcurve* c1, _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); // SL_SAYS check with Efi + this->m_visitor->found_overlap(c1, c2, first_parent); CGAL_SL_PRINT_END_EOL("computing intersection"); return; @@ -828,7 +828,6 @@ _create_overlapping_curve(const X_monotone_curve_2& overlap_cv, 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)) { - // SL_SAYS check with Efi CGAL_assertion(c1->left_event() == c2->left_event()); left_event=(Event*)(c1->left_event()); } @@ -844,7 +843,6 @@ _create_overlapping_curve(const X_monotone_curve_2& overlap_cv, 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)) { - // SL_SAYS check with Efi CGAL_assertion(c1->right_event() == c2->right_event()); right_event = (Event*)(c1->right_event()); } @@ -855,7 +853,7 @@ _create_overlapping_curve(const X_monotone_curve_2& overlap_cv, if (!c1->is_start_point(left_event)) { - // here we do no add a curve on the left if there wasn't a curve before + // 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). @@ -918,7 +916,7 @@ _create_overlapping_curve(const X_monotone_curve_2& overlap_cv, sc_it!=all_leaves_diff.end(); ++sc_it) { - overlap_sc = this->m_subCurveAlloc.allocate(1); // SL_SAYS: allocate all at once? + 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); From 8df4fb911fffd199948864911dc7d1d0e3710c45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 14 Nov 2017 18:23:36 +0100 Subject: [PATCH 44/44] add more comments about why we do it incrementaly --- .../CGAL/Sweep_line_2/Sweep_line_2_impl.h | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) 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 b2939e28037..f4b99477433 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 @@ -512,17 +512,25 @@ void Sweep_line_2::_intersect(Subcurve* c1, 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; - vector_inserter vi(inter_res) ; - vector_inserter vi_end(inter_res); + ; - this->m_traits->intersect_2_object()(xc, (*sc_it)->last_curve(), vi); - // SL_SAYS: we need to check that the following assertions are always valid - CGAL_assertion(inter_res.empty() || inter_res.size()==1); + 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()); }