BWAPI
|
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