diff --git a/Visibility_2/include/CGAL/Simple_polygon_visibility_2.h b/Visibility_2/include/CGAL/Simple_polygon_visibility_2.h index fbe58b2ab48..ddd229f67bb 100644 --- a/Visibility_2/include/CGAL/Simple_polygon_visibility_2.h +++ b/Visibility_2/include/CGAL/Simple_polygon_visibility_2.h @@ -36,10 +36,10 @@ namespace CGAL { -template -class Simple_polygon_visibility_2 { + template + class Simple_polygon_visibility_2 { -public: + public: typedef Arrangement_2_ Arrangement_2; typedef typename Arrangement_2::Traits_2 Traits_2; typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2; @@ -49,14 +49,14 @@ public: typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle; typedef typename Arrangement_2::Halfedge_const_handle - Halfedge_const_handle; + Halfedge_const_handle; typedef typename Arrangement_2::Halfedge_handle Halfedge_handle; typedef typename Arrangement_2::Ccb_halfedge_const_circulator - Ccb_halfedge_const_circulator; + Ccb_halfedge_const_circulator; typedef typename Arrangement_2::Face_const_handle Face_const_handle; typedef typename Arrangement_2::Face_handle Face_handle; typedef typename Arrangement_2::Halfedge_around_vertex_const_circulator - Halfedge_around_vertex_const_circulator; + Halfedge_around_vertex_const_circulator; typedef typename Geometry_traits_2::Point_2 Point_2; typedef typename Geometry_traits_2::Ray_2 Ray_2; @@ -72,7 +72,7 @@ public: /*! Constructor given an arrangement and the Regularization tag. */ Simple_polygon_visibility_2(const Arrangement_2& arr): - p_arr(&arr) { + p_arr(&arr) { traits = p_arr->geometry_traits(); point_location.attach(arr); query_pt_is_vertex = false; @@ -84,7 +84,7 @@ public: std::string name() const { return std::string("S_visibility_2"); } /*! Method to check if the visibility object is attached or not to - an arrangement*/ + an arrangement*/ bool is_attached() const { return (p_arr != NULL); } @@ -92,15 +92,15 @@ public: /*! Attaches the visibility object to the 'arr' arrangement */ void attach(const Arrangement_2& arr) { if(p_arr != &arr){ - detach(); - p_arr = &arr; - traits = p_arr->geometry_traits(); - point_location.attach(arr); + detach(); + p_arr = &arr; + traits = p_arr->geometry_traits(); + point_location.attach(arr); } } /*! Detaches the visibility object from the arrangement it is - attached to*/ + attached to*/ void detach() { point_location.detach(); p_arr = NULL; @@ -117,7 +117,7 @@ public: } /*! Computes the visibility object from the query point 'q' in the face - 'face' and constructs the output in 'out_arr'*/ + 'face' and constructs the output in 'out_arr'*/ template typename VARR::Face_handle compute_visibility(const Point_2& q, @@ -149,13 +149,13 @@ public: } /*! Computes the visibility region of the query point 'q' located on the - halfedge 'he' and constructs the output in 'out_arr'*/ + halfedge 'he' and constructs the output in 'out_arr'*/ template typename VARR::Face_handle compute_visibility( - const Point_2& q, - const Halfedge_const_handle he, - VARR& out_arr ) const + const Point_2& q, + const Halfedge_const_handle he, + VARR& out_arr ) const { out_arr.clear(); @@ -197,7 +197,7 @@ public: } -private: + private: typedef Arr_walk_along_line_point_location Arr_point_location; typedef typename Arr_point_location::result_type Location_result; @@ -210,8 +210,8 @@ private: mutable Arr_point_location point_location; /*! Stack of visibile points; manipulated when going through the sequence - of input vertices; contains the vertices of the visibility region after - the run of the algorithm*/ + of input vertices; contains the vertices of the visibility region after + the run of the algorithm*/ mutable std::stack stack; /*! Sequence of input vertices*/ mutable Vertex_container vertices; @@ -226,130 +226,128 @@ private: typename VARR::Face_handle output(const Point_2& q, VARR& out_arr) const { - if(inserted_artificial_starting_vertex) - stack.pop(); + if(inserted_artificial_starting_vertex) + stack.pop(); - std::vector points; - while(!stack.empty()) { - const Point_2& top = stack.top(); - if (top != q || query_pt_is_vertex) { - points.push_back(top); - } - stack.pop(); + std::vector points; + while(!stack.empty()) { + const Point_2& top = stack.top(); + if (top != q || query_pt_is_vertex) { + points.push_back(top); } + stack.pop(); + } - if(inserted_artificial_starting_vertex) { - points.back() = points[0]; - inserted_artificial_starting_vertex = false; + if(inserted_artificial_starting_vertex) { + points.back() = points[0]; + inserted_artificial_starting_vertex = false; + } + + + // Quick fix for now. Can be done faster + bool is_degenerate = false; + + for(typename std::vector::size_type i = 0; i < points.size()-2;i++){ + if(CGAL::orientation(points[i],points[i+1],points[i+2]) == CGAL::COLLINEAR){ + is_degenerate = true; + break; } - - - - // Quick fix for now. Can be done faster - bool is_degenerate = false; - for(typename std::vector::size_type i = 0; i < points.size()-2;i++){ - if(CGAL::orientation(points[i],points[i+1],points[i+2]) == CGAL::COLLINEAR){ - is_degenerate = true; - break; - } - } - if(is_degenerate){ - //std::cout << is_degenerate << std::endl; - std::vector segments; + } + if(is_degenerate){ + //std::cout << is_degenerate << std::endl; + std::vector segments; - for(typename std::vector::size_type i = 0;i < points.size() - 1; ++i) - { - segments.push_back(Segment_2(points[i], points[i+1])); - } - CGAL::insert(out_arr, segments.begin(), segments.end()); - }else{ - points.pop_back(); - //std::cout << " ordanary " << std::endl; - typename VARR::Vertex_handle v_last, v_first; - v_last = v_first = + for(typename std::vector::size_type i = 0;i < points.size() - 1; ++i) + { + segments.push_back(Segment_2(points[i], points[i+1])); + } + CGAL::insert(out_arr, segments.begin(), segments.end()); + }else{ + points.pop_back(); + //std::cout << " ordanary " << std::endl; + typename VARR::Vertex_handle v_last, v_first; + v_last = v_first = out_arr.insert_in_face_interior(points[0],out_arr.unbounded_face()); - for(unsigned int i = 0; i < points.size()-1; i++){ - if(points[i] < points[(i+1)]){ - v_last = out_arr.insert_from_left_vertex ( - Segment_2(points[i], points[i+1]), v_last - )->target(); - } else { - v_last = out_arr.insert_from_right_vertex( - Segment_2(points[i], points[i+1]), v_last - )->target(); - } - } - out_arr.insert_at_vertices( - Segment_2(points.front(), points.back()), - v_last, v_first - ); + for(unsigned int i = 0; i < points.size()-1; i++){ + if(points[i] < points[(i+1)]){ + v_last = out_arr.insert_from_left_vertex ( + Segment_2(points[i], points[i+1]), v_last + )->target(); + } else { + v_last = out_arr.insert_from_right_vertex( + Segment_2(points[i], points[i+1]), v_last + )->target(); + } } + out_arr.insert_at_vertices( + Segment_2(points.front(), points.back()), + v_last, v_first + ); -// Visibility_2::report_while_handling_needles( -// traits, q, points, out_arr); + } - CGAL_postcondition(out_arr.number_of_isolated_vertices() == 0); - CGAL_postcondition(stack.empty()); + CGAL_postcondition(out_arr.number_of_isolated_vertices() == 0); + CGAL_postcondition(stack.empty()); - Visibility_2::conditional_regularize(out_arr, Regularization_category()); - vertices.clear(); + Visibility_2::conditional_regularize(out_arr, Regularization_category()); + vertices.clear(); - if (out_arr.faces_begin()->is_unbounded()) { - return ++out_arr.faces_begin(); - } - else { - return out_arr.faces_begin(); - } + if (out_arr.faces_begin()->is_unbounded()) { + return ++out_arr.faces_begin(); + } + else { + return out_arr.faces_begin(); + } } /*! Finds a visible vertex from the query point 'q' in 'face' - to start the algorithm from*/ + to start the algorithm from*/ Ccb_halfedge_const_circulator find_visible_start(Face_const_handle face, const Point_2 &q) const { - Location_result result = point_location.ray_shoot_up(q); + Location_result result = point_location.ray_shoot_up(q); - if(const Halfedge_const_handle* e = - boost::get(&(result))) + if(const Halfedge_const_handle* e = + boost::get(&(result))) { - CGAL_assertion((*e)->face() == face); - Point_2 p(q.x(), - traits->compute_y_at_x_2_object()( - Line_2((*e)->source()->point(), - (*e)->target()->point()) , - q.x())); + CGAL_assertion((*e)->face() == face); + Point_2 p(q.x(), + traits->compute_y_at_x_2_object()( + Line_2((*e)->source()->point(), + (*e)->target()->point()) , + q.x())); - vertices.push_back(p); - inserted_artificial_starting_vertex = true; + vertices.push_back(p); + inserted_artificial_starting_vertex = true; - return (*e)->next()->ccb(); + return (*e)->next()->ccb(); } - else if (const Vertex_const_handle* v = - boost::get(&(result))) + else if (const Vertex_const_handle* v = + boost::get(&(result))) { - Halfedge_around_vertex_const_circulator cir = - (*v)->incident_halfedges(); + Halfedge_around_vertex_const_circulator cir = + (*v)->incident_halfedges(); - while(face != cir->face()) { - ++cir; - } - return cir->next()->ccb(); + while(face != cir->face()) { + ++cir; + } + return cir->next()->ccb(); } - else + else { - CGAL_assertion_msg(false, "Should not be reachable."); - return Ccb_halfedge_const_circulator(); + CGAL_assertion_msg(false, "Should not be reachable."); + return Ccb_halfedge_const_circulator(); } } /*! Main method of the algorithm - initializes the stack and variables - and calles the corresponding methods acc. to the algorithm's state; - 'q' - query point; - 'i' - current vertex' index - 'w' - endpoint of ray shot from query point */ + and calles the corresponding methods acc. to the algorithm's state; + 'q' - query point; + 'i' - current vertex' index + 'w' - endpoint of ray shot from query point */ void visibility_region_impl(const Point_2& q) const { Size_type i = 0; Point_2 w; @@ -372,45 +370,45 @@ private: Ray_2 ray_origin( q, vertices[0] ); do { switch(upcase) { - case LEFT: - left(i, w, q); - break; - case RIGHT: - right(i, w, q); - break; - case SCANA: - scana(i, w, q); - break; - case SCANB: - scanb(i, w); - break; - case SCANC: - scanc(i, w); - break; - case SCAND: - scand(i, w); - break; - case FINISH: - break; + case LEFT: + left(i, w, q); + break; + case RIGHT: + right(i, w, q); + break; + case SCANA: + scana(i, w, q); + break; + case SCANB: + scanb(i, w); + break; + case SCANC: + scanc(i, w); + break; + case SCAND: + scand(i, w); + break; + case FINISH: + break; } if ( upcase == LEFT ) { Point_2 s_t = stack.top(); stack.pop(); if (traits->orientation_2_object()(q, vertices[0], stack.top() ) - == RIGHT_TURN - && - traits->orientation_2_object()(q, vertices[0], s_t) - == LEFT_TURN ) - { - Segment_2 seg( stack.top(), s_t ); - if (Object_2 result = Intersect_2()(seg, ray_origin) ) - { - const Point_2 * ipoint = object_cast(&result); - assert( ipoint != NULL ); - s_t = *ipoint; - upcase = SCANB; - } - } + == RIGHT_TURN + && + traits->orientation_2_object()(q, vertices[0], s_t) + == LEFT_TURN ) + { + Segment_2 seg( stack.top(), s_t ); + if (Object_2 result = Intersect_2()(seg, ray_origin) ) + { + const Point_2 * ipoint = object_cast(&result); + assert( ipoint != NULL ); + s_t = *ipoint; + upcase = SCANB; + } + } stack.push( s_t ); } } while(upcase != FINISH); @@ -422,155 +420,155 @@ private: upcase = FINISH; } else { - Point_2 s_t = stack.top(); - stack.pop(); - Point_2 s_t_prev = stack.top(); - stack.push( s_t ); - Orientation orient1 = traits->orientation_2_object()( - q, - vertices[i], - vertices[i+1] ); + Point_2 s_t = stack.top(); + stack.pop(); + Point_2 s_t_prev = stack.top(); + stack.push( s_t ); + Orientation orient1 = traits->orientation_2_object()( + q, + vertices[i], + vertices[i+1] ); - if ( orient1 != RIGHT_TURN ) { - // Case L2 - upcase = LEFT; - stack.push( vertices[i+1] ); - w = vertices[i+1]; - i++; - } else { - Orientation orient2 = traits->orientation_2_object()( - s_t_prev, - vertices[i], - vertices[i+1] ); + if ( orient1 != RIGHT_TURN ) { + // Case L2 + upcase = LEFT; + stack.push( vertices[i+1] ); + w = vertices[i+1]; + i++; + } else { + Orientation orient2 = traits->orientation_2_object()( + s_t_prev, + vertices[i], + vertices[i+1] ); - if ( orient2 == RIGHT_TURN ) { - // Case L3 - upcase = SCANA; - w = vertices[i+1]; - i++; - } else { - // Case L4 - upcase = RIGHT; - w = vertices[i]; - i++; - } - } + if ( orient2 == RIGHT_TURN ) { + // Case L3 + upcase = SCANA; + w = vertices[i+1]; + i++; + } else { + // Case L4 + upcase = RIGHT; + w = vertices[i]; + i++; + } + } } } /*! Scans the stack such that all vertices that were pushed before to the - stack and are now not visible anymore. */ + stack and are now not visible anymore. */ void right(Size_type& i, Point_2& w, const Point_2& q) const { - Point_2 s_j; - Point_2 s_j_prev; - Point_2 u; - int mode = 0; - Orientation orient1, orient2; + Point_2 s_j; + Point_2 s_j_prev; + Point_2 u; + int mode = 0; + Orientation orient1, orient2; - s_j_prev = stack.top(); - orient2 = traits->orientation_2_object()( q, s_j_prev, vertices[i] ); + s_j_prev = stack.top(); + orient2 = traits->orientation_2_object()( q, s_j_prev, vertices[i] ); - while ( stack.size() > 1 ) { - s_j = s_j_prev; - orient1 = orient2; - stack.pop(); - s_j_prev = stack.top(); + while ( stack.size() > 1 ) { + s_j = s_j_prev; + orient1 = orient2; + stack.pop(); + s_j_prev = stack.top(); - orient2 = traits->orientation_2_object()( q, s_j_prev, vertices[i]); - if ( orient1 != LEFT_TURN && orient2 != RIGHT_TURN ) { - mode = 1; - break; - } + orient2 = traits->orientation_2_object()( q, s_j_prev, vertices[i]); + if ( orient1 != LEFT_TURN && orient2 != RIGHT_TURN ) { + mode = 1; + break; + } - Segment_2 seg2( vertices[i-1], vertices[i] ); - Segment_2 seg( s_j_prev, s_j ); - if ( vertices[i-1] != s_j ) - { - Object_2 result = Intersect_2()( seg, seg2 ); - if(result) { - const Point_2 * ipoint = object_cast(&result); - assert( ipoint != NULL ); - u = *ipoint; - mode = 2; - break; - } - } - } + Segment_2 seg2( vertices[i-1], vertices[i] ); + Segment_2 seg( s_j_prev, s_j ); + if ( vertices[i-1] != s_j ) + { + Object_2 result = Intersect_2()( seg, seg2 ); + if(result) { + const Point_2 * ipoint = object_cast(&result); + assert( ipoint != NULL ); + u = *ipoint; + mode = 2; + break; + } + } + } - assert( mode != 0 ); - if ( mode == 1 ) { - orient1 = traits->orientation_2_object()(q, vertices[i], vertices[i+1] ); + assert( mode != 0 ); + if ( mode == 1 ) { + orient1 = traits->orientation_2_object()(q, vertices[i], vertices[i+1] ); - orient2 = traits->orientation_2_object()(vertices[i-1], - vertices[i], - vertices[i+1] ); + orient2 = traits->orientation_2_object()(vertices[i-1], + vertices[i], + vertices[i+1] ); - if ( orient1 == RIGHT_TURN ) { - // Case R1 - // Since the next action is RIGHT, we do not compute the intersection - // of (s_j,s_j_prev) and the ray (query_pt, vertices[i]), - // thus, (s_j,s_j_prev) is not shortcutted, but it is harmless - upcase = RIGHT; - stack.push( s_j ); - w = vertices[i]; - i++; - } else if ( orient2 == RIGHT_TURN ) { - // Case R2 - Ray_2 ray( q, vertices[i] ); - Segment_2 seg( s_j_prev, s_j ); + if ( orient1 == RIGHT_TURN ) { + // Case R1 + // Since the next action is RIGHT, we do not compute the intersection + // of (s_j,s_j_prev) and the ray (query_pt, vertices[i]), + // thus, (s_j,s_j_prev) is not shortcutted, but it is harmless + upcase = RIGHT; + stack.push( s_j ); + w = vertices[i]; + i++; + } else if ( orient2 == RIGHT_TURN ) { + // Case R2 + Ray_2 ray( q, vertices[i] ); + Segment_2 seg( s_j_prev, s_j ); - Object_2 result = Intersect_2()( seg, ray ); - const Point_2 * ipoint = object_cast(&result); + Object_2 result = Intersect_2()( seg, ray ); + const Point_2 * ipoint = object_cast(&result); - assert( ipoint != NULL ); + assert( ipoint != NULL ); - u = *ipoint; - if ( stack.top() != u ) { - stack.push( u ); - } - upcase = LEFT; - stack.push( vertices[i] ); - stack.push( vertices[i+1] ); - w = vertices[i+1]; - i++; - } else { - // Case R3 - Ray_2 ray( q, vertices[i] ); - Segment_2 seg( s_j_prev, s_j ); + u = *ipoint; + if ( stack.top() != u ) { + stack.push( u ); + } + upcase = LEFT; + stack.push( vertices[i] ); + stack.push( vertices[i+1] ); + w = vertices[i+1]; + i++; + } else { + // Case R3 + Ray_2 ray( q, vertices[i] ); + Segment_2 seg( s_j_prev, s_j ); - Object_2 result = Intersect_2()( seg, ray ); - const Point_2 * ipoint = object_cast(&result); + Object_2 result = Intersect_2()( seg, ray ); + const Point_2 * ipoint = object_cast(&result); - assert( ipoint != NULL ); + assert( ipoint != NULL ); - u = *ipoint; - if ( stack.top() != u ) { - stack.push( u ); - } - upcase = SCANC; - w = vertices[i]; - i++; - } - } else if ( mode == 2 ) { - // Case R4 - upcase = SCAND; - w = u; - } + u = *ipoint; + if ( stack.top() != u ) { + stack.push( u ); + } + upcase = SCANC; + w = vertices[i]; + i++; + } + } else if ( mode == 2 ) { + // Case R4 + upcase = SCAND; + w = u; + } } /*! Scans the vertices starting from index 'i' for the first visible vertex - out of the back hidden window */ + out of the back hidden window */ void scana(Size_type& i, Point_2& w, const Point_2& q) const { // Scan v_i, v_i+1, ..., v_n for the first edge to intersect (z, s_t) Point_2 u; Size_type k = scan_edges( i, q, stack.top(), u, true ); Orientation orient1 = - traits->orientation_2_object()(q, vertices[k], vertices[k+1] ); + traits->orientation_2_object()(q, vertices[k], vertices[k+1] ); if ( orient1 == RIGHT_TURN ) { bool fwd = traits-> - collinear_are_ordered_along_line_2_object()(q, stack.top(), u ); + collinear_are_ordered_along_line_2_object()(q, stack.top(), u ); if ( !fwd ) { // Case A1 @@ -616,7 +614,7 @@ private: } /*! Finds the exit from a general front hidden window by finding the first - vertex to the right of the ray defined by the query_point and w*/ + vertex to the right of the ray defined by the query_point and w*/ void scanc(Size_type& i, Point_2& w) const { Point_2 u; Size_type k = scan_edges( i, stack.top(), w, u, false ); @@ -639,13 +637,13 @@ private: } /*! Scan edges v_i,v_{i+1},...,v_n, until find an edge intersecting given ray - or given segment. is_ray = true -> ray, false -> segment. - The intersection point is returned by u */ + or given segment. is_ray = true -> ray, false -> segment. + The intersection point is returned by u */ Size_type scan_edges( Size_type i, - const Point_2& ray_begin, - const Point_2& ray_end, - Point_2& u, - bool is_ray ) const + const Point_2& ray_begin, + const Point_2& ray_end, + Point_2& u, + bool is_ray ) const { Orientation old_orient = RIGHT_TURN; Ray_2 ray( ray_begin, ray_end ); @@ -654,34 +652,34 @@ private: Object_2 result; for ( k = i; k+1 < vertices.size(); k++ ) { Orientation curr_orient = traits->orientation_2_object()( - ray_begin, - ray_end, - vertices[k+1] ); + ray_begin, + ray_end, + vertices[k+1] ); if ( curr_orient != old_orient ) { // Orientation switch, an intersection may occur Segment_2 seg( vertices[k], vertices[k+1] ); if ( is_ray ) { - result = Intersect_2()( seg, ray ); - if(result) - break; + result = Intersect_2()( seg, ray ); + if(result) + break; } else { - result = Intersect_2()( seg, s2 ); - if(result) - break; + result = Intersect_2()( seg, s2 ); + if(result) + break; } } old_orient = curr_orient; - } + } assert( k+1( &result ); if ( ipoint ) { - u = *ipoint; + u = *ipoint; } else { - u = vertices[k+1]; + u = vertices[k+1]; } - return k; + return k; } -}; + }; } // namespace CGAL #endif