BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Boolean_set_operations_2/Gps_on_surface_base_2_impl.h
Go to the documentation of this file.
00001 // Copyright (c) 2005  Tel-Aviv University (Israel).
00002 // All rights reserved.
00003 //
00004 // This file is part of CGAL (www.cgal.org); you may redistribute it under
00005 // the terms of the Q Public License version 1.0.
00006 // See the file LICENSE.QPL distributed with CGAL.
00007 //
00008 // Licensees holding a valid commercial license may use this file in
00009 // accordance with the commercial license agreement provided with the software.
00010 //
00011 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00012 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00013 //
00014 // $URL:
00015 // $Id: 
00016 // 
00017 //
00018 // Author(s)     : Baruch Zukerman <baruchzu@post.tau.ac.il>
00019 //                 Efi Fogel <efif@post.tau.ac.il>
00020 //                 Ophir Setter    <ophir.setter@cs.tau.ac.il>
00021 //                 Guy Zucker <guyzucke@post.tau.ac.il> 
00022 
00023 #ifndef CGAL_GPS_ON_SURFACE_BASE_2_IMPL_H
00024 #define CGAL_GPS_ON_SURFACE_BASE_2_IMPL_H
00025 
00026 #include <CGAL/iterator.h>
00027 #include <CGAL/function_objects.h>
00028 #include <CGAL/circulator.h> 
00029 #include <CGAL/Boolean_set_operations_2/Gps_bfs_scanner.h>
00030 #include <CGAL/Arr_accessor.h>
00031 
00032 #include <queue>
00033 #include <list>
00034 
00035 template <class Traits_, class TopTraits_, class ValidationPolicy>
00036 void Gps_on_surface_base_2<Traits_, TopTraits_,ValidationPolicy>::
00037 construct_polygon(Ccb_halfedge_const_circulator ccb, Polygon_2 & pgn,
00038                   Traits_ * tr)
00039 {
00040   typedef CGAL::Ccb_curve_iterator<Arrangement_on_surface_2>    
00041     Ccb_curve_iterator;
00042   Ccb_curve_iterator begin(ccb, false);
00043   Ccb_curve_iterator end(ccb, true);
00044 
00045   tr->construct_polygon_2_object()(begin, end, pgn);
00046 }
00047 
00048 // The comments below was written after trying to understand what the visitors
00049 // do. There was no comment by the author of this class.
00050 // This class is used afterwards to extract polygons from the representing
00051 // arrangement.
00052 // This scanner is not the same as the Gps_bfs_scanner. In this file, the
00053 // Gps_bfs_scanner is used with Init_faces_visitor to init the faces of the
00054 // representing arrangement. 
00055 // It seems that Gps_bfs_scanner is used for a regular bfs scan on the faces
00056 // of the arrangements, with comparison to Arr_bfs_scanner that cares about
00057 // inner ccbs and outer ccbs (it treats them differently).
00058 // If this is the case, we should unite Gps_bfs_scanner with the regular
00059 // adaptation of arrangement to boost graph.
00060 template <class Arrangement, class OutputIterator>
00061 class Arr_bfs_scanner
00062 {
00063 public:
00064   typedef typename Arrangement::Geometry_traits_2       Gps_traits;
00065   typedef typename Arrangement::Topology_traits         Gps_top_traits;
00066   typedef typename Gps_traits::Polygon_2                Polygon_2;
00067   typedef typename Gps_traits::Polygon_with_holes_2     Polygon_with_holes_2;
00068   typedef typename Arrangement::Ccb_halfedge_const_circulator 
00069     Ccb_halfedge_const_circulator;
00070   typedef typename Arrangement::Face_const_iterator     Face_const_iterator;
00071   typedef typename Arrangement::Halfedge_const_iterator Halfedge_const_iterator;
00072   typedef typename Arrangement::Outer_ccb_const_iterator     
00073     Outer_ccb_const_iterator;
00074   typedef typename Arrangement::Inner_ccb_const_iterator     
00075     Inner_ccb_const_iterator;
00076 
00077 
00078 protected:
00079 
00080   Gps_traits*                            m_traits;
00081   std::queue<Face_const_iterator>        m_holes_q;
00082   std::list<Polygon_2>                   m_pgn_holes;
00083   OutputIterator                         m_oi;
00084 
00085 public:
00086 
00088   Arr_bfs_scanner(Gps_traits* tr, OutputIterator oi) : m_traits(tr), m_oi(oi)
00089   {}
00090                              
00091 
00092   void scan(Arrangement& arr)
00093   {
00094     Face_const_iterator   ubf;
00095     for (ubf = arr.faces_begin(); ubf != arr.faces_end(); ++ubf)
00096     {
00097       if (ubf->number_of_outer_ccbs() != 0)
00098         continue;
00099       if (ubf->visited())
00100         continue;
00101       
00102       Inner_ccb_const_iterator  holes_it;
00103       if (!ubf->contained())
00104       {
00105         ubf->set_visited(true);
00106         for (holes_it = ubf->inner_ccbs_begin();
00107              holes_it != ubf->inner_ccbs_end(); ++holes_it)
00108         {
00109           scan_ccb (*holes_it);
00110         }
00111       }
00112       else
00113       {
00114         // ubf is contained -> unbounded polygon !!
00115         scan_contained_ubf(ubf);
00116         
00117       }
00118       
00119       while(!m_holes_q.empty())
00120       {
00121         Face_const_iterator top_f = m_holes_q.front();
00122         m_holes_q.pop();
00123         top_f->set_visited(true);
00124         for (holes_it = top_f->inner_ccbs_begin();
00125              holes_it != top_f->inner_ccbs_end(); ++holes_it)
00126         {
00127           scan_ccb(*holes_it);
00128         }
00129         
00130         //scan_uncontained_face(top_f->outer_ccb());
00131       }
00132     }
00133 
00134     Face_const_iterator   fit;
00135     for (fit = arr.faces_begin(); fit != arr.faces_end(); ++fit)
00136     {
00137       fit->set_visited(false);
00138     }
00139   }
00140 
00141   OutputIterator output_iterator() const
00142   {
00143     return m_oi;
00144   }
00145 
00146   void scan_ccb(Ccb_halfedge_const_circulator ccb)
00147   {
00148          
00149     Polygon_2 pgn_boundary;
00150     Gps_on_surface_base_2<Gps_traits, Gps_top_traits>::
00151       construct_polygon(ccb, pgn_boundary, m_traits);
00152 
00153     Ccb_halfedge_const_circulator ccb_end = ccb;
00154     do
00155     {
00156       Halfedge_const_iterator he = ccb;
00157       if (!he->twin()->face()->visited())
00158         all_incident_faces(he->twin()->face());
00159       ++ccb;
00160     }
00161     while(ccb != ccb_end);
00162     Polygon_with_holes_2 pgn = 
00163       m_traits->construct_polygon_with_holes_2_object()(pgn_boundary,
00164                                                         m_pgn_holes.begin(),
00165                                                         m_pgn_holes.end());
00166     /*Polygon_with_holes_2 pgn(pgn_boundary,
00167                              m_pgn_holes.begin(),
00168                              m_pgn_holes.end());*/
00169     *m_oi = pgn;
00170     ++m_oi;
00171     m_pgn_holes.clear();
00172   }
00173 
00174   void scan_contained_ubf(Face_const_iterator ubf)
00175   {
00176     CGAL_assertion(ubf->number_of_outer_ccbs() == 0 && ubf->contained());
00177     // ubf is contained -> unbounded polygon !!
00178     all_incident_faces(ubf);
00179     Polygon_2 boundary;
00180     Polygon_with_holes_2 pgn = 
00181       m_traits->construct_polygon_with_holes_2_object()(boundary,
00182                                                         m_pgn_holes.begin(),
00183                                                         m_pgn_holes.end());
00184     /*Polygon_with_holes_2 pgn(boundary,
00185                              m_pgn_holes.begin(),
00186                              m_pgn_holes.end());*/
00187     *m_oi = pgn;
00188     ++m_oi;
00189     m_pgn_holes.clear();
00190   }
00191 
00192 
00193   void all_incident_faces(Face_const_iterator f)
00194   {
00195     CGAL_assertion(!f->visited());
00196     f->set_visited(true);
00197     if (f->number_of_outer_ccbs() != 0)
00198     {
00199       if (!f->contained())
00200       {
00201         for (Outer_ccb_const_iterator oci = f->outer_ccbs_begin();
00202              oci != f->outer_ccbs_end(); ++oci)
00203         {
00204           m_pgn_holes.push_back(Polygon_2());
00205           Gps_on_surface_base_2<Gps_traits, Gps_top_traits>::
00206             construct_polygon(*oci, m_pgn_holes.back(), m_traits);
00207         }
00208         
00209         m_holes_q.push(f);
00210       }
00211 
00212     
00213       for (Outer_ccb_const_iterator oci = f->outer_ccbs_begin();
00214            oci != f->outer_ccbs_end(); ++oci)
00215       {
00216         Ccb_halfedge_const_circulator ccb_end = *oci;
00217         Ccb_halfedge_const_circulator ccb_circ = ccb_end;
00218         do
00219         { 
00220           //get the current halfedge on the face boundary
00221           Halfedge_const_iterator he  = ccb_circ;
00222           Face_const_iterator new_f = he->twin()->face();
00223           if (!new_f->visited())
00224           {
00225             all_incident_faces(new_f);
00226           }
00227           ++ccb_circ;
00228         }
00229         while(ccb_circ != ccb_end);
00230       }
00231     }
00232 
00233     if (f->contained())
00234     {
00235       Inner_ccb_const_iterator hit;
00236       for(hit = f->inner_ccbs_begin(); hit != f->inner_ccbs_end(); ++hit)
00237       {
00238         Ccb_halfedge_const_circulator ccb_of_hole = *hit;
00239         Halfedge_const_iterator he = ccb_of_hole;
00240         if (is_single_face(ccb_of_hole))
00241         {
00242           CGAL_assertion(!he->twin()->face()->contained());
00243          
00244           m_pgn_holes.push_back(Polygon_2());
00245           Gps_on_surface_base_2<Gps_traits, Gps_top_traits>::
00246             construct_polygon(he->twin()->face()->outer_ccb(),
00247                               m_pgn_holes.back(), m_traits);
00248           m_holes_q.push(he->twin()->face());
00249         }
00250         else
00251         {
00252           Ccb_halfedge_const_circulator ccb_end = ccb_of_hole;
00253           do
00254           {
00255             Halfedge_const_iterator he = ccb_of_hole;
00256             if (!he->twin()->face()->visited())
00257               all_incident_faces(he->twin()->face());
00258             ++ccb_of_hole;
00259           }
00260           while(ccb_of_hole != ccb_end);
00261         }
00262       }
00263     }
00264   }
00265 
00266   bool is_single_face(Ccb_halfedge_const_circulator ccb)
00267   {
00268     Ccb_halfedge_const_circulator ccb_end = ccb;
00269     Ccb_halfedge_const_circulator ccb_circ = ccb_end;
00270     Halfedge_const_iterator he = ccb;
00271     Face_const_iterator curr_f = he->twin()->face();
00272     do
00273     { 
00274       //get the current halfedge on the face boundary
00275       Halfedge_const_iterator he  = ccb_circ;
00276       if (he->twin()->face() != curr_f)
00277         return false;
00278       if (he->twin()->target()->degree() != 2)
00279         return false;
00280       ++ccb_circ;
00281     }
00282     while(ccb_circ != ccb_end);
00283     return true;
00284   }
00285 };
00286 
00287 
00288 template <class Arrangement>
00289 class Init_faces_visitor
00290 {
00291   typedef typename Arrangement::Face_iterator             Face_iterator;
00292   typedef typename Arrangement::Halfedge_iterator         Halfedge_iterator;
00293  
00294 public:
00295 
00297 
00304   void discovered_face(Face_iterator old_f, 
00305                        Face_iterator new_f, 
00306                        Halfedge_iterator /*he*/)
00307   {
00308     new_f->set_contained(!old_f->contained());
00309   }
00310 };
00311 
00313 
00319 template <class Traits_, class TopTraits_, class ValidationPolicy>
00320 void Gps_on_surface_base_2<Traits_, TopTraits_,ValidationPolicy>::
00321 _insert(const Polygon_2& pgn, Arrangement_on_surface_2 & arr)
00322 {
00323   typedef Arr_accessor<Arrangement_on_surface_2>                  Arr_accessor;
00324 
00325   Arr_accessor  accessor(arr);
00326   Compare_endpoints_xy_2  cmp_ends = m_traits->compare_endpoints_xy_2_object();
00327 
00328   std::pair<Curve_const_iterator, Curve_const_iterator> itr_pair =
00329     m_traits->construct_curves_2_object()(pgn);
00330 
00331   if (itr_pair.first == itr_pair.second)
00332     return;
00333 
00334   Curve_const_iterator curr = itr_pair.first;
00335   Curve_const_iterator end  = itr_pair.second;
00336 
00337   const Arr_parameter_space  ps_x =
00338     m_traits_adaptor.parameter_space_in_x_2_object()(*curr, ARR_MIN_END);
00339   const Arr_parameter_space  ps_y =
00340     m_traits_adaptor.parameter_space_in_y_2_object()(*curr, ARR_MIN_END);
00341   
00342   Object obj_f;
00343   if ((ps_x == ARR_INTERIOR) && (ps_y == ARR_INTERIOR))
00344   {
00345     Point_location pl(arr);
00346     obj_f = pl.locate(m_traits->construct_min_vertex_2_object()(*curr));
00347   }
00348   else
00349   {
00350     obj_f = accessor.locate_curve_end(*curr, ARR_MIN_END, ps_x, ps_y);
00351   }
00352 
00353   Face_const_handle const_f;
00354   // face should not be contained as the pgn is completly disjoint of the
00355   // arrangement.
00356   CGAL_assertion(CGAL::assign(const_f, obj_f) && !const_f->contained());
00357   CGAL::assign(const_f, obj_f);
00358   Face_iterator f = arr.non_const_handle(const_f);
00359   
00360   Halfedge_handle first_he = 
00361     arr.insert_in_face_interior(*curr, f);
00362   //first_he is directed from left to right (see insert_in_face_interior)
00363   
00364   Halfedge_handle curr_he;
00365   if (cmp_ends(*curr) == CGAL::SMALLER)
00366   {
00367     // curr curve and first_he have the same direction
00368     curr_he = first_he;
00369     first_he = first_he->twin();
00370   }
00371   else
00372   {
00373     // curr curve and first_he have opposite directions
00374     CGAL_assertion(cmp_ends(*curr) == CGAL::LARGER);
00375     curr_he = first_he->twin();
00376   }
00377 
00378   Curve_const_iterator temp = curr;
00379   ++temp;
00380   if (temp == end) // a polygon with circular arcs may have only
00381                   // two edges (full circle for example)
00382   {
00383     /*Halfedge_handle he = 
00384       arr.insert_at_vertices(*temp, curr_he, first_he);*/
00385     bool new_face_created;
00386     Halfedge_handle he = accessor.insert_at_vertices_ex (*temp,
00387                                                          curr_he,
00388                                                          first_he,
00389                                                          cmp_ends(*temp),
00390                                                          new_face_created);
00391     CGAL_assertion(new_face_created); 
00392     CGAL_assertion((he->face() != he->twin()->face()));
00393     
00394     he->face()->set_contained(true);
00395     return;
00396   }
00397 
00398   //The polygon has 3 or more edges
00399   Curve_const_iterator last = end;
00400   --last;
00401   for(++curr ; curr != last; ++curr)
00402   {
00403     const X_monotone_curve_2& curr_cv = *curr;
00404     if (cmp_ends(curr_cv) == CGAL::SMALLER)
00405       curr_he = arr.insert_from_left_vertex(curr_cv, curr_he);
00406     else
00407     {
00408       CGAL_assertion(cmp_ends(curr_cv) == CGAL::LARGER);
00409       curr_he = arr.insert_from_right_vertex(curr_cv, curr_he);
00410     }
00411   }
00412 
00413   const X_monotone_curve_2& last_cv = *last;
00414   /*Halfedge_handle last_he =
00415     arr.insert_at_vertices(last_cv, curr_he, first_he); */
00416   bool new_face_created;
00417   Halfedge_handle last_he = 
00418     accessor.insert_at_vertices_ex (last_cv,
00419                                     curr_he,
00420                                     first_he,
00421                                     cmp_ends(last_cv),
00422                                     new_face_created);
00423   CGAL_assertion(new_face_created); 
00424   CGAL_assertion((last_he->face() != last_he->twin()->face()));
00425   
00426   last_he->face()->set_contained(true);
00427 }
00428 
00429 
00430 template <class Traits_, class TopTraits_, class ValidationPolicy>
00431   template<class PolygonIter >
00432   void Gps_on_surface_base_2<Traits_, TopTraits_, ValidationPolicy>::
00433   insert(PolygonIter p_begin, PolygonIter p_end)
00434 {
00435   typename std::iterator_traits<PolygonIter>::value_type pgn;
00436   //check validity of all polygons    
00437   for( ; p_begin != p_end; ++p_begin)
00438   {
00439     ValidationPolicy::is_valid(*p_begin, *m_traits);
00440   }
00441 
00442   _insert(p_begin, p_end, pgn);
00443 }
00444 
00445 template <class Traits_, class TopTraits_, class ValidationPolicy>
00446   template<class PolygonIter, class PolygonWithHolesIter>
00447   void Gps_on_surface_base_2<Traits_, TopTraits_, ValidationPolicy>::
00448   insert(PolygonIter p_begin, PolygonIter p_end,
00449          PolygonWithHolesIter pwh_begin, PolygonWithHolesIter pwh_end)
00450 {
00451   typedef std::list<X_monotone_curve_2>                  XCurveList;
00452   typedef Init_faces_visitor<Arrangement_on_surface_2>              My_visitor;
00453   typedef Gps_bfs_scanner<Arrangement_on_surface_2, My_visitor>     Arr_bfs_scanner;
00454 
00455   XCurveList xcurve_list;
00456   
00457   for( ; p_begin != p_end; ++p_begin)
00458   {
00459     ValidationPolicy::is_valid(*p_begin, *m_traits);
00460     _construct_curves(*p_begin, std::back_inserter(xcurve_list));
00461   }
00462 
00463   bool is_unbounded = false;
00464   for( ; pwh_begin != pwh_end; ++pwh_begin)
00465   {
00466     ValidationPolicy::is_valid(*pwh_begin, *m_traits);
00467     is_unbounded = (is_unbounded || m_traits->construct_is_unbounded_object()(*pwh_begin));
00468     // is_unbounded = (is_unbounded || pwh_begin->is_unbounded());
00469     _construct_curves(*pwh_begin, std::back_inserter(xcurve_list));
00470   }
00471   insert_non_intersecting_curves(*m_arr, xcurve_list.begin(), xcurve_list.end());
00472 
00473   if (is_unbounded)
00474   {
00475     for (Face_iterator fit = m_arr->faces_begin();
00476          fit != m_arr->faces_end(); ++fit)
00477     {
00478       if (fit->number_of_outer_ccbs() == 0)
00479         fit->set_contained(true);
00480     }
00481   }
00482 
00483   My_visitor v;
00484   Arr_bfs_scanner scanner(v);
00485   scanner.scan(*m_arr);
00486   _reset_faces(m_arr);
00487 }
00488 
00489 //insert a range of simple polygons to the arrangement
00490 template <class Traits_, class TopTraits_, class ValidationPolicy>
00491   template<class PolygonIter>
00492   void Gps_on_surface_base_2<Traits_, TopTraits_, ValidationPolicy>::
00493   _insert(PolygonIter p_begin, PolygonIter p_end, Polygon_2 & /*pgn*/)
00494 {  
00495   for(PolygonIter pitr = p_begin; pitr != p_end; ++pitr)
00496   {
00497     this->_insert(*pitr, *m_arr);
00498   }
00499 }
00500 
00501 template <class Traits_, class TopTraits_, class ValidationPolicy>
00502   template<class PolygonIter>
00503   void Gps_on_surface_base_2<Traits_, TopTraits_, ValidationPolicy>::
00504   _insert(PolygonIter p_begin, PolygonIter p_end, Polygon_with_holes_2 & /*pgn*/)
00505 {  
00506   typedef std::list<X_monotone_curve_2>                  XCurveList;
00507   typedef Init_faces_visitor<Arrangement_on_surface_2>              My_visitor;
00508   typedef Gps_bfs_scanner<Arrangement_on_surface_2, My_visitor>     Arr_bfs_scanner;
00509 
00510   XCurveList xcurve_list;
00511   bool is_unbounded = false;
00512   for( ; p_begin != p_end; ++p_begin)
00513   {
00514     // is_unbounded = (is_unbounded || p_begin->is_unbounded());
00515     is_unbounded = (is_unbounded || m_traits->construct_is_unbounded_object()(*p_begin));  
00516     _construct_curves(*p_begin, std::back_inserter(xcurve_list));
00517 
00518   }
00519   insert_non_intersecting_curves(*m_arr, xcurve_list.begin(), xcurve_list.end());
00520 
00521   if (is_unbounded)
00522   {
00523     for (Face_iterator fit = m_arr->faces_begin();
00524          fit != m_arr->faces_end(); ++fit)
00525     {
00526       if (fit->number_of_outer_ccbs() == 0)
00527         fit->set_contained(true);
00528     }
00529   }
00530 
00531   My_visitor v;
00532   Arr_bfs_scanner scanner(v);
00533   scanner.scan(*m_arr);
00534   _reset_faces(m_arr);
00535 }
00536 
00537 //insert non-sipmle poloygons with holes (non incident edges may have
00538 // common vertex,  but they dont intersect at their interior
00539 template <class Traits_, class TopTraits_, class ValidationPolicy>
00540   void Gps_on_surface_base_2<Traits_, TopTraits_, ValidationPolicy>::
00541   _insert(const Polygon_with_holes_2 & pgn, Arrangement_on_surface_2 & arr)
00542 {
00543  // inner function not exposed to user - no validation 
00544  // ValidationPolicy::is_valid(pgn, *m_traits);
00545 
00546   typedef std::list<X_monotone_curve_2>                  XCurveList;
00547   typedef Init_faces_visitor<Arrangement_on_surface_2>          My_visitor;
00548   typedef Gps_bfs_scanner<Arrangement_on_surface_2, My_visitor> Arr_bfs_scanner;
00549 
00550   XCurveList xcurve_list;
00551   _construct_curves(pgn, std::back_inserter(xcurve_list));
00552   insert_non_intersecting_curves(arr, xcurve_list.begin(), xcurve_list.end());
00553 
00554   //if (pgn.is_unbounded())
00555   if (m_traits->construct_is_unbounded_object()(pgn))     
00556   {
00557     for (Face_iterator fit = arr.faces_begin(); 
00558          fit != arr.faces_end(); ++fit)
00559     {
00560       if (fit->number_of_outer_ccbs() == 0)
00561         fit->set_contained(true);
00562     }
00563   }
00564 
00565   My_visitor v;
00566   Arr_bfs_scanner scanner(v);
00567   scanner.scan(arr);
00568   _reset_faces(&arr);
00569 }
00570 
00571 template <class Traits_, class TopTraits_, class ValidationPolicy>
00572   template <class OutputIterator>
00573   void 
00574   Gps_on_surface_base_2<Traits_, TopTraits_, ValidationPolicy>::
00575   _construct_curves(const Polygon_2 & pgn, OutputIterator oi)
00576 {
00577   std::pair<Curve_const_iterator,
00578     Curve_const_iterator> itr_pair =
00579     m_traits->construct_curves_2_object()(pgn);
00580   std::copy (itr_pair.first, itr_pair.second, oi);
00581 }
00582 
00583 template <class Traits_, class TopTraits_, class ValidationPolicy>
00584   template <class OutputIterator>
00585   void Gps_on_surface_base_2<Traits_, TopTraits_, ValidationPolicy>::
00586   _construct_curves(const Polygon_with_holes_2 & pgn, OutputIterator oi)
00587 {
00588   //if (!pgn.is_unbounded())
00589   if (!m_traits->construct_is_unbounded_object()(pgn))
00590   {
00591     const Polygon_2& pgn_boundary = m_traits->construct_outer_boundary_object ()(pgn);
00592     std::pair<Curve_const_iterator,
00593       Curve_const_iterator> itr_pair = 
00594       m_traits->construct_curves_2_object()(pgn_boundary);
00595     std::copy (itr_pair.first, itr_pair.second, oi);
00596   }
00597   std::pair<GP_Holes_const_iterator, GP_Holes_const_iterator> hpair = 
00598     m_traits->construct_holes_object()(pgn);
00599   GP_Holes_const_iterator hit;
00600   for (hit = hpair.first; hit != hpair.second; ++hit)
00601   {
00602     const Polygon_2& pgn_hole = *hit;
00603     std::pair<Curve_const_iterator,
00604       Curve_const_iterator> itr_pair =
00605       m_traits->construct_curves_2_object()(pgn_hole);
00606     std::copy (itr_pair.first, itr_pair.second, oi);
00607   }
00608 }
00609 
00610 template <class Traits_, class TopTraits_, class ValidationPolicy>
00611   template <class OutputIterator>
00612   OutputIterator
00613   Gps_on_surface_base_2<Traits_, TopTraits_, ValidationPolicy>::
00614   polygons_with_holes(OutputIterator out) const
00615 {
00616   typedef Arr_bfs_scanner<Arrangement_on_surface_2, OutputIterator>     Arr_bfs_scanner;
00617   Arr_bfs_scanner scanner(this->m_traits, out);
00618   scanner.scan(*(this->m_arr));
00619   return (scanner.output_iterator());
00620 }
00621 
00622 
00623 template <class Traits_, class TopTraits_, class ValidationPolicy>
00624   typename Gps_on_surface_base_2<Traits_, TopTraits_, ValidationPolicy>::Size 
00625   Gps_on_surface_base_2<Traits_, TopTraits_, ValidationPolicy>::
00626   number_of_polygons_with_holes() const
00627 {
00628  
00629   typedef Arr_bfs_scanner<Arrangement_on_surface_2, Counting_output_iterator>
00630     Arr_bfs_scanner;
00631   //counting_output_operator CTOR reqires a parameter  
00632   std::size_t *cc = new size_t();  
00633   Arr_bfs_scanner scanner(this->m_traits, Counting_output_iterator(cc));
00634   scanner.scan(*(this->m_arr));
00635   return (scanner.output_iterator().current_counter());
00636 }
00637 
00638 
00639 template <class Traits_, class TopTraits_, class ValidationPolicy>
00640   bool Gps_on_surface_base_2<Traits_, TopTraits_, ValidationPolicy>::
00641   locate(const Point_2& q, Polygon_with_holes_2& pgn) const
00642 {
00643   Point_location pl(*m_arr);
00644 
00645   Object obj = pl.locate(q);
00646   Face_const_iterator f;
00647   if (CGAL::assign(f, obj))
00648   {
00649     if (!f->contained())
00650       return false;
00651   }
00652   else
00653   {
00654     Halfedge_const_handle he;
00655     if (CGAL::assign(he, obj))
00656     {
00657       if (he->face()->contained())
00658         f = he->face();
00659       else
00660       {
00661         CGAL_assertion(he->twin()->face()->contained());
00662         f = he->twin()->face();
00663       }
00664     }
00665     else
00666     {
00667       Vertex_const_handle v;
00668       CGAL_assertion(CGAL::assign(v, obj));
00669       CGAL::assign(v, obj);
00670       Halfedge_around_vertex_const_circulator hav = v->incident_halfedges();
00671       Halfedge_const_handle he = hav;
00672       if (he->face()->contained())
00673         f = he->face();
00674       else
00675       {
00676         CGAL_assertion(he->twin()->face()->contained());
00677         f = he->twin()->face();
00678       }
00679     }
00680   }
00681 
00682   typedef Oneset_iterator<Polygon_with_holes_2>    OutputItr;
00683   typedef Arr_bfs_scanner<Arrangement_on_surface_2, OutputItr>     Arr_bfs_scanner;
00684 
00685   OutputItr oi (pgn);
00686   Arr_bfs_scanner scanner(this->m_traits, oi);
00687   
00688   
00689   Ccb_halfedge_const_circulator ccb_of_pgn = get_boundary_of_polygon(f);
00690   this->_reset_faces();
00691   if (ccb_of_pgn == Ccb_halfedge_const_circulator()) 
00692   {
00693     // the polygon has no boundary
00694 
00695     // f is unbounded 
00696     for (Face_iterator fit = m_arr->faces_begin(); fit != m_arr->faces_end();
00697          ++fit)
00698     {
00699       if (fit->number_of_outer_ccbs() == 0)
00700         scanner.scan_contained_ubf(fit);
00701     }
00702   }
00703   else
00704   {
00705     Halfedge_const_handle he_of_pgn = ccb_of_pgn;
00706     this->_reset_faces();
00707     he_of_pgn->face()->set_visited(true);
00708     scanner.scan_ccb(ccb_of_pgn);
00709   }
00710 
00711   this->_reset_faces();
00712   return true;
00713 }
00714 
00715 template <class Traits_, class TopTraits_, class ValidationPolicy>
00716   typename Gps_on_surface_base_2<Traits_, TopTraits_, ValidationPolicy>::Ccb_halfedge_const_circulator
00717   Gps_on_surface_base_2<Traits_, TopTraits_, ValidationPolicy>::
00718   get_boundary_of_polygon(Face_const_iterator f) const
00719 {
00720   CGAL_assertion(!f->visited());
00721   f->set_visited(true);
00722   
00723   if (f->number_of_outer_ccbs() == 0) // (f->is_unbounded())
00724   {
00725     return Ccb_halfedge_const_circulator();
00726   }
00727 
00728   // We assume that a polygon has only one outer_ccb. This code does not handle
00729   // the case where there are more than 1 outer ccbs. If this is the case, we
00730   // need to devise a method to convert the outer ccbs to inner ccbs so we 
00731   // will have only one outer ccb.
00732   if (f->number_of_outer_ccbs() > 1)
00733     CGAL_error_msg("Not implemented yet.");
00734 
00735         // Some compilers (VC 9) do not like that we directly access the ccb_circ. So we have 
00736         // to pass through the iterator.  
00737   Outer_ccb_const_iterator oci_temp = f->outer_ccbs_begin();
00738   Ccb_halfedge_const_circulator ccb_end = *oci_temp;
00739   Ccb_halfedge_const_circulator ccb_circ = ccb_end;
00740   do
00741   { 
00742     //get the current halfedge on the face boundary
00743     Halfedge_const_iterator he  = ccb_circ;
00744     Face_const_iterator new_f = he->twin()->face();
00745     if (!new_f->visited())
00746     {
00747       if (is_hole_of_face(new_f, he) && !new_f->contained())
00748         return (he->twin());
00749       return (get_boundary_of_polygon(new_f));
00750     }
00751     ++ccb_circ;
00752   }
00753   while(ccb_circ != ccb_end);
00754   CGAL_error();
00755   return Ccb_halfedge_const_circulator();
00756   
00757 }
00758 
00759 template <class Traits_, class TopTraits_, class ValidationPolicy>
00760   bool Gps_on_surface_base_2<Traits_, TopTraits_, ValidationPolicy>::
00761   is_hole_of_face(Face_const_handle f, Halfedge_const_handle he) const
00762 {
00763   Inner_ccb_const_iterator   holes_it;
00764   for (holes_it = f->inner_ccbs_begin(); 
00765        holes_it != f->inner_ccbs_end(); ++holes_it)
00766   {
00767     Ccb_halfedge_const_circulator ccb = *holes_it;
00768     Ccb_halfedge_const_circulator ccb_end = ccb;
00769     do
00770     {
00771       Halfedge_const_handle he_inside_hole = ccb;
00772       he_inside_hole = he_inside_hole->twin();
00773       if (he == he_inside_hole)
00774         return true;
00775 
00776       ++ccb;
00777     }
00778     while(ccb != ccb_end);
00779   }
00780 
00781   return false;
00782 }
00783 
00784 #endif // CGAL_GPS_UTILS_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines