#ifndef CGAL_MAP_OVERLAY_SWEEP_H #define CGAL_MAP_OVERLAY_SWEEP_H #include #include #ifndef CGAL_IN_PLACE_LIST_H #include #endif #ifndef CGAL_HANDLE_H #include #endif #ifndef CGAL_ASSERTIONS_H #include #endif #ifndef CGAL_MAP_OVERLAY_BASE_H #include #endif #ifndef CGAL_SWEEP_CURVES_BASE_H #include #endif #ifndef CGAL_POINT_PLUS_HANDLE_H #include #endif CGAL_BEGIN_NAMESPACE template class X_curve_plus_id_handle; template class Point_plus_handle; 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 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) {}; //Arr_X_curve_plus(const curve &cv, Halfedge_handle h, bool b) : curve(cv), parent(h), first_map(b) {} 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_is_same(*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 >::iterator > class Map_overlay_sweep : public Map_overlay_base, public Sweep_curves_base, Map_overlay_sweep_utils::X_curve_plus_id_handle > { public: typedef PM_ PM; typedef Map_overlay_change_notification_ Map_overlay_change_notification; typedef Curve_iterator_ Curve_iterator; typedef Point_plus_handle Point_plus; typedef Map_overlay_sweep_utils::X_curve_plus_id_handle X_curve_plus; 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 typename PM::Traits Traits; typedef typename Traits::X_curve X_curve; typedef typename Traits::Point Point; typedef Sweep_curves_base 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 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_flip(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_flip(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; Event_queue event_queue; Status_line status; //std::list disjoint_interior_curves; 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()); 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_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.make_x_monotone(*cv_iter, x_monotone_subcurves); #ifdef CGAL_SWEEP_LINE_DEBUG std::cout<<"printing x-monotone parts"<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); 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_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 ); 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 "<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.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_flip(*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_get_point_status(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_is_same(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_is_same(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() <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 "<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())<get_curve().flipped()){ //cout<<"update subdivision: curve is flipped "<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 (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 (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()="<curve()<curve() == cv || h->curve() == traits.curve_flip(cv)) // return h; if (traits.curve_is_same(h->curve(),cv) || traits.curve_is_same(h->curve(),traits.curve_flip(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(),cv) || traits.curve_is_same(circ->curve(),traits.curve_flip(cv))) return Halfedge_handle(circ); //if (circ->curve() == cv || circ->curve() == traits.curve_flip(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(), cv_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())) { // means we have a new sub curve to insert. Halfedge_handle h; cout<<"handling curves "<get_curve()<<"with right most point so far "<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()<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, right_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<