diff --git a/Visibility_2/include/CGAL/Parallel_rotational_sweep_visibility_2.h b/Visibility_2/include/CGAL/Parallel_rotational_sweep_visibility_2.h index 84bb163448b..29384febac4 100644 --- a/Visibility_2/include/CGAL/Parallel_rotational_sweep_visibility_2.h +++ b/Visibility_2/include/CGAL/Parallel_rotational_sweep_visibility_2.h @@ -27,7 +27,7 @@ #include #include #include -#include +#include //#define MYDEBUG #ifdef MYDEBUG @@ -71,16 +71,42 @@ private: typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2; typedef typename Geometry_traits_2::Point_2 Point_2; + typedef typename Geometry_traits_2::FT Number_type; typedef typename Arrangement_2::Ccb_halfedge_const_circulator Circulator; private: Circulator circ; CGAL::Orientation orient; + CGAL::Orientation boundary_orient; enum { NOT_APPLIED, INWARD, OUTWARD, IN_EDGE, AT_SOURCE, AT_TARGET } mode; int idx; + int prev_idx; + int quad; + private: + int compute_quad( const Point_2& query_pt, const Point_2& p ) + { + CGAL::Comparison_result cx = CGAL::compare_x( query_pt, p ); + CGAL::Comparison_result cy = CGAL::compare_y( query_pt, p ); + if ( cy == CGAL::SMALLER ) { + if ( cx == CGAL::SMALLER ) + return 0; + else + return 1; + } else if ( cy == CGAL::LARGER ) { + if ( cx == CGAL::LARGER ) + return 2; + else + return 3; + } else { + if ( cx != CGAL::LARGER ) + return 0; + else + return 2; + } + } public: - Edge ( const Point_2& query_pt, const Circulator& he, bool on_edge, bool on_vertex, int _idx ) - : circ( he ), idx( _idx ) + Edge ( const Point_2& query_pt, const Circulator& he, bool on_edge, bool on_vertex ) + : circ( he ) { if ( on_vertex ) { orient = CGAL::COLLINEAR; @@ -108,7 +134,11 @@ private: mode = NOT_APPLIED; } } + quad = compute_quad( query_pt, he->source()->point() ); + boundary_orient = CGAL::orientation( prev_source(), source(), target() ); } + void set_index ( int i, int p ) + { idx = i; prev_idx = p; } const Point_2& source () const { return circ->source()->point(); } @@ -122,6 +152,8 @@ private: { return circ; } CGAL::Orientation orientation () const { return orient; } + CGAL::Orientation boundary_orientation () const + { return boundary_orient; } bool inward () const { return ( mode == INWARD ); } bool outward () const @@ -134,6 +166,12 @@ private: { return ( mode == AT_TARGET ); } int index () const { return idx; } + int prev_index () const + { return prev_idx; } + int quadrant () const + { return quad; } + bool angle_less_than_pi () const + { return ( quadrant() < 2 ); } #ifdef MYDEBUG void trace ( ostream& os ) @@ -173,6 +211,7 @@ private: break; } os << "]" << endl; + os << "\t\tquadrant=[" << quadrant() << "], idx=[" << index() << "], prev_idx=[" << prev_index() << "]" << endl; } #endif }; @@ -208,36 +247,11 @@ private: typedef typename Geometry_traits_2::Point_2 Point_2; typedef typename Geometry_traits_2::FT Number_type; private: - // angle_less_than pi - // Verify whether the polar angle of p is less than pi - bool angle_less_than_pi( const Point_2& p ) - { - CGAL::Orientation orient = CGAL::orientation( query_pt, aux, p ); - return ( orient == CGAL::LEFT_TURN || - ( orient == CGAL::COLLINEAR && p.x() >= query_pt.x() ) ); - } - // less_general - // precondition: query_pt, p1 and p2 are not collinear - // return true if p1 has smaller polar angle - bool less_general ( const Point_2& p1, const Point_2& p2, CGAL::Orientation orient ) - { - if ( angle_less_than_pi( p1 ) ) { - if ( orient == CGAL::LEFT_TURN ) - return true; - else - return ( CGAL::orientation( query_pt, aux, p2 ) == CGAL::RIGHT_TURN ); - } else { - if ( orient == CGAL::RIGHT_TURN ) - return false; - else - return ( CGAL::orientation( query_pt, aux, p2 ) == CGAL::RIGHT_TURN ); - } - } // less_source_at_query_pt // Precondition: he1.source() == query_pt bool less_source_at_query_pt( const Edge_type& he1, const Edge_type& he2 ) { - CGAL::Orientation orient1 = CGAL::orientation( he1.prev_source(), he1.source(), he1.target() ); + CGAL::Orientation orient1 = he1.boundary_orientation(); CGAL::Orientation orient2 = CGAL::orientation( he1.source(), he1.target(), he2.source() ); if ( orient1 == CGAL::LEFT_TURN ) { // The boundary makes a left turn at query_pt @@ -251,14 +265,26 @@ private: return false; } else { // he1.source(), he1.target(), he2.source() are ordered along ray - return !angle_less_than_pi( he2.source() ); + return !he2.angle_less_than_pi(); + } + } else if ( orient2 == CGAL::LEFT_TURN ) { + // he1.source(), he1.target(), he2.source() make a left turn + if ( he2.angle_less_than_pi() ) { + return false; + } else { + return ( he1.target().y() < query_pt.y() || + ( he1.target().y() == query_pt.y() && + he1.target().x() < query_pt.x() ) ); } } else { - Point_2 image( query_pt.x()+query_pt.x()-he1.target().x(), query_pt.y()+query_pt.y()-he1.target().y() ); - if ( orient2 == CGAL::LEFT_TURN ) - return less_general( image, he2.source(), CGAL::RIGHT_TURN ); - else - return less_general( image, he2.source(), CGAL::LEFT_TURN ); + // he1.source(), he1.target(), he2.source() make a right turn + if ( he2.angle_less_than_pi() ) { + return ( he1.target().y() < query_pt.y() || + ( he1.target().y() == query_pt.y() && + he1.target().x() < query_pt.x() ) ); + } else { + return true; + } } } else { // The boundary makes a right turn at query_pt, @@ -269,56 +295,82 @@ private: // he1.source(), he1.target(), he2.source() are collinear if ( CGAL::collinear_are_ordered_along_line( he2.source(), he1.source(), he1.target() ) ) { // he1.source() is between he1.target() and he2.source() - return angle_less_than_pi( he1.target() ); + return !he2.angle_less_than_pi(); } else { // he1.source(), he1.target(), he2.source() are ordered along ray return true; } + } else if ( orient2 == CGAL::LEFT_TURN ) { + // he1.source(), he1.target(), he2.source() make a left turn + if ( he2.angle_less_than_pi() ) { + return ( he1.target().y() > query_pt.y() || + ( he1.target().y() == query_pt.y() && + he1.target().x() > query_pt.x() ) ); + } else { + return true; + } } else { - return less_general( he1.target(), he2.source(), orient2 ); + // he1.source(), he1.target(), he2.source() make a right turn + if ( he2.angle_less_than_pi() ) { + return false; + } else { + return ( he1.target().y() > query_pt.y() || + ( he1.target().y() == query_pt.y() && + he1.target().x() > query_pt.x() ) ); + } } } } - // less_on_ray - // Precondition: he1.source() and he2.source() are collinear on a ray - // shooting from the query_pt - bool less_on_ray ( const Edge_type& he1, const Edge_type& he2 ) + // less + bool less ( const Edge_type& he1, const Edge_type& he2 ) { - if ( CGAL::collinear_are_ordered_along_line( query_pt, he1.source(), he2.source() ) ) - // he1.source() is closer - return ( he1.orientation() == CGAL::RIGHT_TURN || - ( he1.at_source() || he1.outward() ) ); - else - return !( he2.orientation() == CGAL::RIGHT_TURN || - ( he2.at_source() || he2.outward() ) ); - } - public: - // Constructor - Less_Source( const Point_2& q, const Point_2& a ) - : query_pt( q ), aux( a ) - {} - // Comparator - // Precondition: he1 and he2 are not the same halfedge - bool operator () ( const Edge_type& he1, const Edge_type& he2 ) - { - CGAL::Orientation orient = CGAL::orientation( query_pt, he1.source(), he2.source() ); - if ( orient != CGAL::COLLINEAR ) - return less_general( he1.source(), he2.source(), orient ); - // query_pt, he1.source(), he2.source() are collinear if ( he2.at_source() ) return !less_source_at_query_pt( he2, he1 ); if ( he1.at_source() ) return less_source_at_query_pt( he1, he2 ); - if ( CGAL::collinear_are_ordered_along_line( he1.source(), query_pt, he2.source() ) ) - // querypt is between he1.source() and he2.source() - return angle_less_than_pi( he1.source() ); - return less_on_ray ( he1, he2 ); + + if ( he1.quadrant() != he2.quadrant() ) + return ( he1.quadrant() < he2.quadrant() ); + // In the same quadrant + CGAL::Orientation orient = CGAL::orientation( query_pt, he1.source(), he2.source() ); + if ( orient != CGAL::COLLINEAR ) { + // General case, in the same quadrant + return ( orient == CGAL::LEFT_TURN ); + } else { + // query_pt, he1.source(), he2.source() are collinear on a ray + if ( CGAL::collinear_are_ordered_along_line( query_pt, he1.source(), he2.source() ) ) { + // he1.source() is closer + return ( he1.orientation() == CGAL::RIGHT_TURN || he1.outward() ); + } else { + // he2.source() is closer + return !( he2.orientation() == CGAL::RIGHT_TURN || he2.outward() ); + } + } } + public: + // Constructor + Less_Source( const Point_2& q ) + : query_pt( q ) + {} + // Comparator + // Precondition: he1 and he2 are not the same halfedge + bool operator () ( const Edge_type& he1, const Edge_type& he2 ) + { return less( he1, he2 ); } private: Point_2 query_pt; Point_2 aux; }; + /* + class Less_Edge + Compare the halfedges intersecting a ray, find whose intersection point + is closer to the query point. + The class rovides a comparator: + Less_Edge( const Edge_type& he1, const Edge_type& he2 ) + where he1 and he2 are two half edges. + + Precondition: he1 != he2 + */ template < class E > class Less_Edge { @@ -326,93 +378,73 @@ private: typedef E Edge_type; typedef typename E::Geometry_traits_2 Geometry_traits_2; typedef typename Geometry_traits_2::Point_2 Point_2; - typedef typename Geometry_traits_2::FT Number_type; private: - // less_vertex, the halfedge he1 passes throught query_pt + Point_2 query_pt; + private: + // less_vertex + // Precondition: (1) he1 contains query_pt + // (2) he2 does not contain query_pt bool less_vertex ( const Edge_type& he1, const Edge_type& he2 ) { - if ( he1.at_source() ) { - if ( he2.at_target() ) { - // he2 is the previous halfedge of he1 - return ( CGAL::orientation( query_pt, *p_aux, he1.target() ) != CGAL::COLLINEAR ); - } else { - return true; - } - } else if ( he1.at_target() ) { - if ( he2.at_source() ) { - // he2 is the next halfege of he2 - return ( CGAL::orientation( query_pt, *p_aux, he2.target() ) == CGAL::COLLINEAR ); - } else { - return true; - } - } else { - // The query point lies in the interior of he1 - return true; - } + assert( !(he2.at_source() || he2.at_target() || he2.in_edge() ) ); + return true; } - // less_collinear, the halfedge he1 is through the ray (query_pt, *p_aux) - bool less_collinear ( const Edge_type& he1, const Edge_type& he2 ) - { - if ( he1.inward() ) { - if ( he2.inward() || he2.outward() ) - return ( CGAL::collinear_are_ordered_along_line( query_pt, he1.target(), he2.target() ) ); - else - return ( CGAL::orientation( he2.source(), he2.target(), query_pt ) == - CGAL::orientation( he2.source(), he2.target(), he1.target() ) ); - } else { - // he1.outward() - if ( he2.inward() || he2.outward() ) - return ( CGAL::collinear_are_ordered_along_line( query_pt, he1.source(), he2.source() ) ); - else - return ( CGAL::orientation( he2.source(), he2.target(), query_pt ) == - CGAL::orientation( he2.source(), he2.target(), he1.source() ) ); - } - } - // General setting, he2 is the next halfedge of he1 + // less_consecutive + // Precondition: (1) Both he1 and he2 does not contain query_pt + // (2) he1 is the previous halfedge of he2 bool less_consecutive ( const Edge_type& he1, const Edge_type& he2 ) { - CGAL::Orientation orient1 = CGAL::orientation( query_pt, *p_aux, he1.target() ); - if ( orient1 == CGAL::LEFT_TURN ) { - return ( CGAL::orientation( he1.source(), he1.target(), he2.target() ) == CGAL::RIGHT_TURN ); - } else if ( orient1 == CGAL::RIGHT_TURN ) { - return ( CGAL::orientation( he1.source(), he1.target(), he2.target() ) == CGAL::LEFT_TURN ); + if ( he1.outward() ) + return true; + else if ( he1.inward() ) + return false; + else if ( he1.orientation() == CGAL::LEFT_TURN ) { + return ( he2.boundary_orientation() == CGAL::RIGHT_TURN ); } else { - // orient1 == CGAL::COLLINEAR - if ( he1.orientation() == CGAL::LEFT_TURN ) { - if ( he2.orientation() == CGAL::LEFT_TURN ) - return false; - else - return ( CGAL::orientation( he1.source(), he1.target(), he2.target() ) == CGAL::RIGHT_TURN ); - } else { - // he1.orientation() == CGAL::RIGHT_TURN - if ( he2.orientation() == CGAL::RIGHT_TURN ) - return true; - else - return ( CGAL::orientation( he1.source(), he1.target(), he2.target() ) == CGAL::LEFT_TURN ); - } + // he1.orientation() == CGAL::RIGHT_TURN + return ( he2.boundary_orientation() != CGAL::RIGHT_TURN ); } } - // less_general, the general case + // less_collinear + // Precondition: (1) Both he1 and he2 does not contain query_pt + // (2) he1 and he2 are not incident + // (3) query_pt, he1.source(), he1.target() are collinear + bool less_collinear ( const Edge_type& he1, const Edge_type& he2 ) + { + if ( he2.inward() || he2.outward() ) { + return CGAL::collinear_are_ordered_along_line( query_pt, + he1.source(), + he2.source() ); + } else { + return ( CGAL::orientation( he2.source(), he2.target(), he1.source() ) + == he2.orientation() ); + } + } + // less_general + // Precondition: (1) Both he1 and he2 does not contain query_pt + // (2) he1 and he2 are not incident + // (3) he1.orientation() == CGAL::LEFT_TURN || RIGHT_TURN + // (4) he2.orientation() == CGAL::LEFT_TURN || RIGHT_TURN bool less_general ( const Edge_type& he1, const Edge_type& he2 ) { - if ( he1.source() == he2.target() ) - return !less_consecutive( he2, he1 ); - if ( he1.target() == he2.source() ) - return less_consecutive( he1, he2 ); - CGAL::Orientation orient1 = CGAL::orientation( he1.source(), he1.target(), he2.source() ); - CGAL::Orientation orient2 = CGAL::orientation( he1.source(), he1.target(), he2.target() ); + CGAL::Orientation orient1 = CGAL::orientation( he1.source(), + he1.target(), + he2.source() ); + CGAL::Orientation orient2 = CGAL::orientation( he1.source(), + he1.target(), + he2.target() ); if ( orient1 == orient2 ) { - return ( CGAL::orientation( he1.source(), he1.target(), query_pt ) != orient1 ); + // he2.source() and he2.target() lies on the same side of he1 + return ( CGAL::orientation( he1.source(), he1.target(), query_pt ) + != orient1 ); } else { - return ( CGAL::orientation( he2.source(), he2.target(), query_pt ) == - CGAL::orientation( he2.source(), he2.target(), he1.source() ) ); + // he2.source() and he2.target() lies on the different side of he1 + return ( CGAL::orientation( he2.source(), he2.target(), he1.source() ) + == he2.orientation() ); } } - public: - Less_Edge ( const Point_2& q, const Point_2 * a ) - : query_pt( q ), p_aux( a ) - {} - bool operator () ( const Edge_type& he1, const Edge_type& he2 ) + // less + bool less ( const Edge_type& he1, const Edge_type& he2 ) { if ( he1.circulator() == he2.circulator() ) return false; @@ -420,27 +452,90 @@ private: return less_vertex( he1, he2 ); if ( he2.at_source() || he2.at_target() || he2.in_edge() ) return !less_vertex( he2, he1 ); + if ( he1.index() == he2.prev_index() ) + return less_consecutive( he1, he2 ); + if ( he1.prev_index() == he2.index() ) + return !less_consecutive( he2, he1 ); if ( he1.inward() || he1.outward() ) return less_collinear( he1, he2 ); if ( he2.inward() || he2.outward() ) return !less_collinear( he2, he1 ); return less_general( he1, he2 ); } + public: + Less_Edge ( const Point_2& q ) + : query_pt( q ) + {} + bool operator () ( const Edge_type& he1, const Edge_type& he2 ) + { return less( he1, he2 ); } + }; + + template < class E, class Comp > + class Active_Edge + { private: - Point_2 query_pt; - const Point_2 * p_aux; + typedef E Edge_type; + typedef Comp Sorter; + typedef typename E::Geometry_traits_2 Geometry_traits_2; + typedef typename Geometry_traits_2::Point_2 Point_2; + typedef typename std::set Active_edge_container; + typedef typename std::vector Edge_vector; + private: + Active_edge_container active_edges; + const Edge_vector * p_edges; + std::vector active; + public: + Active_Edge ( const Edge_vector * pe, const Sorter& s ) + : p_edges( pe ), active_edges( s ) + { active.assign( pe->size(), false ); } + + void insert ( const Edge_type& he ) + { + active_edges.insert( he ); + active[he.index()] = true; + } + void erase ( const Edge_type& he ) + { + active_edges.erase( he ); + active[he.index()] = false; + } + void replace ( const Edge_type& he1, const Edge_type& he2 ) + { + typename Active_edge_container::const_iterator ait; + ait = active_edges.find( he1 ); + assert( ait != active_edges.end() ); + const Edge_type& const_he = *ait; + Edge_type& tmp_he = const_cast(const_he); + tmp_he = he2; + active[he1.index()] = false; + active[he2.index()] = true; + } + bool is_active( int idx ) const + { return active[idx]; } + const Edge_type& closest () const + { return *(active_edges.begin()); } +#ifdef MYDEBUG + void trace ( ostream& os ) + { + typename Active_edge_container::const_iterator ait; + for( ait = active_edges.begin(); ait != active_edges.end(); ait++ ) { + cout << "Edge: " << ait->source() << " --> " << ait->target() << endl; + } + cout << "Active:[ "; + for ( int i = 0; i < active.size(); i++ ) { + if ( active[i] ) + cout << i << " "; + } + cout << "]" << endl; + } +#endif }; private: typedef Edge Edge_type; typedef std::vector Edge_vector; typedef typename Edge_vector::const_iterator Edge_iterator; - typedef bool Active_edge_property; typedef Less_Edge Active_edge_sorter; - typedef std::map - Active_edge_container; - typedef typename Active_edge_container::const_iterator - Active_const_iterator; private: // do_intersect_ray @@ -449,14 +544,23 @@ private: bool do_intersect_ray ( const Point_2& query_pt, const Point_2& aux, const Edge_type& he ) { if ( he.orientation() != CGAL::COLLINEAR ) { - Ray_2 ray( query_pt, aux ); - Segment_2 seg( he.source(), he.target() ); - if ( !CGAL::do_intersect( ray, seg ) ) + CGAL::Orientation orient1 = CGAL::orientation( query_pt, aux, he.source() ); + CGAL::Orientation orient2 = CGAL::orientation( query_pt, aux, he.target() ); + if ( orient1 == orient2 ) return false; - if ( he.orientation() == CGAL::LEFT_TURN ) - return ( CGAL::orientation( query_pt, aux, he.source() ) == CGAL::RIGHT_TURN ); - else - return ( CGAL::orientation( query_pt, aux, he.target() ) == CGAL::RIGHT_TURN ); + if ( orient1 == CGAL::COLLINEAR ) { + if ( CGAL::collinear_are_ordered_along_line( aux, query_pt, he.source() ) ) + return false; + // Ray intersects he at he.source() + return ( he.orientation() == CGAL::RIGHT_TURN ); + } else if ( orient2 == CGAL::COLLINEAR ) { + if ( CGAL::collinear_are_ordered_along_line( aux, query_pt, he.target() ) ) + return false; + // Ray intersects he at he.target() + return ( he.orientation() == CGAL::LEFT_TURN ); + } else { + return ( CGAL::orientation( query_pt, aux, he.target() ) == he.orientation() ); + } } else if ( he.inward() || he.outward() ) { return false; } else if ( he.at_source() ) { @@ -534,10 +638,8 @@ private: std::vector& out_points ) { Point_2 aux; - Active_edge_sorter closer( query_pt, &aux ); - Active_edge_container active_edges( closer ); - std::vector active; - Active_const_iterator ait; + Active_edge_sorter closer( query_pt ); + Active_Edge< Edge_type, Active_edge_sorter > active( &unsorted_edges, closer ); // Initialize the edges intersecting the ray aux = first->source(); @@ -550,11 +652,9 @@ private: } } - active.assign( unsorted_edges.size(), false ); for ( Edge_iterator eit = edges.begin(); eit != edges.end(); eit++ ) { if ( do_intersect_ray( query_pt, aux, *eit ) ) { - active_edges.insert( std::make_pair( *eit, true ) ); - active[eit->index()] = true; + active.insert( *eit ); } } @@ -563,94 +663,82 @@ cout << "query_pt = [" << query_pt << "]" < " << unsorted_edges[i].target() << " idx = " << unsorted_edges[i].index() << endl; + unsorted_edges[i].trace( cout ); } cout << endl; cout << "Sorted edges" << endl; cout << "================================" << endl; for ( int i = 0; i < edges.size(); i++ ) { - cout << "Edge: " << edges[i].source() << " --> " << edges[i].target() << " idx = " << edges[i].index() << endl; + edges[i].trace( cout ); } cout << endl; cout << "After Initialization" << endl; cout << "================================" << endl; -for ( ait = active_edges.begin(); ait != active_edges.end(); ait++ ) { - cout << "Edge: " << ait->first.source() << " ---> " << ait->first.target() << endl; -} +active.trace( cout ); cout << endl; #endif // Rotational sweep the ray, until reach the end of the cone - Point_2 first_intersection, last_intersection; - first_intersection = last_intersection = calculate_intersection( query_pt, aux, active_edges.begin()->first.circulator() ); - bool first_intersect_at_vertex = ( first_intersection == active_edges.begin()->first.source() || first_intersection == active_edges.begin()->first.target() ); + Point_2 first_pt, last_pt; + first_pt = last_pt = calculate_intersection( query_pt, aux, active.closest().circulator() ); + bool first_at_vertex = ( first_pt == active.closest().source() || first_pt == active.closest().target() ); for ( Edge_iterator eit = first; eit != last; eit++ ) { aux = eit->source(); int idx = eit->index(); - int prev = ( idx-1 ); - if ( prev < 0 ) - prev = unsorted_edges.size() - 1; - Circulator top = active_edges.begin()->first.circulator(); + int prev = eit->prev_index(); + Circulator top = active.closest().circulator(); assert( unsorted_edges[idx].circulator() == eit->circulator() ); #ifdef MYDEBUG -cout << "idx=" << idx << ",prev=" << prev << ",size=" << unsorted_edges.size() << endl; +cout << "idx = " << idx << " , prev = " << prev << endl; cout << "Current edge: " << eit->source() << " --> " << eit->target() << " Previous edge: " << unsorted_edges[prev].source() << " --> " << unsorted_edges[prev].target() << endl; -cout << "aux = " << aux << " top: " << top->source()->point() << " --> " << top->target()->point() << endl; +cout << "top: " << top->source()->point() << " --> " << top->target()->point() << endl; #endif - if ( active[idx] && active[prev] ) { + if ( active.is_active( idx ) && active.is_active( prev ) ) { // Both edges incident to the current vertex are active #ifdef MYDEBUG cout << "Both Active!" << endl; #endif - active_edges.erase( *eit ); - active[idx] = false; - active_edges.erase( unsorted_edges[prev] ); - active[prev] = false; - if ( top != active_edges.begin()->first.circulator() ) { + active.erase( *eit ); + active.erase( unsorted_edges[prev] ); + if ( top != active.closest().circulator() ) { Point_2 u; - u = calculate_intersection( query_pt, aux, active_edges.begin()->first.circulator() ); - if ( last_intersection != eit->source() ) + u = calculate_intersection( query_pt, aux, active.closest().circulator() ); + if ( last_pt != eit->source() ) out_points.push_back( eit->source() ); out_points.push_back( u ); - last_intersection = u; + last_pt = u; #ifdef MYDEBUG cout << "New Top! Intersection = " << u << endl; #endif } - } else if ( active[idx] ) { + } else if ( active.is_active( idx ) ) { #ifdef MYDEBUG cout << "Current Active!" << endl; #endif // Only one edge whose source is the current vertex is active. - active_edges.erase( *eit ); - active[idx] = false; - active_edges.insert( std::make_pair( unsorted_edges[prev], true ) ); - active[prev] = true; - if ( top != active_edges.begin()->first.circulator() ) { - if ( last_intersection != eit->source() ) { + active.replace( *eit, unsorted_edges[prev] ); + if ( top != active.closest().circulator() ) { + if ( last_pt != eit->source() ) { out_points.push_back( eit->source() ); - last_intersection = eit->source(); + last_pt = eit->source(); } #ifdef MYDEBUG cout << "New Top! Intersection = " << eit->source() << endl; #endif } - } else if ( active[prev] ) { + } else if ( active.is_active( prev ) ) { #ifdef MYDEBUG cout << "Previous Active!" << endl; #endif // Only one edge whose target is the current vertex is active. - active_edges.erase( unsorted_edges[prev] ); - active[prev] = false; - active_edges.insert( std::make_pair( *eit, true ) ); - active[idx] = true; - if ( top != active_edges.begin()->first.circulator() ) { - if ( last_intersection != eit->source() ) { + active.replace( unsorted_edges[prev], *eit ); + if ( top != active.closest().circulator() ) { + if ( last_pt != eit->source() ) { out_points.push_back( eit->source() ); - last_intersection = eit->source(); + last_pt = eit->source(); } #ifdef MYDEBUG cout << "New Top! Intersection = " << eit->source() << endl; @@ -661,20 +749,18 @@ cout << "New Top! Intersection = " << eit->source() << endl; #ifdef MYDEBUG cout << "Both Inctive!" << endl; #endif - active_edges.insert( std::make_pair( *eit, true ) ); - active[idx] = true; - active_edges.insert( std::make_pair( unsorted_edges[prev], true ) ); - active[prev] = true; - if ( top != active_edges.begin()->first.circulator() ) { + active.insert( *eit ); + active.insert( unsorted_edges[prev] ); + if ( top != active.closest().circulator() ) { Point_2 u; if ( query_on_vertex && query_pt == aux ) u = aux; else u = calculate_intersection( query_pt, aux, top ); - if ( last_intersection != u ) + if ( last_pt != u ) out_points.push_back( u ); out_points.push_back( eit->source() ); - last_intersection = eit->source(); + last_pt = eit->source(); #ifdef MYDEBUG cout << "New Top! Intersection = " << u << endl; #endif @@ -682,16 +768,15 @@ cout << "New Top! Intersection = " << u << endl; } #ifdef MYDEBUG cout << "*** After Iteration ***" << endl; -for ( ait = active_edges.begin(); ait != active_edges.end(); ait++ ) { - cout << "Edge: " << ait->first.source() << " ---> " << ait->first.target() << endl; -} +active.trace( cout ); cout << endl; #endif } - if ( first_intersection != last_intersection ) { - if ( first_intersect_at_vertex || - ( CGAL::orientation( out_points.front(), out_points.back(), first_intersection ) != CGAL::COLLINEAR ) ) - out_points.push_back( first_intersection ); + + if ( first_pt != last_pt ) { + if ( first_at_vertex || + ( CGAL::orientation( out_points.front(), out_points.back(), first_pt ) != CGAL::COLLINEAR ) ) + out_points.push_back( first_pt ); } #ifdef MYDEBUG cout << "Visibility segments:" << endl; @@ -708,24 +793,26 @@ cout << endl; compute_visibility_impl ( const Point_2& query_pt, VARR& arr_out ) { Point_2 aux( query_pt.x()+Number_type(1), query_pt.y() ); - Less_Source comp ( query_pt, aux ); + Less_Source comp ( query_pt ); // Sort halfedges with their source point by polar angle + std::sort( edges.begin(), edges.end(), comp ); #ifdef MYDEBUG for ( int i = 0; i < edges.size(); i++ ) { for ( int j = 0; j < edges.size(); j++ ) { - if ( i== j ) + if ( i == j ) continue; bool res = comp( edges[i], edges[j] ); - cout << "Edges1: " << edges[i].source() << " --> " << edges[i].target() << " "; - cout << "Edges2: " << edges[j].source() << " --> " << edges[j].target() << " "; - if ( res ) - cout << "Result: 1<2" < " << edges[i].target() << " "; + cout << "Edges2: " << edges[j].source() << " --> " << edges[j].target() << " "; + if ( res ) + cout << "Result: 1<2" < vec; compute_visibility_partition( query_pt, edges.begin(), edges.end(), vec ); @@ -739,6 +826,7 @@ for ( int i = 0; i < edges.size(); i++ ) { edges.clear(); unsorted_edges.clear(); + return arr_out.faces_begin(); } @@ -808,11 +896,12 @@ public: arr_out.clear(); edges.clear(); + Circulator circ, curr; Circulator qedge( he2 ); Circulator qprev( he2->prev() ); - int idx = 0; + int hole_base = 0, hole_edge = 0; if ( f->has_outer_ccb() ) { curr = circ = f->outer_ccb(); @@ -824,13 +913,18 @@ public: } else if ( curr == qprev ) { on_edge = on_vertex = query_on_vertex; } - edges.push_back( Edge_type( query_pt, curr, on_edge, on_vertex, idx ) ); - idx++; + edges.push_back( Edge_type( query_pt, curr, on_edge, on_vertex ) ); + hole_edge++; } while ( ++curr != circ ); + for ( int i = 0; i < hole_edge; i++ ) { + edges[hole_base+i].set_index( hole_base+i, hole_base+(i+hole_edge-1)%hole_edge ); + } + hole_base += hole_edge; } for ( Hole_const_iterator hi = f->holes_begin(); hi != f->holes_end(); hi++ ) { curr = circ = *hi; + hole_edge = 0; do { bool on_edge = false, on_vertex = false; if ( curr == qedge ) { @@ -839,9 +933,13 @@ public: } else if ( curr == qprev ) { on_edge = on_vertex = query_on_vertex; } - edges.push_back( Edge_type( query_pt, curr, on_edge, on_vertex, idx ) ); - idx++; + edges.push_back( Edge_type( query_pt, curr, on_edge, on_vertex ) ); + hole_edge++; } while ( ++curr != circ ); + for ( int i = 0; i < hole_edge; i++ ) { + edges[hole_base+i].set_index( hole_base+i, hole_base+(i+hole_edge-1)%hole_edge ); + } + hole_base += hole_edge; } unsorted_edges.assign( edges.begin(), edges.end() ); @@ -863,22 +961,31 @@ public: Circulator circ, curr; - int idx = 0; + int hole_base = 0, hole_edge = 0; if ( f->has_outer_ccb() ) { curr = circ = f->outer_ccb(); do { - edges.push_back( Edge_type( query_pt, curr, false, false, idx ) ); - idx++; + edges.push_back( Edge_type( query_pt, curr, false, false ) ); + hole_edge++; } while ( ++curr != circ ); + for ( int i = 0; i < hole_edge; i++ ) { + edges[hole_base+i].set_index( hole_base+i, hole_base+(i+hole_edge-1)%hole_edge ); + } + hole_base += hole_edge; } for ( Hole_const_iterator hi = f->holes_begin(); hi != f->holes_end(); hi++ ) { curr = circ = *hi; + hole_edge = 0; do { - edges.push_back( Edge_type( query_pt, curr, false, false, idx ) ); - idx++; + edges.push_back( Edge_type( query_pt, curr, false, false ) ); + hole_edge++; } while ( ++curr != circ ); + for ( int i = 0; i < hole_edge; i++ ) { + edges[hole_base+i].set_index( hole_base+i, hole_base+(i+hole_edge-1)%hole_edge ); + } + hole_base += hole_edge; } unsorted_edges.assign( edges.begin(), edges.end() ); @@ -894,7 +1001,6 @@ private: bool query_on_vertex; Edge_vector edges; Edge_vector unsorted_edges; - }; // End of class Rotational_sweep_visibility_2 } // End namespace CGAL