// Copyright (c) 1997 Tel-Aviv University (Israel). // All rights reserved. // // This file is part of CGAL (www.cgal.org); you may redistribute it under // the terms of the Q Public License version 1.0. // See the file LICENSE.QPL distributed with CGAL. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ // $Id$ // // // Author(s) : Eti Ezra #ifndef CGAL_MAP_OVERLAY_SWEEP_H #define CGAL_MAP_OVERLAY_SWEEP_H #include #include #include #include #include #include #include #include #include CGAL_BEGIN_NAMESPACE template class X_curve_plus_id_handle; template class Point_handle_plus; struct Map_overlay_sweep_utils { // X_curve_plus_id_handle: // holds a curve and its id number. // The addition of id number to a curve was made due to overlapping // (in which some binary predicates return EQUAL, // while we are interseted in sharp order relation. template class X_curve_plus_id_handle : public PM_::Traits::X_curve { public: typedef PM_ PM; typedef typename PM::Traits Traits; //typedef SweepLineTraits_2 Traits; typedef typename Traits::X_curve curve; typedef typename Traits::Point Point; //typedef typename Arrangement::Halfedge_handle Halfedge_handle; typedef typename PM::Halfedge_const_handle Halfedge_const_handle; X_curve_plus_id_handle() : curve(), parent(), first_map_(true), flipped_(false) {}; X_curve_plus_id_handle(const curve &cv, Halfedge_const_handle h, bool first_map, bool flipped, unsigned int id = 0) : curve(cv), parent(h), first_map_(first_map), flipped_(flipped), id_(id){} //Arr_X_curve_plus(Halfedge_handle h, bool b) : curve(h->curve()), //parent(h), first_map(b) {} X_curve_plus_id_handle(Halfedge_const_handle h, bool first_map, bool flipped, unsigned int id = 0) : curve(h->curve()), parent(h), first_map_(first_map), flipped_(flipped), id_(id) {} // used when no Halfedge_handle is supplied. X_curve_plus_id_handle(const curve &cv, bool first_map, bool flipped, unsigned int id = 0) : curve(cv), parent(), first_map_(first_map), flipped_(flipped), id_(id) {}; X_curve_plus_id_handle(const X_curve_plus_id_handle &cv) : curve(cv), parent(cv.parent), first_map_(cv.first_map()), flipped_(cv.flipped()), id_(cv.id()) {} ~X_curve_plus_id_handle(){} X_curve_plus_id_handle& operator=(const X_curve_plus_id_handle &cv) { curve::operator=(cv); parent=cv.get_parent(); first_map_ = cv.first_map(); flipped_= cv.flipped(); id_ = cv.id(); return *this; } bool operator==(const X_curve_plus_id_handle &cv) const { //return curve::operator==(cv); Traits traits; return (id_ == cv.id() && traits.curve_equal(*this, cv)); } void set_id(unsigned int i) { id_ = i; } Halfedge_const_handle get_parent() const { return parent; } bool first_map() const { return first_map_; } bool flipped() const { return flipped_; } unsigned int id() const { return id_; } protected: Halfedge_const_handle parent; bool first_map_; bool flipped_; unsigned int id_; }; }; template class Map_overlay_sweep : public Map_overlay_base, public Sweep_curves_base_2 >::iterator, typename PM_::Traits, Point_handle_plus, Map_overlay_sweep_utils::X_curve_plus_id_handle > { public: typedef PM_ PM; typedef Map_overlay_change_notification_ Map_overlay_change_notification; //typedef std::list >::iterator //Curve_iterator; typedef Point_handle_plus Point_plus; typedef Map_overlay_sweep_utils::X_curve_plus_id_handle X_curve_plus; typedef typename std::list::iterator Curve_iterator; typedef typename PM::Vertex_handle Vertex_handle; typedef typename PM::Halfedge_handle Halfedge_handle; typedef typename PM::Face_handle Face_handle; typedef typename PM::Vertex_const_handle Vertex_const_handle; typedef typename PM::Halfedge_const_handle Halfedge_const_handle; typedef typename PM::Face_const_handle Face_const_handle; typedef typename PM::Vertex Vertex; typedef typename PM::Halfedge Halfedge; typedef typename PM::Face Face; typedef typename PM::Vertex_iterator Vertex_iterator; typedef typename PM::Vertex_const_iterator Vertex_const_iterator; typedef typename PM::Halfedge_iterator Halfedge_iterator; typedef typename PM::Halfedge_const_iterator Halfedge_const_iterator; typedef typename PM::Face_iterator Face_iterator; typedef typename PM::Face_const_iterator Face_const_iterator; typedef typename PM::Ccb_halfedge_circulator Ccb_halfedge_circulator; typedef typename PM::Locate_type Locate_type; //typedef SweepLineTraits_2 Traits; typedef typename PM::Traits Traits; typedef typename Traits::X_curve X_curve; typedef typename Traits::Point Point; typedef Sweep_curves_base_2 Base; typedef typename Base::Curve_node Curve_node; typedef typename Base::Intersection_point_node Intersection_point_node; typedef typename Base::Points_iterator Points_iterator; typedef typename Base::Points_const_iterator Points_const_iterator; typedef typename Base::Curve_node_iterator Curve_node_iterator; typedef typename Base::Curve_node_const_iterator Curve_node_const_iterator; typedef typename Base::X_curve_list X_curve_list; typedef typename Base::X_curve_list_iterator X_curve_list_iterator; typedef typename Base::Vertices_points_plus Vertices_points_plus; typedef typename Base::Event_queue Event_queue; typedef typename Base::Status_line Status_line; typedef typename Vertices_points_plus::value_type Vertices_points_plus_value_type; typedef typename Event_queue::value_type Event_queue_value_type; typedef typename Status_line::value_type Status_line_value_type; typedef typename Vertices_points_plus::iterator Vertices_points_plus_iterator; typedef typename Event_queue::iterator Event_queue_iterator; typedef typename Status_line::iterator Status_line_iterator; typedef typename std::list::iterator list_Curve_node_iterator; typedef std::list X_curve_plus_list; typedef typename X_curve_plus_list::iterator X_curve_plus_list_iterator; //typedef Curve_node::Points_iterator Points_iterator; typedef //Curve_node::Points_const_iterator Points_const_iterator; typedef //Intersection_point_node::Curve_node_iterator Curve_node_iterator; //typedef Intersection_point_node::Curve_node_const_iterator //Curve_node_const_iterator; // typedef std::pair Curve_pair; // typedef std::map > // Vertices_points_plus; typedef std::multimap > Event_queue; // typedef std::multimap > Status_line; void map_overlay(const PM &a1, const PM &a2, Map_overlay_change_notification *pm_change_notf, PM &result) { std::list curves; unsigned int id = 0; // updating curevs to contain all updated curves plus. Halfedge_const_iterator h_iter; for (h_iter = a1.halfedges_begin(); h_iter != a1.halfedges_end(); ++h_iter, ++h_iter, ++id){ bool b; X_curve cv(h_iter->curve()); if ((b = is_right(traits->curve_source(h_iter->curve()), traits->curve_target(h_iter->curve())) )) cv = traits->curve_opposite(h_iter->curve()); Halfedge_const_handle h = h_iter; curves.push_back(X_curve_plus(cv, h, true, b, id)); //is_right(traits.curve_source(cv), // traits.curve_target(cv))) ); } for(h_iter = a2.halfedges_begin(); h_iter != a2.halfedges_end(); ++h_iter, ++h_iter, ++id){ bool b; X_curve cv(h_iter->curve()); if ((b = is_right(traits->curve_source(h_iter->curve()), traits->curve_target(h_iter->curve())) )) cv = traits->curve_opposite(h_iter->curve()); Halfedge_const_handle h = h_iter; curves.push_back(X_curve_plus(cv, h, false, b, id)); //is_right(traits.curve_source(cv), // traits.curve_target(cv))) ); } sweep_curves_to_planar_map(curves.begin(), curves.end(), pm_change_notf, result); pm_change_notf->update_all_faces(result); } private: void sweep_curves_to_planar_map(Curve_iterator curves_begin, Curve_iterator curves_end, Map_overlay_change_notification *pm_change_notf, PM &result) { //Traits traits; typename Base::Less_xy event_queue_pred(traits); Event_queue event_queue(event_queue_pred); typename Base::Less_yx status_pred(traits); Status_line status(status_pred); //Event_queue event_queue; //Status_line status; //int c_sweep_t; //c_sweep_t = clock(); #ifdef CGAL_SWEEP_LINE_DEBUG unsigned int n = 0; for (Curve_iterator cv_iter = curves_begin; cv_iter != curves_end; ++cv_iter, ++n); cout<<"number of edges on input "<< n <curve_source(*cv_iter)) == input_vertices.end()) input_vertices.insert( Vertices_points_plus_value_type (traits->curve_source(*cv_iter), Point_plus(traits->curve_source(*cv_iter))) ); if (input_vertices.find(traits->curve_target(*cv_iter)) == input_vertices.end()) input_vertices.insert( Vertices_points_plus_value_type (traits->curve_target(*cv_iter), Point_plus(traits->curve_target(*cv_iter))) ); } // end of input_vertices construction. // now creating the Curve_node handles and the event queue. for(Curve_iterator cv_iter = curves_begin; cv_iter != curves_end; ++cv_iter){ //X_curve cv(*cv_iter); //if (is_right(traits.curve_source(*cv_iter), // traits.curve_target(*cv_iter)) ) // cv = traits.curve_opposite(*cv_iter); #ifdef CGAL_SWEEP_LINE_DEBUG cout<< *cv_iter <curve_source(*cv_iter) ); //assert(traits.curve_source(cv) == curr_point_plus->second.point()); Event_queue_iterator edge_point = event_queue.find( traits->curve_source(*cv_iter) ); // defining one cv_node for both source and target event points. //X_curve_plus cv_plus(cv, id); // to satisfy BCC. Curve_node cv_node = Curve_node(*cv_iter, curr_point_plus->second,traits ); Intersection_point_node source_point_node = Intersection_point_node(cv_node, curr_point_plus->second,traits ); if (edge_point == event_queue.end() || edge_point->second.get_point() != source_point_node.get_point()) event_queue.insert(Event_queue_value_type (traits->curve_source(*cv_iter), source_point_node)); else edge_point->second.merge(source_point_node); edge_point = event_queue.find( traits->curve_target(*cv_iter) ); curr_point_plus = input_vertices.find( traits->curve_target(*cv_iter) ); //assert(traits.curve_target(cv) == curr_point_plus->second.point()); Intersection_point_node target_point_node = Intersection_point_node(cv_node, curr_point_plus->second, traits ); if (edge_point == event_queue.end() || edge_point->second.get_point() != target_point_node.get_point()) event_queue.insert(Event_queue_value_type(traits-> curve_target(*cv_iter), target_point_node)); else edge_point->second.merge(target_point_node); } // now starting the sweeping. unsigned int queue_size = 0; bool event_terminated = true; //bool event_overlap_terminated = true; while ( !(event_queue.empty()) ){ ++queue_size; // fetch the next event. Event_queue_iterator event = event_queue.begin(); const Point& event_point = event->first; Intersection_point_node& point_node = event->second; //bool event_terminated = true; #ifdef CGAL_SWEEP_LINE_DEBUG cout<<"* * * event point is "<curve_source(cv_iter->get_curve()) && event_point == cv_iter->get_rightmost_point().point()) cv_iter->erase_rightmost_point(); } // now, updating the planar map (or arrangement) according the curves // enemating from the currnet event point. update_subdivision(point_node, pm_change_notf, result); // updating all the new intersection nodes of the curves // participating within the event. for (Curve_node_iterator cv_iter = point_node.curves_begin(); cv_iter != point_node.curves_end(); ++cv_iter){ if (event_point != cv_iter->get_rightmost_point().point()) cv_iter->push_event_point(point_node.get_point()); } //if (event_terminated) event_queue.erase(event); } #ifdef CGAL_SWEEP_LINE_DEBUG std::cout<<"the number of events was "<curve()); // result.clear(); // // Now, creating all the point_plus handle: for any pair of overlapping // points from the input we ensure we have only one handle. - not having // such a structure as input_vertices caused a bug. // Vertices_points_plus input_vertices; // for (X_curve_list_iterator cv_iter = subdivision_curves.begin(); // cv_iter != subdivision_curves.end(); cv_iter++){ // if (input_vertices.find(traits.curve_source(*cv_iter)) == // input_vertices.end()) // input_vertices.insert(Vertices_points_plus_value_type // (traits.curve_source(*cv_iter), // Point_plus(traits.curve_source(*cv_iter))) ); // if (input_vertices.find(traits.curve_target(*cv_iter)) == // input_vertices.end()) // input_vertices.insert(Vertices_points_plus_value_type // (traits.curve_target(*cv_iter), // Point_plus(traits.curve_target(*cv_iter))) ); // }*/ // // splitting all curves to x-monotone curves. // X_curve_plus_list x_monotone_curves; // for (Curve_iterator cv_iter = curves_begin; // cv_iter != curves_end; ++cv_iter){ // /*if (!traits.is_x_monotone(*cv_iter)) { // X_curve_list x_monotone_subcurves; // traits.curve_make_x_monotone(*cv_iter, x_monotone_subcurves); // #ifdef CGAL_SWEEP_LINE_DEBUG // std::cout<<"printing x-monotone parts"<parent(), // cv_iter->first_map(), cv_iter->id())); // } // } // else*/ // x_monotone_curves.push_back(*cv_iter); // } // /* // // now adding to the x-monotone container all the curves // // in the original subdivision. // for (X_curve_plus_list_iterator cv_iter = subdivision_curves.begin(); // cv_iter != subdivision_curves.end(); cv_iter++) // x_monotone_curves.push_back(*cv_iter);*/ // // Now, creating all the point_plus handle: for any pair of // overlapping points // // from the input we ensure we have only one handle. - not having such // // a structure as input_vertices caused a bug. // for (X_curve_plus_list_iterator cv_iter = x_monotone_curves.begin(); // cv_iter != x_monotone_curves.end(); ++cv_iter){ // if (input_vertices.find(traits.curve_source(*cv_iter)) == // input_vertices.end()) // input_vertices.insert( Vertices_points_plus_value_type // (traits.curve_source(*cv_iter), // Point_plus(traits.curve_source(*cv_iter)))); // if (input_vertices.find(traits.curve_target(*cv_iter)) == // input_vertices.end()) // input_vertices.insert( Vertices_points_plus_value_type // (traits.curve_target(*cv_iter), // Point_plus(traits.curve_target(*cv_iter)))); // } // // end of input_vertices construction. // // now creating the Curve_node handles and the event queue. // unsigned int id = 0; // for(X_curve_plus_list_iterator cv_iter = x_monotone_curves.begin(); // cv_iter != x_monotone_curves.end(); ++cv_iter, ++id){ // X_curve cv(*cv_iter); // //Halfedge_const_handle parent = cv_iter->get_parent(); // if (is_right(traits.curve_source(*cv_iter), // traits.curve_target(*cv_iter)) ) // cv = traits.curve_opposite(*cv_iter); // #ifdef CGAL_SWEEP_LINE_DEBUG // cout<second.point()); // Event_queue_iterator edge_point = // event_queue.find( traits.curve_source(cv) ); // // defining one cv_node for both source and target event points. // //X_curve_plus cv_plus(cv, id); // to satisfy BCC. // Curve_node cv_node = Curve_node(X_curve_plus(cv, // cv_iter->get_parent(), // cv_iter->first_map(), // cv_iter->flipped(), // id), // curr_point_plus->second); // Intersection_point_node source_point_node = // Intersection_point_node(cv_node, curr_point_plus->second ); // if (edge_point == event_queue.end() || // edge_point->second.get_point() != source_point_node.get_point()) // event_queue.insert(Event_queue_value_type // (traits.curve_source(cv), // source_point_node)); // else // edge_point->second.merge(source_point_node); // edge_point = event_queue.find( traits.curve_target(cv) ); // curr_point_plus = input_vertices.find( traits.curve_target(cv) ); // //assert(traits.curve_target(cv) == curr_point_plus->second.point()); // Intersection_point_node target_point_node = // Intersection_point_node(cv_node, curr_point_plus->second ); // if (edge_point == event_queue.end() || // edge_point->second.get_point() != target_point_node.get_point()) // event_queue.insert(Event_queue_value_type(traits.curve_target(cv), // target_point_node)); // else // edge_point->second.merge(target_point_node); // } // int c_sweep_t; // c_sweep_t = clock(); // // now starting the sweeping. // unsigned int queue_size = 0; // bool event_terminated = true; // //bool event_overlap_terminated = true; // while ( !(event_queue.empty()) ){ // queue_size++; // // fetch the next event. // Event_queue_iterator event = event_queue.begin(); // const Point& event_point = event->first; // Intersection_point_node& point_node = event->second; // //bool event_terminated = true; // #ifdef CGAL_SWEEP_LINE_DEBUG // cout<<"* * * event point is "<get_curve()) && // event_point == cv_iter->get_rightmost_point().point()) // cv_iter->erase_rightmost_point(); // } // // now, updating the planar map (or arrangement) according the curves // // enemating from the currnet event point. // update_subdivision(point_node, pm_change_notf, result); // // updating all the new intersection nodes of the curves // // participating within the event. // for (Curve_node_iterator cv_iter = point_node.curves_begin(); // cv_iter != point_node.curves_end(); ++cv_iter){ // if (event_point != cv_iter->get_rightmost_point().point()) // cv_iter->push_event_point(point_node.get_point()); // } // //if (event_terminated) // event_queue.erase(event); // } // #ifdef CGAL_SWEEP_LINE_DEBUG // std::cout<<"the number of events was "<first; Status_line::iterator next_neighbor = ++lower_neighbor; if (next_neighbor == status.end()) return false; lower_neighbor--; Curve_node cv2 = next_neighbor->first; #ifdef CGAL_SWEEP_LINE_DEBUG cout<<"cv1 and cv2 are "<first.get_rightmost_point().point()); if (is_left(next_neighbor->first.get_rightmost_point().point(), // lower_neighbor->first.get_rightmost_point().point())) ref_point = next_neighbor->first.get_rightmost_point().point(); if (traits.nearest_intersection_to_right (cv1.get_curve(), cv2.get_curve(), // ref_point, xp1, xp2) ){ // we choose the leftmost point because the intersection point may be one // of the points on lower_neighbor or next_neighbor, specially it can be a // tangent point, and the function nearest_intersection_to_right may // return false (it's third parameter is the ittersection point itself!). #ifdef CGAL_SWEEP_LINE_DEBUG cout<<"rightmost pointon status, xp1 and xp2 are " <first.get_rightmost_point().point()<<" "<first.get_rightmost_point().point()) xp1 = xp2; // for debugging. //if (traits.curve_compare_y_at_x(cv1.get_curve(), xp1) != // Traits::ON_CURVE) // cout<<"The point "<first.push_event_point(xp1); //next_iter->first.push_event_point(xp1); Event_queue::iterator xp_event = event_queue.find(xp1); bool xp_cv1_in_queue = false, xp_cv2_in_queue = false; if (xp_event == event_queue.end()) event_queue.insert(Event_queue::value_type(xp1, Intersection_point_node(cv1, cv2, xp1))); else{ // have to check the event is a new event. (we might calculated with // point before). for ( Curve_node_iterator cv_iter = xp_event->second.curves_begin(); cv_iter != xp_event->second.curves_end(); cv_iter++){ if (traits.curve_equal(cv_iter->get_curve(), cv1.get_curve()) ) // fix later : change it to compare the curve nodes it self! xp_cv1_in_queue = true; if (traits.curve_equal(cv_iter->get_curve(), cv2.get_curve()) ) xp_cv2_in_queue = true; } if (!xp_cv1_in_queue && !xp_cv2_in_queue) xp_event->second.merge(Intersection_point_node(cv1, cv2, Point_plus(xp1))); else if (!xp_cv1_in_queue) xp_event->second.merge(Intersection_point_node(cv1, Point_plus(xp1))); else if (!xp_cv2_in_queue) xp_event->second.merge(Intersection_point_node(cv2, Point_plus(xp1))); } // updating the curve_node holding the right point of cv1 (so when we // get to this event point //we can find easily the curve node and remove it from status. point = xp1; return (!xp_cv1_in_queue || !xp_cv2_in_queue); } } return false; }*/ void update_subdivision(Intersection_point_node& point_node, Map_overlay_change_notification *pm_change_notf, PM &pm) { #ifdef CGAL_SWEEP_LINE_DEBUG cout<<"--------- updating map with point node"<< point_node.get_point().point() <curves_overlap(cv_iter1->get_curve(), cv_iter2->get_curve())) cout<<"update_subdivision "<get_curve()<< " and "<< cv_iter2->get_curve() <<" are overlapping"<get_curve()<get_rightmost_point().point(), point_node.get_point().point())) { // means we have a new sub curve to insert. Halfedge_handle h; // first splitting the curve in the points // cv_iter->get_rightmost_point().point() // and point_node.get_point().point(). X_curve cv = cv_iter->get_curve(), sub_cv = cv_iter->get_curve(), right_cv = cv; //cout<<"cv is "<curve_source(cv) != cv_iter->get_rightmost_point().point() && traits->curve_target(cv) != cv_iter->get_rightmost_point().point() ) { traits->curve_split(cv, sub_cv, right_cv, cv_iter->get_rightmost_point().point()); cv = right_cv; } if (traits->curve_source(cv) != point_node.get_point().point() && traits->curve_target(cv) != point_node.get_point().point()) traits->curve_split(cv, sub_cv, right_cv, point_node.get_point().point()); else sub_cv = right_cv; // for debugging! //assert(sub_cv == X_curve(cv_iter->get_rightmost_point().point(), // point_node.get_point().point())); //cout<<"sub curve calculates is "<get_rightmost_point().point(), // point_node.get_point().point())<curves_overlap(sub_cv, prev_sub_cv)){ //cout<get_curve().flipped()){ //cout<<"update subdivision: curve is flipped "<curve_opposite(sub_cv); //cout< set_curve_attributes(sub_cv, cv_iter->get_curve().get_parent(), cv_iter->get_curve().first_map()); if (overlap){ // special case of overlapping: // We do not insert the overlapped curve. // However, we have to call add_edge of the notifier in order to // update attributes // of the current halfedge. if (pm_change_notf){ h = find_halfedge(sub_cv, pm); pm_change_notf->add_edge(sub_cv, h, true, true); } } else { prev_sub_cv = sub_cv; if (cv_iter->get_rightmost_point().vertex() != Vertex_handle(NULL)){ //assert(cv_iter->get_rightmost_point().point() == // cv_iter->get_rightmost_point().vertex()->point()); if (point_node.get_point().vertex() != Vertex_handle(NULL)) { //assert(point_node.get_point().point() == // point_node.get_point().vertex()->point()); if (cv_iter->get_curve().flipped()) // opposite orientation. h = pm.insert_at_vertices(sub_cv, point_node.get_point().vertex(), cv_iter-> get_rightmost_point().vertex(), pm_change_notf); else h = pm.insert_at_vertices(sub_cv, cv_iter-> get_rightmost_point().vertex(), point_node.get_point().vertex(), pm_change_notf); } else { if (cv_iter->get_curve().flipped()) h = pm.insert_from_vertex (sub_cv, cv_iter-> get_rightmost_point().vertex(), false, pm_change_notf); else h = pm.insert_from_vertex (sub_cv, cv_iter-> get_rightmost_point().vertex(), true, pm_change_notf); } } else if (point_node.get_point().vertex() != Vertex_handle(NULL)) { //assert(point_node.get_point().point() // == point_node.get_point().vertex()->point()); if (cv_iter->get_curve().flipped()) h = pm.insert_from_vertex (sub_cv, point_node.get_point().vertex(), true, pm_change_notf); else h = pm.insert_from_vertex (sub_cv, point_node.get_point().vertex(), false, pm_change_notf); } else{ h = pm.insert_in_face_interior (sub_cv, pm.unbounded_face(), pm_change_notf); // the point is that if the curve has no source to start the // insertion from, it has to be inserted to the unbounded face, // because all the curves to the right of it have not inserted yet, // and in that stage of the sweep line, the curve is on the // unbounded face - later on it will be updated automatically by // the Planar map (Arrangement) insert functions. } } //assert(h->source()->point() == cv_iter->get_rightmost_point().point() // || // (h->target()->point() == cv_iter->get_rightmost_point().point())); // now update the vertex handle of each point. //if (cv_iter->get_rightmost_point().vertex() == Vertex_handle(NULL)) if (!overlap || pm_change_notf){ if (h->source()->point() == cv_iter->get_rightmost_point().point()) //cv_iter->set_vertex_of_rightmost_point(h->source()); cv_iter->get_rightmost_point().set_vertex(h->source()); else if (h->target()->point() == cv_iter->get_rightmost_point().point()) //cv_iter->set_vertex_of_rightmost_point(h->target()); cv_iter->get_rightmost_point().set_vertex(h->target()); } //assert(h->source()->point() == point_node.get_point().point() || // (h->target()->point() == point_node.get_point().point())); //if (point_node.get_point().vertex() == Vertex_handle(NULL)) if (!overlap || pm_change_notf){ if (h->source()->point() == point_node.get_point().point()) point_node.get_point().set_vertex(h->source()); else if (h->target()->point() == point_node.get_point().point()) point_node.get_point().set_vertex(h->target()); } } // else - no new sub curve is inserted to the subdivision. } } Halfedge_handle find_halfedge(const X_curve& cv, PM& pm) { //cout<<"In find_halfedge"<curve_source(cv),lt); //cout<<"cv="<curve()="<curve()<curve() == cv || h->curve() == traits.curve_opposite(cv)) // return h; if (traits->curve_equal(h->curve(),cv) || traits->curve_equal(h->curve(),traits->curve_opposite(cv)) ) return h; Vertex_handle v; if (h->source()->point() == traits->curve_source(cv)) v = h->source(); else v = h->target(); typename PM::Halfedge_around_vertex_circulator circ = v->incident_halfedges(); do { //cout<<"circ->curve()="<curve()<curve_equal(circ->curve(),cv) || traits->curve_equal(circ->curve(),traits->curve_opposite(cv))) return Halfedge_handle(circ); //if (circ->curve() == cv || circ->curve() == traits.curve_opposite(cv)) // return Halfedge_handle(circ); } while (++circ != v->incident_halfedges()); CGAL_assertion(0); return Halfedge_handle(0); } /* void update_subdivision(Intersection_point_node& point_node, Map_overlay_change_notification *pm_change_notf, PM &pm) { for (Curve_node_iterator cv_iter = point_node.curves_begin(); cv_iter != point_node.curves_end(); cv_iter++){ if (is_left(cv_iter->get_rightmost_point().point(), point_node.get_point().point())) { // means we have a new sub curve to insert. Halfedge_handle h; pm_change_notf->set_curve_attributes(X_curve(cv_iter-> get_rightmost_point().point(), point_node.get_point().point()), cv_iter-> get_curve().get_parent(), cv_iter-> get_curve().get_parent()->twin(), cv_iter-> get_curve().first_map()); if (cv_iter->get_rightmost_point().vertex() != Vertex_handle(NULL)){ //assert(cv_iter->get_rightmost_point().point() == //cv_iter->get_rightmost_point().vertex()->point()); if (point_node.get_point().vertex() != Vertex_handle(NULL)) { //assert(point_node.get_point().point() == //point_node.get_point().vertex()->point()); h = pm.insert_at_vertices(X_curve( cv_iter-> get_rightmost_point().point(), point_node.get_point().point()), cv_iter->get_rightmost_point().vertex(), point_node.get_point().vertex(), pm_change_notf); } else h = pm.insert_from_vertex (X_curve( cv_iter-> get_rightmost_point().point(), point_node.get_point().point()), cv_iter->get_rightmost_point().vertex(), true, pm_change_notf); } else if (point_node.get_point().vertex() != Vertex_handle(NULL)) { //assert(point_node.get_point().point() == //point_node.get_point().vertex()->point()); h = pm.insert_from_vertex (X_curve( point_node.get_point().point(), c v_iter->get_rightmost_point().point()), point_node.get_point().vertex(), true, pm_change_notf); } else{ h = pm.insert_in_face_interior (X_curve( cv_iter-> get_rightmost_point().point(), point_node.get_point().point()), pm.unbounded_face(), pm_change_notf); // the point is that if the curve has no source to start the insertion // from, it has to be inserted to the unbounded face, because all the // curves to the right of it have not inserted yet, and in that stage of // the sweep line, the curve is on the unbounded face - later on it will // be updated automatically by the Planar map (Arrangement) insert // functions. } //assert(h->source()->point() == cv_iter->get_rightmost_point().point() // || (h->target()->point() == cv_iter->get_rightmost_point().point())); // now update the vertex handle of each point. //if (cv_iter->get_rightmost_point().vertex() == Vertex_handle(NULL)) { if (h->source()->point() == cv_iter->get_rightmost_point().point()) cv_iter->set_vertex_of_rightmost_point(h->source()); else if (h->target()->point() == cv_iter->get_rightmost_point().point()) cv_iter->set_vertex_of_rightmost_point(h->target()); } //assert(h->source()->point() == point_node.get_point().point() || (h->target()->point() == point_node.get_point().point())); //if (point_node.get_point().vertex() == Vertex_handle(NULL)) { if (h->source()->point() == point_node.get_point().point()) point_node.set_vertex(h->source()); else if (h->target()->point() == point_node.get_point().point()) point_node.set_vertex(h->target()); } } // else - no new sub curve is inserted to the subdivision. } }*/ void update_subdivision_debug(Intersection_point_node& point_node, PM &arr) { cout<<"--------- updating map"<get_rightmost_point().point(), point_node.get_point().point())) { Halfedge_handle h; cout << "handling curves "<get_curve() << "with right most point so far " << cv_iter->get_rightmost_point().point()<get_rightmost_point().vertex() != Vertex_handle(NULL)){ assert(cv_iter->get_rightmost_point().point() == cv_iter->get_rightmost_point().vertex()->point()); std::cout << "Point of cv_iter is on map" << cv_iter->get_rightmost_point().point() <point()); h = arr.insert_at_vertices(X_curve(cv_iter-> get_rightmost_point().point(), point_node.get_point().point()), cv_iter->get_rightmost_point().vertex(), point_node.get_point().vertex()); } else h = arr.insert_from_vertex (X_curve(cv_iter-> get_rightmost_point().point(), point_node.get_point().point()), cv_iter->get_rightmost_point().vertex(), true); } else if (point_node.get_point().vertex() != Vertex_handle(NULL)) { std::cout << "Only Point of point_node is on map" << point_node.get_point().point() <point()); h = arr.insert_from_vertex (X_curve( point_node.get_point().point(), cv_iter-> get_rightmost_point().point()), point_node.get_point().vertex(), true); } else{ // debugging. Locate_type lt; Halfedge_handle tmp_h = arr.locate(cv_iter-> get_rightmost_point().point(), lt); std::cout << "curve right most point locate type is " <get_rightmost_point().point() << std::endl; tmp_h = arr.locate(point_node.get_point().point(), lt); std::cout << "point intersection node locate type is " < get_rightmost_point().point(), point_node.get_point().point()), arr.unbounded_face()); // the point is that if the curve has no source to start the insertion // from, it has to be inserted to the unbounded face, because all the // curves to the right of it have not inserted yet, and in that stage // of the sweep line, the curve is on the unbounded face - later on it // will be updated automatically by the Planar map (Arrangement) // insert functions. } assert(h->source()->point() == cv_iter->get_rightmost_point().point() || (h->target()->point() == cv_iter->get_rightmost_point().point())); // now update the vertex handle of each point. //if (cv_iter->get_rightmost_point().vertex() == Vertex_handle(NULL)) //for (Curve_node_iterator curr_cv_iter = point_node.curves_begin(); // curr_cv_iter != point_node.curves_end(); curr_cv_iter++) { if (h->source()->point() == cv_iter->get_rightmost_point().point()) cv_iter->set_vertex_of_rightmost_point(h->source()); else if (h->target()->point() == cv_iter->get_rightmost_point().point()) cv_iter->set_vertex_of_rightmost_point(h->target()); else assert(0); } assert(h->source()->point() == point_node.get_point().point() || (h->target()->point() == point_node.get_point().point())); //if (point_node.get_point().vertex() == Vertex_handle(NULL)) { if (h->source()->point() == point_node.get_point().point()) point_node.set_vertex(h->source()); else if (h->target()->point() == point_node.get_point().point()) point_node.set_vertex(h->target()); else assert(0); } } // else - no new sub curve is inserted to the subdivision. } // checking that the handles were correctly updated. for (Curve_node_iterator cv_iter = point_node.curves_begin(); cv_iter != point_node.curves_end(); cv_iter++){ if (is_left(cv_iter->get_rightmost_point().point(), point_node.get_point().point())) // means we have a new sub curve to insert. assert (cv_iter->get_rightmost_point().vertex() != Vertex_handle(NULL)); } cout<<"--------- finish updating map"<& curves, Map_overlay_change_notification *pmwx_change_notf, Arrangement &arr) { #ifdef CGAL_SWEEP_LINE_DEBUG cout<<"Inserting "<::const_iterator cv_iter = curves.begin(); cv_iter != curves.end(); cv_iter++){ #ifdef CGAL_SWEEP_LINE_DEBUG cout<<"The Curve is "<get_curve()<get_curve(), left_cv, right_cv = cv_iter->get_curve(); for (Curve_node::Points_const_iterator points_iter = cv_iter->points_begin(); points_iter != cv_iter->points_end(); points_iter++){ // make surve the splitting is not at the edge points. if (points_iter == cv_iter->points_begin()) continue; ++points_iter; if (points_iter == cv_iter->points_end()) break; points_iter--; #ifdef CGAL_SWEEP_LINE_DEBUG cout<<"Right sub curve is "<set_curve_attributes(left_cv, cv_iter-> get_curve().get_parent(), cv_iter-> get_curve().get_parent()->twin(), cv_iter-> get_curve().is_first_map()); arr.insert(left_cv, pmwx_change_notf); cv = right_cv; } pmwx_change_notf->set_curve_attributes(right_cv, cv_iter->get_curve().get_parent(), cv_iter-> get_curve().get_parent()->twin(), cv_iter-> get_curve().is_first_map()); arr.insert(right_cv, pmwx_change_notf); } } void build_pm_overlay(const std::list& curves, Arrangement &arr) { #ifdef CGAL_SWEEP_LINE_DEBUG cout<<"Inserting "<::const_iterator cv_iter = curves.begin(); cv_iter != curves.end(); cv_iter++){ #ifdef CGAL_SWEEP_LINE_DEBUG cout<<"The Curve is "<get_curve()<get_curve(), left_cv, r ight_cv = cv_iter->get_curve(); Halfedge_handle h; for (Curve_node::Points_const_iterator points_iter = cv_iter->points_begin(); points_iter != cv_iter->points_end(); points_iter++){ // make surve the splitting is not at the edge points. if (points_iter == cv_iter->points_begin()) continue; #ifdef CGAL_SWEEP_LINE_DEBUG cout<<"Right sub curve is "<points_end()) last = true; points_iter--; if (last) left_cv = right_cv; // if the point is the last one, it's the target point and we can't make split. else traits.curve_split(cv, left_cv, right_cv, *points_iter); #ifdef CGAL_SWEEP_LINE_DEBUG cout<<"Sub curve is "<points_begin()) second_intersection_point = true; points_iter++; // h always holds in its source the left point and in its target the // right point. if (second_intersection_point) h = arr.insert(left_cv); else{ Locate_type lt; Halfedge_handle located_h = arr.locate(*points_iter, lt); if (lt == Arrangement::VERTEX){ Vertex_handle v; if (located_h->source()->point() == *points_iter) v = located_h->source(); else v = located_h->target(); h = arr.insert_at_vertices (left_cv, h->target(), v); } else h = arr.insert_from_vertex (left_cv, h->target(), true); } cv = right_cv; } //arr.insert(right_cv); } }*/ /* //---- debuging functions ---- bool is_valid(const Status_line& status){ std::list curve_nodes; std::list subcurves; for (Status_line::const_iterator iter = status.begin(); iter != status.end(); iter++) curve_nodes.push_back(iter->first); get_subcurves(curve_nodes, subcurves); return (!do_intersect_subcurves(subcurves)); } // Output function. void write_pm_overlay(const std::list& curves) { #ifdef CGAL_SWEEP_LINE_DEBUG cout<<"Inserting "<::const_iterator cv_iter = curves.begin(); cv_iter != curves.end(); cv_iter++){ X_curve cv = cv_iter->get_curve(), left_cv, right_cv = cv_iter->get_curve(); for (Curve_node::Points_const_iterator points_iter = cv_iter->points_begin(); points_iter != cv_iter->points_end(); points_iter++){ // make surve the splitting is not at the edge points. if (points_iter == cv_iter->points_begin()) continue; num_of_subcurves++; ++points_iter; if (points_iter == cv_iter->points_end()){ f_curves << right_cv.source().xcoordD() <<" " << right_cv.source().ycoordD() <<" "<< right_cv.target().xcoordD() <<" "<< right_cv.target().ycoordD() <& curves) { double max_x = 10, min_x = -10, min_y = -10; // debuging. //cout<<"Inserting "<::const_iterator cv_iter = curves.begin(); cv_iter != curves.end(); cv_iter++){ X_curve cv = cv_iter->get_curve(), left_cv, right_cv = cv_iter->get_curve(); for (Curve_node::Points_const_iterator points_iter = cv_iter->points_begin(); points_iter != cv_iter->points_end(); points_iter++){ W<points_begin()) continue; ++points_iter; if (points_iter == cv_iter->points_end()) break; points_iter--; //cout<<"Right sub curve is "<& curves, std::list& subcurves) { for (std::list::const_iterator cv_iter = curves.begin(); cv_iter != curves.end(); cv_iter++){ X_curve cv = cv_iter->get_curve(), left_cv, right_cv = cv_iter->get_curve(); for (Curve_node::Points_const_iterator points_iter = cv_iter->points_begin(); points_iter != cv_iter->points_end(); points_iter++){ // make surve the splitting is not at the edge points. if (points_iter == cv_iter->points_begin()) continue; if (*points_iter == rightmost(traits.curve_source(cv_iter->get_curve()), traits.curve_target(cv_iter->get_curve())) ) left_cv = right_cv; else traits.curve_split(cv, left_cv, right_cv, points_iter->point()); subcurves.push_back(left_cv); cv = right_cv; } //subcurves.push_back(right_cv); } } bool do_intersect_subcurves(const std::list& subcurves) { for (std::list::const_iterator scv_iter1 = subcurves.begin(); scv_iter1 != subcurves.end(); scv_iter1++){ for (std::list::const_iterator scv_iter2 = scv_iter1; scv_iter2 != subcurves.end(); scv_iter2++){ if (scv_iter2 == scv_iter1) continue; Point ref_point1, ref_point2, xp1, xp2; ref_point1 = leftmost(traits.curve_source(*scv_iter1), traits.curve_target(*scv_iter1)); ref_point2 = leftmost(traits.curve_source(*scv_iter2), traits.curve_target(*scv_iter2)); if (ref_point1 != ref_point2) ref_point1 = leftmost(ref_point1, ref_point2); if (traits.nearest_intersection_to_right(*scv_iter1, *scv_iter2, ref_point1, xp1, xp2)){ if (xp1 == ref_point1) xp1 = xp2; if ( !( (xp1 == traits.curve_source(*scv_iter1) || xp1 == traits.curve_target(*scv_iter1) ) && (xp1 == traits.curve_source(*scv_iter2) || xp1 == traits.curve_target(*scv_iter2) )) ){ #ifdef CGAL_SWEEP_LINE_DEBUG cout<<"The curves "<<*scv_iter1<<" "<<*scv_iter2<<" are intersected in the point "<second; cout<first); } cout<<"\n"; } void print_points_on_curves(const Curve_node& cv){ cout<<"list of points is "<point()<<" "; cout<