BWAPI
|
00001 00002 // Copyright (c) 2005 Tel-Aviv University (Israel). 00003 // All rights reserved. 00004 // 00005 // This file is part of CGAL (www.cgal.org); you may redistribute it under 00006 // the terms of the Q Public License version 1.0. 00007 // See the file LICENSE.QPL distributed with CGAL. 00008 // 00009 // Licensees holding a valid commercial license may use this file in 00010 // accordance with the commercial license agreement provided with the software. 00011 // 00012 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00013 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00014 // 00015 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Arrangement_on_surface_2/include/CGAL/Arrangement_2/Arrangement_on_surface_2_global.h $ 00016 // $Id: Arrangement_on_surface_2_global.h 50366 2009-07-05 12:56:48Z efif $ 00017 // 00018 // 00019 // Author(s) : Ron Wein <wein@post.tau.ac.il> 00020 // Baruch Zukerman <baruchzu@post.tau.ac.il> 00021 // Efi Fogel <efif@post.tau.ac.il> 00022 // 00023 #ifndef CGAL_ARRANGEMENT_ON_SURFACE_2_GLOBAL_H 00024 #define CGAL_ARRANGEMENT_ON_SURFACE_2_GLOBAL_H 00025 00030 #include <boost/type_traits.hpp> 00031 #include <boost/mpl/if.hpp> 00032 00033 #include <CGAL/Arrangement_on_surface_2.h> 00034 #include <CGAL/Arr_accessor.h> 00035 #include <CGAL/Basic_sweep_line_2.h> 00036 #include <CGAL/Sweep_line_2.h> 00037 #include <CGAL/Arrangement_zone_2.h> 00038 #include <CGAL/Arrangement_2/Arr_compute_zone_visitor.h> 00039 #include <CGAL/Arrangement_2/Arr_do_intersect_zone_visitor.h> 00040 #include <CGAL/Arrangement_2/Arr_traits_adaptor_2.h> 00041 #include <CGAL/Sweep_line_2/Sweep_line_2_utils.h> 00042 #include <CGAL/Sweep_line_2/Sweep_line_2_visitors.h> 00043 00044 #include <boost/type_traits.hpp> 00045 00046 #include <list> 00047 00048 CGAL_BEGIN_NAMESPACE 00049 00050 //----------------------------------------------------------------------------- 00051 // Insert a curve into the arrangement (incremental insertion). 00052 // The inserted curve may intersect the existing arrangement. 00053 // 00054 // The last parameter is used to resolve ambiguity between this function and 00055 // do_intersect of X_monotone_curve_2 in case that X_monotone_curve_2 and 00056 // Curve_2 are the same class. 00057 // The last parameter should be boost::false_type but we used a 00058 // workaround since it didn't compile in FC3_g++-3.4.4 with the error of: 00059 // 00060 // error: no matching function for call to `do_intersect(Arrangement_2<>&, 00061 // const Arr_segment_2&, const Arr_walk_along_line_point_location<>&, 00062 // mpl_::bool_< true>)' 00063 // 00064 template <class GeomTraits, class TopTraits, class PointLocation, 00065 class ZoneVisitor> 00066 void insert (Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 00067 const typename GeomTraits::Curve_2& c, 00068 const PointLocation& pl, ZoneVisitor &visitor, 00069 boost::is_same<int, double>::type) 00070 { 00071 typedef Arrangement_on_surface_2<GeomTraits, TopTraits> Arr; 00072 typedef ZoneVisitor Zone_visitor; 00073 00074 // Obtain an arrangement accessor. 00075 Arr_accessor<Arr> arr_access (arr); 00076 00077 // Initialize a zone-computation object an a visitor that performs the 00078 // incremental insertion. 00079 Arrangement_zone_2<Arr, Zone_visitor> arr_zone (arr, &visitor); 00080 00081 // Break the input curve into x-monotone subcurves and isolated points. 00082 std::list<CGAL::Object> x_objects; 00083 std::list<CGAL::Object>::const_iterator obj_iter; 00084 const typename GeomTraits::X_monotone_curve_2 *x_curve; 00085 const typename GeomTraits::Point_2 *iso_p; 00086 00087 arr.geometry_traits()->make_x_monotone_2_object() 00088 (c, std::back_inserter (x_objects)); 00089 00090 // Insert each x-monotone curve into the arrangement. 00091 for (obj_iter = x_objects.begin(); obj_iter != x_objects.end(); ++obj_iter) 00092 { 00093 // Act according to the type of the current object. 00094 x_curve = 00095 object_cast<typename GeomTraits::X_monotone_curve_2> (&(*obj_iter)); 00096 00097 if (x_curve != NULL) 00098 { 00099 // Inserting an x-monotone curve: 00100 // Initialize the zone-computation object with the given curve. 00101 arr_zone.init (*x_curve, pl); 00102 00103 // Notify the arrangement observers that a global operation is about to 00104 // take place. 00105 arr_access.notify_before_global_change(); 00106 00107 // Insert the current x-monotone curve into the arrangement. 00108 arr_zone.compute_zone(); 00109 00110 // Notify the arrangement observers that the global operation has been 00111 // completed. 00112 arr_access.notify_after_global_change(); 00113 } 00114 else 00115 { 00116 iso_p = object_cast<typename GeomTraits::Point_2> (&(*obj_iter)); 00117 CGAL_assertion (iso_p != NULL); 00118 00119 // Inserting a point into the arrangement: 00120 insert_point (arr, *iso_p, pl); 00121 } 00122 } 00123 } 00124 00125 //----------------------------------------------------------------------------- 00126 // Insert an x-monotone curve into the arrangement (incremental insertion). 00127 // The inserted x-monotone curve may intersect the existing arrangement. 00128 // 00129 // The last parameter is used to resolve ambiguity between this function and 00130 // do_intersect of Curve_2 in case that X_monotone_curve_2 and Curve_2 are the 00131 // same class. The last parameter should be boost::true_type but we used a 00132 // workaround since it didn't compile in FC3_g++-3.4.4 with the error of: 00133 // 00134 // error: no matching function for call to `do_intersect(Arrangement_2<>&, 00135 // const Arr_segment_2&, const Arr_walk_along_line_point_location<>&, 00136 // mpl_::bool_< true>)' 00137 // 00138 // 00139 template <class GeomTraits, class TopTraits, class PointLocation, 00140 class ZoneVisitor> 00141 void insert(Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 00142 const typename GeomTraits::X_monotone_curve_2& c, 00143 const PointLocation& pl, ZoneVisitor &visitor, 00144 boost::is_same<int, int>::type) 00145 { 00146 typedef Arrangement_on_surface_2<GeomTraits, TopTraits> Arr; 00147 typedef ZoneVisitor Zone_visitor; 00148 00149 // Obtain an arrangement accessor. 00150 Arr_accessor<Arr> arr_access (arr); 00151 00152 // Initialize a zone-computation object an a visitor that performs the 00153 // incremental insertion. 00154 Arrangement_zone_2<Arr, Zone_visitor> arr_zone (arr, &visitor); 00155 00156 // Initialize the zone-computation object with the given curve. 00157 00158 /* Needs to be deleted!!! 00159 { 00160 std::cout << std::endl; 00161 std::cout << "xxxxxxxxxxxx" << std::endl; 00162 std::cout << "c: " << c << std::endl; 00163 std::cout << std::endl; 00164 typename Arr::Vertex_const_iterator vit; 00165 std::cout << arr.number_of_vertices() << " vertices:" << std::endl; 00166 for (vit = arr.vertices_begin(); vit != arr.vertices_end(); ++vit) 00167 { 00168 std::cout << "(" << vit->point() << ")"; 00169 if (vit->is_isolated()) 00170 std::cout << " - Isolated." << std::endl; 00171 else 00172 std::cout << " - degree " << vit->degree() << std::endl; 00173 } 00174 std::cout << std::endl; 00175 std::cout << "xxxxxxxxxxxx" << std::endl; 00176 } 00177 */ 00178 arr_zone.init (c, pl); 00179 00180 // Notify the arrangement observers that a global operation is about to 00181 // take place. 00182 arr_access.notify_before_global_change(); 00183 00184 // Insert the x-monotone curve into the arrangement. 00185 arr_zone.compute_zone(); 00186 00187 // Notify the arrangement observers that the global operation has been 00188 // completed. 00189 arr_access.notify_after_global_change(); 00190 } 00191 00192 //----------------------------------------------------------------------------- 00193 // Common interface for the insert of the Curve_2 and X_monotone_curve_2 00194 template <class GeomTraits, class TopTraits, class Curve, class PointLocation, 00195 class ZoneVisitor> 00196 void insert (Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 00197 const Curve& c, const PointLocation& pl, ZoneVisitor &visitor) 00198 { 00199 typedef typename GeomTraits::X_monotone_curve_2 X_monotone_curve_2; 00200 00201 typedef typename boost::is_same<Curve, X_monotone_curve_2>::type 00202 Is_x_monotone; 00203 00204 insert(arr, c, pl, visitor, Is_x_monotone()); 00205 } 00206 00207 // In some compilers there is a template deduction disambiguity between this 00208 // function and the function receiving two InputIterator. 00209 // For now the solution is to add a dummy variable at the end (referring 00210 // to point-location). Maybe the proper solution is to use boost::enable_if 00211 // together with appropriate tag. 00212 template <class GeomTraits, class TopTraits, class Curve, class PointLocation> 00213 void insert (Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 00214 const Curve& c, const PointLocation& pl, 00215 typename PointLocation::Point_2*) 00216 { 00217 typedef Arrangement_on_surface_2<GeomTraits, TopTraits> Arr; 00218 typedef typename TopTraits::Zone_insertion_visitor Zone_visitor; 00219 00220 Zone_visitor visitor; 00221 insert (arr, c, pl, visitor); 00222 } 00223 00224 //----------------------------------------------------------------------------- 00225 // Insert a curve/x-monotone curve into the arrangement (incremental 00226 // insertion). 00227 // The inserted x-monotone curve may intersect the existing arrangement. 00228 // Overloaded version with no point location object - using the default point 00229 // location. 00230 // 00231 template <class GeomTraits, class TopTraits, class Curve> 00232 void insert(Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 00233 const Curve& c) 00234 { 00235 // Create a default point-location object and use it to insert the curve. 00236 typename TopTraits::Default_point_location_strategy def_pl (arr); 00237 00238 insert (arr, c, def_pl); 00239 } 00240 00246 template <typename GeomTraits, typename TopTraits, typename InputIterator> 00247 void insert_empty(Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 00248 InputIterator begin_xcurves, InputIterator end_xcurves) 00249 { 00250 typedef typename TopTraits::Sweep_line_construction_visitor 00251 Construct_visitor; 00252 typedef typename Construct_visitor::Traits_2 Construct_traits; 00253 00254 const GeomTraits * geom_traits = arr.geometry_traits(); 00255 Construct_visitor visitor(&arr); 00256 00257 /* We would like to avoid copy construction of the geometry traits class. 00258 * Copy construction is undesired, because it may results with data 00259 * duplication or even data loss. 00260 * 00261 * If the type Construct_visitor::Traits_2 is the same as the type 00262 * GeomTraits, use a reference to GeomTraits to avoid constructing a new one. 00263 * Otherwise, instantiate a local variable of the former and provide 00264 * the later as a single parameter to the constructor. 00265 * 00266 * Use the form 'A a(*b);' and not ''A a = b;' to handle the case where A has 00267 * only an implicit constructor, (which takes *b as a parameter). 00268 */ 00269 typename boost::mpl::if_<boost::is_same<GeomTraits, Construct_traits>, 00270 const Construct_traits&, Construct_traits>::type 00271 traits(*geom_traits); 00272 00273 // Define a sweep-line instance and perform the sweep: 00274 Sweep_line_2<typename Construct_visitor::Traits_2, Construct_visitor, 00275 typename Construct_visitor::Subcurve, 00276 typename Construct_visitor::Event> 00277 sweep_line(&traits, &visitor); 00278 sweep_line.sweep(begin_xcurves, end_xcurves); 00279 } 00280 00289 template <typename GeomTraits, typename TopTraits, 00290 typename XcInputIterator, typename PInputIterator> 00291 void insert_empty(Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 00292 XcInputIterator begin_xcurves, XcInputIterator end_xcurves, 00293 PInputIterator begin_points, PInputIterator end_points) 00294 { 00295 typedef typename TopTraits::Sweep_line_construction_visitor 00296 Construct_visitor; 00297 typedef typename Construct_visitor::Traits_2 Construct_traits; 00298 00299 const GeomTraits * geom_traits = arr.geometry_traits(); 00300 Construct_visitor visitor(&arr); 00301 00302 /* We would like to avoid copy construction of the geometry traits class. 00303 * Copy construction is undesired, because it may results with data 00304 * duplication or even data loss. 00305 * 00306 * If the type Construct_visitor::Traits_2 is the same as the type 00307 * GeomTraits, use a reference to GeomTraits to avoid constructing a new one. 00308 * Otherwise, instantiate a local variable of the former and provide 00309 * the later as a single parameter to the constructor. 00310 * 00311 * Use the form 'A a(*b);' and not ''A a = b;' to handle the case where A has 00312 * only an implicit constructor, (which takes *b as a parameter). 00313 */ 00314 typename boost::mpl::if_<boost::is_same<GeomTraits, Construct_traits>, 00315 const Construct_traits&, Construct_traits>::type 00316 traits(*geom_traits); 00317 00318 // Define a sweep-line instance and perform the sweep. 00319 Sweep_line_2<typename Construct_visitor::Traits_2, Construct_visitor, 00320 typename Construct_visitor::Subcurve, 00321 typename Construct_visitor::Event> 00322 sweep_line(&traits, &visitor); 00323 sweep_line.sweep(begin_xcurves, end_xcurves, begin_points, end_points); 00324 } 00325 00331 template <typename GeomTraits, typename TopTraits, 00332 typename XcInputIterator, typename PInputIterator> 00333 void insert_non_empty(Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 00334 XcInputIterator begin_xcurves, 00335 XcInputIterator end_xcurves, 00336 PInputIterator begin_points, PInputIterator end_points) 00337 { 00338 typedef typename TopTraits::Sweep_line_insertion_visitor 00339 Insert_visitor; 00340 typedef typename Insert_visitor::Traits_2 Insert_traits; 00341 typedef typename Insert_visitor::Traits_2::X_monotone_curve_2 00342 Ex_x_monotone_curve_2; 00343 typedef typename Insert_visitor::Traits_2::Point_2 Ex_point_2; 00344 00345 const GeomTraits * geom_traits = arr.geometry_traits(); 00346 Insert_visitor visitor(&arr); 00347 00348 /* We would like to avoid copy construction of the geometry traits class. 00349 * Copy construction is undesired, because it may results with data 00350 * duplication or even data loss. 00351 * 00352 * If the type Construct_visitor::Traits_2 is the same as the type 00353 * GeomTraits, use a reference to GeomTraits to avoid constructing a new one. 00354 * Otherwise, instantiate a local variable of the former and provide 00355 * the later as a single parameter to the constructor. 00356 * 00357 * Use the form 'A a(*b);' and not ''A a = b;' to handle the case where A has 00358 * only an implicit constructor, (which takes *b as a parameter). 00359 */ 00360 typename boost::mpl::if_<boost::is_same<GeomTraits, Insert_traits>, 00361 const Insert_traits&, Insert_traits>::type 00362 traits(*geom_traits); 00363 00364 // Create a set of existing as well as new curves and points. 00365 std::list<Ex_x_monotone_curve_2> ex_cvs; 00366 std::list<Ex_point_2> ex_pts; 00367 00368 prepare_for_sweep(arr, 00369 begin_xcurves, end_xcurves, // the x-monotone curves 00370 begin_points, end_points, // the points (if any) 00371 std::back_inserter(ex_cvs), 00372 std::back_inserter(ex_pts), 00373 &traits); 00374 00375 // Define a basic sweep-line instance and perform the sweep. 00376 Sweep_line_2<typename Insert_visitor::Traits_2, Insert_visitor, 00377 typename Insert_visitor::Subcurve, 00378 typename Insert_visitor::Event> 00379 sweep_line(&traits, &visitor); 00380 sweep_line.sweep(ex_cvs.begin(), ex_cvs.end(),ex_pts.begin(), ex_pts.end()); 00381 }; 00382 00383 //----------------------------------------------------------------------------- 00384 // Insert a range of curves into the arrangement (aggregated insertion). 00385 // The inserted curves may intersect one another and may also intersect the 00386 // existing arrangement. 00387 // 00388 // The last parameter is used to resolve ambiguity between this function and 00389 // do_intersect of X_monotone_curve_2 in case that X_monotone_curve_2 and 00390 // Curve_2 are the same class. 00391 // The last parameter should be boost::false_type but we used a 00392 // workaround since it didn't compile in FC3_g++-3.4.4 with the error of: 00393 // 00394 // error: no matching function for call to `do_intersect(Arrangement_2<>&, 00395 // const Arr_segment_2&, const Arr_walk_along_line_point_location<>&, 00396 // mpl_::bool_< true>)' 00397 // 00398 template <class GeomTraits, class TopTraits, class InputIterator> 00399 void insert (Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 00400 InputIterator begin, InputIterator end, 00401 boost::is_same<int, double>::type) 00402 { 00403 typedef Arrangement_on_surface_2<GeomTraits, TopTraits> Arr; 00404 typedef typename GeomTraits::Point_2 Point_2; 00405 typedef typename GeomTraits::X_monotone_curve_2 X_monotone_curve_2; 00406 00407 // Obtain an arrangement accessor. 00408 Arr_accessor<Arr> arr_access (arr); 00409 00410 // Notify the arrangement observers that a global operation is about to 00411 // take place. 00412 arr_access.notify_before_global_change(); 00413 00414 // Subdivide the input curves into x-monotone subcurves and isolated points. 00415 const GeomTraits * geom_traits = arr.geometry_traits(); 00416 std::list<X_monotone_curve_2> xcurves; 00417 std::list<Point_2> iso_points; 00418 00419 make_x_monotone(begin, end, 00420 std::back_inserter(xcurves), std::back_inserter(iso_points), 00421 geom_traits); 00422 00423 if (arr.is_empty()) 00424 insert_empty(arr, xcurves.begin(), xcurves.end(), 00425 iso_points.begin(), iso_points.end()); 00426 else 00427 insert_non_empty(arr, xcurves.begin(), xcurves.end(), 00428 iso_points.begin(), iso_points.end()); 00429 00430 // Notify the arrangement observers that the global operation has been 00431 // completed. 00432 arr_access.notify_after_global_change(); 00433 } 00434 00435 //----------------------------------------------------------------------------- 00436 // Insert a range of x-monotone curves into the arrangement (aggregated 00437 // insertion). The inserted x-monotone curves may intersect one another and 00438 // may also intersect the existing arrangement. 00439 // 00440 // The last parameter is used to resolve ambiguity between this function and 00441 // insert of Curve_2 in case that X_monotone_curve_2 and Curve_2 are the 00442 // same class. The last parameter should be boost::true_type but we used a 00443 // workaround since it didn't compile in FC3_g++-3.4.4 with the error of: 00444 // 00445 // error: no matching function for call to `do_intersect(Arrangement_2<>&, 00446 // const Arr_segment_2&, const Arr_walk_along_line_point_location<>&, 00447 // mpl_::bool_< true>)' 00448 // 00449 template <class GeomTraits, class TopTraits, class InputIterator> 00450 void insert(Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 00451 InputIterator begin, InputIterator end, 00452 boost::is_same<int, int>::type) 00453 { 00454 typedef Arrangement_on_surface_2<GeomTraits, TopTraits> Arr; 00455 00456 // Obtain an arrangement accessor. 00457 Arr_accessor<Arr> arr_access (arr); 00458 00459 // Notify the arrangement observers that a global operation is about to 00460 // take place. 00461 arr_access.notify_before_global_change(); 00462 00463 // Choose the operation depending on whether the input arrangement is 00464 // empty (then we construct it from scratch), or not (where we just insert 00465 // the new curves). 00466 if (arr.is_empty()) 00467 insert_empty(arr, begin, end); 00468 else { 00469 // The arrangement is not empty: use the insertion visitor. 00470 std::list<typename GeomTraits::Point_2> empty; 00471 insert_non_empty(arr, begin, end, empty.begin(), empty.end()); 00472 } 00473 00474 // Notify the arrangement observers that the global operation has been 00475 // completed. 00476 arr_access.notify_after_global_change(); 00477 } 00478 00479 //----------------------------------------------------------------------------- 00480 // Common interface for the inserts of the Curve_2 and X_monotone_curve_2 00481 template <class GeomTraits, class TopTraits, class InputIterator> 00482 void insert (Arrangement_on_surface_2<GeomTraits,TopTraits>& arr, 00483 InputIterator begin, InputIterator end) 00484 { 00485 typedef typename GeomTraits::X_monotone_curve_2 X_monotone_curve_2; 00486 typedef typename std::iterator_traits<InputIterator>::value_type 00487 Iterator_value_type; 00488 00489 typedef typename boost::is_same<Iterator_value_type,X_monotone_curve_2>::type 00490 Is_x_monotone; 00491 00492 return insert (arr, begin, end, Is_x_monotone()); 00493 } 00494 00495 //----------------------------------------------------------------------------- 00496 // Insert an x-monotone curve into the arrangement (incremental insertion) 00497 // when the location of the left endpoint of the curve is known and is 00498 // given as an isertion hint. 00499 // The inserted x-monotone curve may intersect the existing arrangement. 00500 // 00501 template <class GeomTraits, class TopTraits> 00502 void insert (Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 00503 const typename GeomTraits::X_monotone_curve_2& c, 00504 const Object& obj) 00505 { 00506 typedef Arrangement_on_surface_2<GeomTraits, TopTraits> Arr; 00507 typedef typename TopTraits::Zone_insertion_visitor Zone_visitor; 00508 00509 // Obtain an arrangement accessor. 00510 Arr_accessor<Arr> arr_access (arr); 00511 00512 // Define a zone-computation object an a visitor that performs the 00513 // incremental insertion. 00514 Zone_visitor visitor; 00515 Arrangement_zone_2<Arr, Zone_visitor> arr_zone (arr, &visitor); 00516 00517 // Initialize the zone-computation object with the given curve. 00518 arr_zone.init_with_hint (c, obj); 00519 00520 // Notify the arrangement observers that a global operation is about to 00521 // take place. 00522 arr_access.notify_before_global_change(); 00523 00524 // Insert the x-monotone curve into the arrangement. 00525 arr_zone.compute_zone(); 00526 00527 // Notify the arrangement observers that the global operation has been 00528 // completed. 00529 arr_access.notify_after_global_change(); 00530 } 00531 00532 // ---------------------------------------------------------------------------- 00533 // backward compatibility functions. 00534 /* DEPRECATED use insert() instead */ 00535 template <class GeomTraits, class TopTraits, class PointLocation> 00536 CGAL_DEPRECATED void insert_x_monotone_curve 00537 (Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 00538 const typename GeomTraits::X_monotone_curve_2& c, 00539 const PointLocation& pl) 00540 { 00541 insert(arr, c, pl); 00542 } 00543 00544 /* DEPRECATED use insert() instead */ 00545 template <class GeomTraits, class TopTraits> 00546 CGAL_DEPRECATED void insert_x_monotone_curve 00547 (Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 00548 const typename GeomTraits::X_monotone_curve_2& c) 00549 { 00550 insert(arr, c); 00551 } 00552 00553 /* DEPRECATED use insert() instead */ 00554 template <class GeomTraits, class TopTraits, class InputIterator> 00555 CGAL_DEPRECATED void insert_x_monotone_curves 00556 (Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 00557 InputIterator begin, InputIterator end) 00558 { 00559 insert(arr, begin, end); 00560 } 00561 00562 /* DEPRECATED use insert() instead */ 00563 template <class GeomTraits, class TopTraits> 00564 CGAL_DEPRECATED void insert_x_monotone_curve 00565 (Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 00566 const typename GeomTraits::X_monotone_curve_2& c, 00567 const Object& obj) 00568 { 00569 insert(arr, c, obj); 00570 } 00571 00572 /* DEPRECATED use insert() instead */ 00573 template <class GeomTraits, class TopTraits, class PointLocation> 00574 CGAL_DEPRECATED 00575 void insert_curve(Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 00576 const typename GeomTraits::Curve_2& c, 00577 const PointLocation& pl) 00578 { 00579 insert(arr, c, pl); 00580 } 00581 00582 /* DEPRECATED use insert() instead */ 00583 template <class GeomTraits, class TopTraits> 00584 CGAL_DEPRECATED 00585 void insert_curve(Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 00586 const typename GeomTraits::Curve_2& c) 00587 { 00588 insert(arr, c); 00589 } 00590 00591 /* DEPRECATED use insert() instead */ 00592 template <class GeomTraits, class TopTraits, class InputIterator> 00593 CGAL_DEPRECATED 00594 void insert_curves (Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 00595 InputIterator begin, InputIterator end) 00596 { 00597 insert(arr, begin, end); 00598 } 00599 00600 //----------------------------------------------------------------------------- 00601 // Insert an x-monotone curve into the arrangement, such that the curve 00602 // interior does not intersect with any existing edge or vertex in the 00603 // arragement (incremental insertion). 00604 // 00605 template <class GeomTraits, class TopTraits, class PointLocation> 00606 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Halfedge_handle 00607 insert_non_intersecting_curve 00608 (Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 00609 const typename GeomTraits::X_monotone_curve_2& c, 00610 const PointLocation& pl) 00611 { 00612 typedef Arrangement_on_surface_2<GeomTraits, TopTraits> Arr; 00613 00614 typedef Arr_traits_basic_adaptor_2<typename Arr::Geometry_traits_2> 00615 Traits_adaptor_2; 00616 typedef typename Arr::Vertex_const_handle Vertex_const_handle; 00617 typedef typename Arr::Halfedge_const_handle Halfedge_const_handle; 00618 00619 const Traits_adaptor_2 * geom_traits = 00620 static_cast<const Traits_adaptor_2*> (arr.geometry_traits()); 00621 Arr_accessor<Arr> arr_access (arr); 00622 00623 // Check whether the left end has boundary conditions, and locate it in the 00624 // arrangement accordingly. 00625 const Arr_parameter_space bx1 = 00626 geom_traits->parameter_space_in_x_2_object()(c, ARR_MIN_END); 00627 const Arr_parameter_space by1 = 00628 geom_traits->parameter_space_in_y_2_object()(c, ARR_MIN_END); 00629 CGAL::Object obj1; 00630 const Vertex_const_handle *vh1 = NULL; 00631 00632 if (bx1 == ARR_INTERIOR && by1 == ARR_INTERIOR) 00633 { 00634 // We have a normal left endpoint with no boundary conditions: 00635 // use a point-location query. 00636 obj1 = pl.locate (geom_traits->construct_min_vertex_2_object() (c)); 00637 00638 // The endpoint must not lie on an existing edge, but may coincide with 00639 // and existing vertex vh1. 00640 CGAL_precondition_msg 00641 (object_cast<Halfedge_const_handle> (&obj1) == NULL, 00642 "The curve must not intersect an existing edge."); 00643 00644 vh1 = object_cast<Vertex_const_handle> (&obj1); 00645 } 00646 else 00647 { 00648 // We have a left end with boundary conditions. Use the accessor to locate 00649 // the feature that contains it. 00650 obj1 = arr_access.locate_curve_end (c, ARR_MIN_END, bx1, by1); 00651 00652 CGAL_precondition_msg 00653 (object_cast<Halfedge_const_handle> (&obj1) == NULL, 00654 "The curve must not overlap an existing edge."); 00655 00656 vh1 = object_cast<Vertex_const_handle> (&obj1); 00657 } 00658 00659 // Check whether the right end has boundary conditions, and locate it in the 00660 // arrangement accordingly. 00661 const Arr_parameter_space bx2 = 00662 geom_traits->parameter_space_in_x_2_object()(c, ARR_MAX_END); 00663 const Arr_parameter_space by2 = 00664 geom_traits->parameter_space_in_y_2_object()(c, ARR_MAX_END); 00665 CGAL::Object obj2; 00666 const Vertex_const_handle *vh2 = NULL; 00667 00668 if (bx2 == ARR_INTERIOR && by2 == ARR_INTERIOR) 00669 { 00670 // We have a normal right endpoint with no boundary conditions: 00671 // use a point-location query. 00672 obj2 = pl.locate (geom_traits->construct_max_vertex_2_object() (c)); 00673 00674 // The endpoint must not lie on an existing edge, but may coincide with 00675 // and existing vertex vh2. 00676 CGAL_precondition_msg 00677 (object_cast<Halfedge_const_handle> (&obj2) == NULL, 00678 "The curve must not intersect an existing edge."); 00679 00680 vh2 = object_cast<Vertex_const_handle> (&obj2); 00681 } 00682 else 00683 { 00684 // We have a right end with boundary conditions. Use the accessor to locate 00685 // the feature that contains it. 00686 obj2 = arr_access.locate_curve_end (c, ARR_MAX_END, bx2, by2); 00687 00688 CGAL_precondition_msg 00689 (object_cast<Halfedge_const_handle> (&obj2) == NULL, 00690 "The curve must not overlap an existing edge."); 00691 00692 vh2 = object_cast<Vertex_const_handle> (&obj2); 00693 } 00694 00695 // Notify the arrangement observers that a global operation is about to 00696 // take place. 00697 arr_access.notify_before_global_change(); 00698 00699 // Check whether the located features containing the curve endpoints 00700 // are vertices or faces, and use the proper specialized insertion function 00701 // accordingly. 00702 typename Arr::Halfedge_handle new_he; 00703 00704 if (vh1 != NULL) 00705 { 00706 if (vh2 != NULL) 00707 { 00708 // Both endpoints are associated with a existing vertices. 00709 // In this case insert_at_vertices() already returns a halfedge 00710 // directed from left to right. 00711 new_he = arr.insert_at_vertices (c, 00712 arr.non_const_handle (*vh1), 00713 arr.non_const_handle (*vh2)); 00714 } 00715 else 00716 { 00717 // Only the left endpoint is associated with an existing vertex. 00718 // In this case insert_from_left_vertex() returns a halfedge directed 00719 // to the new vertex it creates, so it is already directed from left to 00720 // right. 00721 new_he = arr.insert_from_left_vertex (c, arr.non_const_handle (*vh1)); 00722 } 00723 } 00724 else 00725 { 00726 if (vh2 != NULL) 00727 { 00728 // Only the right endpoint is associated with an existing vertex. 00729 // In this case insert_from_left_vertex() returns a halfedge directed 00730 // to the new vertex it creates, so it is directed from right to left 00731 // and we take its twin halfedge instead. 00732 new_he = arr.insert_from_right_vertex (c, arr.non_const_handle (*vh2)); 00733 new_he = new_he->twin(); 00734 } 00735 else 00736 { 00737 // Both endpoints are not associated with existing vertices, so 00738 // we must insert the curve in the interior of a face. 00739 // In this case insert_in_face_interior() already returns a halfedge 00740 // directed from left to right. 00741 const typename Arr::Face_const_handle *fh1; 00742 const typename Arr::Face_const_handle *fh2; 00743 00744 fh1 = object_cast<typename Arr::Face_const_handle> (&obj1); 00745 fh2 = object_cast<typename Arr::Face_const_handle> (&obj2); 00746 00747 CGAL_assertion_msg 00748 (fh1 != NULL && fh2 != NULL && *fh1 == *fh2, 00749 "The curve intersects the interior of existing edges."); 00750 00751 if (fh1 != NULL && fh2 != NULL && *fh1 == *fh2) 00752 { 00753 new_he = arr.insert_in_face_interior (c, arr.non_const_handle (*fh1)); 00754 } 00755 } 00756 } 00757 00758 // Notify the arrangement observers that the global operation has been 00759 // completed. 00760 arr_access.notify_after_global_change(); 00761 00762 // Return the resulting halfedge from the insertion operation. 00763 return (new_he); 00764 } 00765 00766 //----------------------------------------------------------------------------- 00767 // Insert an x-monotone curve into the arrangement, such that the curve 00768 // interior does not intersect with any existing edge or vertex in the 00769 // arragement (incremental insertion). 00770 // Overloaded version with no point location object. 00771 // 00772 template <class GeomTraits, class TopTraits> 00773 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Halfedge_handle 00774 insert_non_intersecting_curve 00775 (Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 00776 const typename GeomTraits::X_monotone_curve_2& c) 00777 { 00778 // Create a default point-location object and use it to insert the curve. 00779 typename TopTraits::Default_point_location_strategy def_pl (arr); 00780 00781 return (insert_non_intersecting_curve (arr, c, def_pl)); 00782 } 00783 00789 template <typename GeomTraits, typename TopTraits, typename InputIterator> 00790 void non_intersecting_insert_empty(Arrangement_on_surface_2<GeomTraits, 00791 TopTraits>& arr, 00792 InputIterator begin_xcurves, 00793 InputIterator end_xcurves) 00794 { 00795 const GeomTraits * geom_traits = arr.geometry_traits(); 00796 typedef typename TopTraits::Sweep_line_non_intersecting_construction_visitor 00797 Construct_visitor; 00798 Construct_visitor visitor(&arr); 00799 typename Construct_visitor::Traits_2 traits(*geom_traits); 00800 00801 // Define a basic sweep-line instance (which is not supposed to handle 00802 // insersections) and perform the sweep. 00803 Basic_sweep_line_2<typename Construct_visitor::Traits_2, Construct_visitor, 00804 typename Construct_visitor::Subcurve, 00805 typename Construct_visitor::Event> 00806 sweep_line(&traits, &visitor); 00807 sweep_line.sweep(begin_xcurves, end_xcurves); 00808 } 00809 00815 template <typename GeomTraits, typename TopTraits, 00816 typename XcInputIterator, typename PInputIterator> 00817 void non_intersecting_insert_empty(Arrangement_on_surface_2<GeomTraits, 00818 TopTraits>& arr, 00819 XcInputIterator begin_xcurves, 00820 XcInputIterator end_xcurves, 00821 PInputIterator begin_points, 00822 PInputIterator end_points) 00823 { 00824 typedef typename TopTraits::Sweep_line_non_intersecting_construction_visitor 00825 Construct_visitor; 00826 typedef typename Construct_visitor::Traits_2 Construct_traits; 00827 00828 const GeomTraits * geom_traits = arr.geometry_traits(); 00829 Construct_visitor visitor(&arr); 00830 00831 /* We would like to avoid copy construction of the geometry traits class. 00832 * Copy construction is undesired, because it may results with data 00833 * duplication or even data loss. 00834 * 00835 * If the type Construct_visitor::Traits_2 is the same as the type 00836 * GeomTraits, use a reference to GeomTraits to avoid constructing a new one. 00837 * Otherwise, instantiate a local variable of the former and provide 00838 * the later as a single parameter to the constructor. 00839 * 00840 * Use the form 'A a(*b);' and not ''A a = b;' to handle the case where A has 00841 * only an implicit constructor, (which takes *b as a parameter). 00842 */ 00843 typename boost::mpl::if_<boost::is_same<GeomTraits, Construct_traits>, 00844 const Construct_traits&, Construct_traits>::type 00845 traits(*geom_traits); 00846 00847 // Define a basic sweep-line instance (which is not supposed to handle 00848 // insersections) and perform the sweep. 00849 Basic_sweep_line_2<typename Construct_visitor::Traits_2, Construct_visitor, 00850 typename Construct_visitor::Subcurve, 00851 typename Construct_visitor::Event> 00852 sweep_line(&traits, &visitor); 00853 sweep_line.sweep(begin_xcurves, end_xcurves, begin_points, end_points); 00854 } 00855 00861 template <typename GeomTraits, typename TopTraits, 00862 typename XcInputIterator, typename PInputIterator> 00863 void non_intersecting_insert_non_empty(Arrangement_on_surface_2<GeomTraits, 00864 TopTraits>& arr, 00865 XcInputIterator begin_xcurves, 00866 XcInputIterator end_xcurves, 00867 PInputIterator begin_points, 00868 PInputIterator end_points) 00869 { 00870 typedef typename TopTraits::Sweep_line_non_intersecting_insertion_visitor 00871 Insert_visitor; 00872 typedef typename Insert_visitor::Traits_2 Insert_traits; 00873 typedef typename Insert_visitor::Traits_2::X_monotone_curve_2 00874 Ex_x_monotone_curve_2; 00875 typedef typename Insert_visitor::Traits_2::Point_2 Ex_point_2; 00876 00877 const GeomTraits * geom_traits = arr.geometry_traits(); 00878 Insert_visitor visitor(&arr); 00879 00880 /* We would like to avoid copy construction of the geometry traits class. 00881 * Copy construction is undesired, because it may results with data 00882 * duplication or even data loss. 00883 * 00884 * If the type Construct_visitor::Traits_2 is the same as the type 00885 * GeomTraits, use a reference to GeomTraits to avoid constructing a new one. 00886 * Otherwise, instantiate a local variable of the former and provide 00887 * the later as a single parameter to the constructor. 00888 * 00889 * Use the form 'A a(*b);' and not ''A a = b;' to handle the case where A has 00890 * only an implicit constructor, (which takes *b as a parameter). 00891 */ 00892 typename boost::mpl::if_<boost::is_same<GeomTraits, Insert_traits>, 00893 const Insert_traits&, Insert_traits>::type 00894 traits(*geom_traits); 00895 00896 // Create a set of existing as well as new curves and points. 00897 std::list<Ex_x_monotone_curve_2> ex_cvs; 00898 std::list<Ex_point_2> ex_pts; 00899 00900 prepare_for_sweep(arr, 00901 begin_xcurves, end_xcurves, // the x-monotone curves 00902 begin_points, end_points, // the points (if any) 00903 std::back_inserter(ex_cvs), 00904 std::back_inserter(ex_pts), 00905 &traits); 00906 00907 // Define a basic sweep-line instance and perform the sweep. 00908 Basic_sweep_line_2<typename Insert_visitor::Traits_2, Insert_visitor, 00909 typename Insert_visitor::Subcurve, 00910 typename Insert_visitor::Event> 00911 sweep_line(&traits, &visitor); 00912 sweep_line.sweep(ex_cvs.begin(), ex_cvs.end(), ex_pts.begin(), ex_pts.end()); 00913 } 00914 00915 //----------------------------------------------------------------------------- 00916 // Insert a range of pairwise interior-disjoint x-monotone curves into 00917 // the arrangement, such that the curve interiors do not intersect with 00918 // any existing edge or vertex in the arragement (aggregated insertion). 00919 // 00920 template <class GeomTraits, class TopTraits, class InputIterator> 00921 void insert_non_intersecting_curves 00922 (Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 00923 InputIterator begin, InputIterator end) 00924 { 00925 typedef Arrangement_on_surface_2<GeomTraits, TopTraits> Arr; 00926 00927 // Obtain an arrangement accessor. 00928 Arr_accessor<Arr> arr_access (arr); 00929 00930 // Notify the arrangement observers that a global operation is about to 00931 // take place. 00932 arr_access.notify_before_global_change(); 00933 00934 // Choose the operation depending on whether the input arrangement is 00935 // empty (then we construct it from scratch), or not (where we just insert 00936 // the new curves). 00937 if (arr.is_empty()) 00938 non_intersecting_insert_empty(arr, begin, end); 00939 else { 00940 std::list<typename GeomTraits::Point_2> empty; 00941 non_intersecting_insert_non_empty(arr, begin, end, 00942 empty.begin(), empty.end()); 00943 } 00944 00945 // Notify the arrangement observers that the global operation has been 00946 // completed. 00947 arr_access.notify_after_global_change(); 00948 } 00949 00950 //----------------------------------------------------------------------------- 00951 // Remove an edge from the arrangement. In case it is possible to merge 00952 // the edges incident to the end-vertices of the removed edge after its 00953 // deletion, the function performs these merges as well. 00954 // 00955 template <class GeomTraits, class TopTraits> 00956 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Face_handle 00957 remove_edge 00958 (Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 00959 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Halfedge_handle e) 00960 { 00961 typedef Arrangement_on_surface_2<GeomTraits, TopTraits> Arr; 00962 typedef Arr_traits_adaptor_2<GeomTraits> Traits_adaptor_2; 00963 00964 // Notify the arrangement observers that a global operation is about to 00965 // take place. 00966 Arr_accessor<Arr> arr_access (arr); 00967 00968 arr_access.notify_before_global_change(); 00969 00970 // Keep track of the end-vertices of the edge we are about to remove. 00971 typename Arr::Vertex_handle v_ends[2]; 00972 bool is_removed[2]; 00973 00974 v_ends[0] = e->source(); 00975 is_removed[0] = 00976 (v_ends[0]->is_at_open_boundary() || v_ends[0]->degree() == 1); 00977 v_ends[1] = e->target(); 00978 is_removed[1] = 00979 (v_ends[1]->is_at_open_boundary() || v_ends[1]->degree() == 1); 00980 00981 // Remove the edge from the arrangement. 00982 typename Arr::Face_handle face = arr.remove_edge (e); 00983 00984 // Examine the end-vertices: If a vertex has now two incident edges, and the 00985 // curves associated with these edges can be merged, merge the two edges and 00986 // remove the vertex. 00987 00988 const Traits_adaptor_2 * traits = 00989 static_cast<const Traits_adaptor_2*> (arr.geometry_traits()); 00990 00991 typename Arr::Halfedge_around_vertex_circulator circ; 00992 typename Arr::Halfedge_handle e1, e2; 00993 int i; 00994 00995 for (i = 0; i < 2; i++) 00996 { 00997 if (! is_removed[i] && v_ends[i]->degree() == 2) 00998 { 00999 // Get the two edges incident to the end-vertex. 01000 circ = v_ends[i]->incident_halfedges(); 01001 e1 = circ; 01002 ++circ; 01003 e2 = circ; 01004 01005 // Check if it is possible to merge the two edges. 01006 if (traits->are_mergeable_2_object() (e1->curve(), e2->curve())) 01007 { 01008 // Merge the two curves. 01009 typename GeomTraits::X_monotone_curve_2 cv; 01010 traits->merge_2_object() (e1->curve(), e2->curve(), 01011 cv); 01012 01013 // Merge the two edges in the arrangement. 01014 arr.merge_edge (e1, e2, cv); 01015 } 01016 } 01017 } 01018 01019 // Notify the arrangement observers that the global operation has been 01020 // completed. 01021 arr_access.notify_after_global_change(); 01022 01023 // Return the face remaining after the removal of the edge. 01024 return (face); 01025 } 01026 01027 //----------------------------------------------------------------------------- 01028 // Insert a vertex that corresponds to a given point into the arrangement. 01029 // The inserted point may lie on any existing arrangement feature. 01030 // 01031 template <class GeomTraits, class TopTraits, class PointLocation> 01032 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Vertex_handle 01033 insert_point (Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 01034 const typename GeomTraits::Point_2& p, 01035 const PointLocation& pl) 01036 { 01037 typedef Arrangement_on_surface_2<GeomTraits, TopTraits> Arr; 01038 01039 // Act according to the type of arrangement feature that contains the point. 01040 const typename Arr::Face_const_handle *fh; 01041 const typename Arr::Halfedge_const_handle *hh; 01042 const typename Arr::Vertex_const_handle *vh; 01043 typename Arr::Vertex_handle vh_for_p; 01044 01045 // Locate the given point in the arrangement. 01046 CGAL::Object obj = pl.locate (p); 01047 01048 // Notify the arrangement observers that a global operation is about to 01049 // take place. 01050 Arr_accessor<Arr> arr_access (arr); 01051 01052 arr_access.notify_before_global_change(); 01053 01054 if ((fh = object_cast<typename Arr::Face_const_handle>(&obj)) != NULL) 01055 { 01056 // p lies inside a face: Insert it as an isolated vertex it the interior of 01057 // this face. 01058 vh_for_p = arr.insert_in_face_interior (p, 01059 arr.non_const_handle (*fh)); 01060 } 01061 else if ((hh = 01062 object_cast<typename Arr::Halfedge_const_handle>(&obj)) != NULL) 01063 { 01064 // p lies in the interior of an edge: Split this edge to create a new 01065 // vertex associated with p. 01066 typename GeomTraits::X_monotone_curve_2 sub_cv1, sub_cv2; 01067 typename Arr::Halfedge_handle split_he; 01068 01069 arr.geometry_traits()->split_2_object() ((*hh)->curve(), p, 01070 sub_cv1, sub_cv2); 01071 01072 split_he = arr.split_edge (arr.non_const_handle (*hh), 01073 sub_cv1, sub_cv2); 01074 01075 // The new vertex is the target of the returned halfedge. 01076 vh_for_p = split_he->target(); 01077 } 01078 else 01079 { 01080 // In this case p lies on an existing vertex, so we just update this 01081 // vertex. 01082 vh = object_cast<typename Arr::Vertex_const_handle>(&obj); 01083 CGAL_assertion (vh != NULL); 01084 01085 vh_for_p = arr.modify_vertex (arr.non_const_handle (*vh), p); 01086 } 01087 01088 // Notify the arrangement observers that the global operation has been 01089 // completed. 01090 arr_access.notify_after_global_change(); 01091 01092 // Return a handle for the vertex associated with p. 01093 return (vh_for_p); 01094 } 01095 01096 //----------------------------------------------------------------------------- 01097 // Insert a vertex that corresponds to a given point into the arrangement. 01098 // The inserted point may lie on any existing arrangement feature. 01099 // 01100 template <class GeomTraits, class TopTraits> 01101 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Vertex_handle 01102 insert_point (Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 01103 const typename GeomTraits::Point_2& p) 01104 { 01105 // Create a default point-location object and use it to insert the point. 01106 typename TopTraits::Default_point_location_strategy def_pl (arr); 01107 01108 return (insert_point (arr, p, def_pl)); 01109 } 01110 01111 //----------------------------------------------------------------------------- 01112 // Remove a vertex from the arrangement. 01113 // 01114 template <class GeomTraits, class TopTraits> 01115 bool remove_vertex 01116 (Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 01117 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Vertex_handle v) 01118 { 01119 typedef Arrangement_on_surface_2<GeomTraits, TopTraits> Arr; 01120 typedef Arr_traits_adaptor_2<GeomTraits> Traits_adaptor_2; 01121 01122 // Notify the arrangement observers that a global operation is about to 01123 // take place. 01124 Arr_accessor<Arr> arr_access (arr); 01125 01126 arr_access.notify_before_global_change(); 01127 01128 // Act according to the number of edges incident to v. 01129 bool removed = false; 01130 01131 if (v->is_isolated()) 01132 { 01133 // In case v is an isolated vertex, simply remove it. 01134 arr.remove_isolated_vertex (v); 01135 removed = true; 01136 } 01137 else if (v->degree() == 2) 01138 { 01139 // If the vertex has now two incident edges, and the curves associated 01140 // with these edges can be merged, merge the two edges and remove the 01141 // vertex. 01142 const Traits_adaptor_2 * traits = 01143 static_cast<const Traits_adaptor_2*>(arr.geometry_traits()); 01144 typename Arr::Halfedge_around_vertex_circulator circ; 01145 typename Arr::Halfedge_handle e1, e2; 01146 01147 circ = v->incident_halfedges(); 01148 e1 = circ; 01149 ++circ; 01150 e2 = circ; 01151 01152 if (traits->are_mergeable_2_object() (e1->curve(), e2->curve())) 01153 { 01154 // Merge the two curves. 01155 typename GeomTraits::X_monotone_curve_2 cv; 01156 traits->merge_2_object() (e1->curve(), e2->curve(), 01157 cv); 01158 01159 // Merge the two edges in the arrangement. 01160 arr.merge_edge (e1, e2, cv); 01161 removed = true; 01162 } 01163 } 01164 01165 // Notify the arrangement observers that the global operation has been 01166 // completed. 01167 arr_access.notify_after_global_change(); 01168 01169 // Return an indication whether the vertex has been removed or not. 01170 return (removed); 01171 } 01172 01173 //----------------------------------------------------------------------------- 01174 // Check the validity of the arrangement. In particular, check that the 01175 // edegs are disjoint-interior, and the holes are located in their proper 01176 // position. 01177 // 01178 template <class GeomTraits, class TopTraits> 01179 bool is_valid (const Arrangement_on_surface_2<GeomTraits, TopTraits>& arr) 01180 { 01181 // First use the internal validity check. 01182 if(!arr.is_valid()) 01183 return (false); 01184 01185 typedef Arrangement_on_surface_2<GeomTraits, TopTraits> Arr; 01186 typedef GeomTraits Geometry_traits_2; 01187 typedef typename Geometry_traits_2::Point_2 Point_2; 01188 typedef typename Geometry_traits_2::X_monotone_curve_2 X_monotone_curve_2; 01189 01190 // Define the sweep-line types: 01191 typedef Sweep_line_do_curves_x_visitor<Geometry_traits_2> Visitor; 01192 typedef Sweep_line_2<Geometry_traits_2, Visitor> Sweep_line_2; 01193 01194 // Define the arrangement iterator and circulator types: 01195 typedef typename Arr::Edge_const_iterator Edge_const_iterator; 01196 typedef typename Arr::Halfedge_const_handle Halfedge_const_handle; 01197 typedef typename Arr::Inner_ccb_const_iterator Inner_ccb_const_iterator; 01198 typedef typename Arr::Face_const_iterator Face_const_iterator; 01199 typedef typename Arr::Face_const_handle Face_const_handle; 01200 typedef typename Arr::Vertex_const_handle Vertex_const_handle; 01201 typedef typename Arr::Isolated_vertex_const_iterator 01202 Isolated_vertex_const_iterator; 01203 typedef typename Arr::Ccb_halfedge_const_circulator 01204 Ccb_halfedge_const_circulator; 01205 typedef typename Arr::Halfedge_around_vertex_const_circulator 01206 Halfedge_around_vertex_const_circulator; 01207 01208 // Perform a sweep over all subcurves associated with arrangement edges. 01209 std::vector<X_monotone_curve_2> curves_vec (arr.number_of_edges()); 01210 Edge_const_iterator eit; 01211 unsigned int i = 0; 01212 01213 for (eit = arr.edges_begin(); eit != arr.edges_end(); ++eit, i++) 01214 curves_vec[i] = eit->curve(); 01215 01216 Visitor visitor; 01217 const Geometry_traits_2 *traits = arr.geometry_traits(); 01218 Sweep_line_2 sweep_line (traits, &visitor); 01219 01220 visitor.sweep_xcurves (curves_vec.begin(), curves_vec.end()); 01221 01222 bool are_edges_disjoint = (! visitor.found_intersection()); 01223 01224 if (!are_edges_disjoint) 01225 { 01226 CGAL_warning_msg (are_edges_disjoint, 01227 "Arrangement edges are not disjoint in their interior."); 01228 return (false); 01229 } 01230 01231 // Check that the holes and isolated vertices are located where they should. 01232 // At the same time, we prepare a vector that consists of all isolated 01233 // vertices and all leftmost vertices from every hole. 01234 std::list<std::pair<Vertex_const_handle, Face_const_handle> > vf_list; 01235 01236 typename Geometry_traits_2::Compare_xy_2 compare_xy = 01237 traits->compare_xy_2_object(); 01238 Face_const_iterator fit; 01239 Face_const_handle fh; 01240 Inner_ccb_const_iterator ic_it; 01241 Halfedge_const_handle ccb; 01242 Isolated_vertex_const_iterator iv_it; 01243 Vertex_const_handle left_v; 01244 bool is_first; 01245 01246 for (fit = arr.faces_begin(); fit != arr.faces_end(); ++fit) 01247 { 01248 // Check all holes in the current face. 01249 fh = fit; 01250 for (ic_it = fh->inner_ccbs_begin(); 01251 ic_it != fh->inner_ccbs_end(); ++ic_it) 01252 { 01253 ccb = *ic_it; 01254 is_first = true; 01255 01256 do 01257 { 01258 if (ccb->face() != fit) 01259 return (false); 01260 01261 if (is_first || 01262 compare_xy (ccb->target()->point(), left_v->point()) == SMALLER) 01263 { 01264 left_v = ccb->target(); 01265 is_first = false; 01266 } 01267 01268 ccb = ccb->next(); 01269 01270 } while (ccb != *ic_it); 01271 01272 vf_list.push_back (std::make_pair (left_v, fh)); 01273 } 01274 01275 // Check all isolated vertices in the current face. 01276 for (iv_it = fh->isolated_vertices_begin(); 01277 iv_it != fh->isolated_vertices_end(); ++iv_it) 01278 { 01279 if (iv_it->face() != fit) 01280 return (false); 01281 01282 vf_list.push_back (std::make_pair (Vertex_const_handle(iv_it), fh)); 01283 } 01284 } 01285 01286 // Shoot a vertical ray from each vertex we have collected downward, and 01287 // check that this vertex is really contained in the proper face. 01288 typename Geometry_traits_2::Compare_y_at_x_right_2 comp_y_at_x_right = 01289 traits->compare_y_at_x_right_2_object(); 01290 typename Geometry_traits_2::Compare_y_at_x_left_2 comp_y_at_x_left = 01291 traits->compare_y_at_x_left_2_object(); 01292 01293 typename std::list<std::pair<Vertex_const_handle, 01294 Face_const_handle> >::iterator vf_iter; 01295 typename TopTraits::Default_point_location_strategy def_pl (arr); 01296 Vertex_const_handle curr_v; 01297 Object obj; 01298 Halfedge_const_handle he_below; 01299 Vertex_const_handle v_below; 01300 Face_const_handle in_face; 01301 Halfedge_around_vertex_const_circulator first, circ; 01302 bool assign_ok; 01303 const Halfedge_const_handle invalid_he; 01304 01305 for (vf_iter = vf_list.begin(); vf_iter != vf_list.end(); ++vf_iter) 01306 { 01307 // Perform ray-shooting from the current vertex. 01308 curr_v = vf_iter->first; 01309 obj = def_pl.ray_shoot_down(curr_v->point()); 01310 01311 if (CGAL::assign(he_below, obj)) 01312 { 01313 // Hit an edge - take the incident face of the halfedge directed to the 01314 // right. 01315 if (he_below->direction() == ARR_RIGHT_TO_LEFT) 01316 he_below = he_below->twin(); 01317 01318 in_face = he_below->face(); 01319 } 01320 else if (CGAL::assign(v_below, obj)) 01321 { 01322 // Hit a vertex. 01323 if(v_below->is_isolated()) 01324 { 01325 in_face = v_below->face(); 01326 } 01327 else 01328 { 01329 // Get the first halfedge aroung v_below that is directed from left to 01330 // right and the first halfedge that is directed from right to left. 01331 first = circ = v_below->incident_halfedges(); 01332 Halfedge_const_handle he_left; // A halfedge to the left of v_below. 01333 Halfedge_const_handle he_right; // A halfedge to the right of v_below. 01334 01335 do 01336 { 01337 if (circ->direction() == ARR_LEFT_TO_RIGHT) 01338 { 01339 he_left = circ; 01340 } 01341 else 01342 { 01343 he_right = circ; 01344 if (he_left != invalid_he && he_right != invalid_he) 01345 break; 01346 } 01347 ++circ; 01348 01349 } while(circ != first); 01350 01351 CGAL_assertion (he_left != invalid_he || he_right != invalid_he); 01352 01353 if (he_left != invalid_he && he_right != invalid_he) 01354 { 01355 while (he_left->direction() == ARR_LEFT_TO_RIGHT) 01356 he_left = he_left->next()->twin(); 01357 01358 he_left = he_left->twin()->prev(); 01359 CGAL_assertion (he_left->direction() == ARR_LEFT_TO_RIGHT); 01360 in_face = he_left->face(); 01361 } 01362 else if (he_left != invalid_he) 01363 { 01364 Comparison_result res; 01365 Halfedge_const_handle he_curr = he_left; 01366 01367 do // as long as we have next he_left halfedge which is above 01368 { 01369 he_left = he_curr; 01370 he_curr = he_left->next()->twin(); 01371 res = comp_y_at_x_left (he_curr->curve(), 01372 he_left->curve(), 01373 v_below->point()); 01374 } while(res == LARGER); 01375 in_face = he_left->face(); 01376 } 01377 else 01378 { 01379 Comparison_result res; 01380 Halfedge_const_handle he_curr = he_right; 01381 01382 do // as long as we have he_right halfedge which is below 01383 { 01384 he_right = he_curr; 01385 he_curr = he_right->next()->twin(); 01386 res = comp_y_at_x_right (he_curr->curve(), 01387 he_right->curve(), 01388 v_below->point()); 01389 } while(res == SMALLER); 01390 in_face = he_right->face(); 01391 } 01392 } 01393 } 01394 else 01395 { 01396 // Hit nothing (an unbounded face is returned). 01397 assign_ok = CGAL::assign(in_face, obj); 01398 01399 CGAL_assertion (assign_ok && in_face->is_unbounded()); 01400 01401 if (! assign_ok) 01402 return (false); 01403 } 01404 01405 if (vf_iter->second != in_face) 01406 { 01407 CGAL_warning_msg (false, 01408 "An inner component is located in the wrong face."); 01409 return (false); 01410 } 01411 } 01412 01413 // If we reached here, the arrangement is valid: 01414 return (true); 01415 } 01416 01417 //----------------------------------------------------------------------------- 01418 // Compute the zone of the given x-monotone curve in the existing arrangement. 01419 // Meaning, it output the arrangment's vertices, edges and faces that the 01420 // x-monotone curve intersects. 01421 template <class GeomTraits, class TopTraits, 01422 class OutputIterator, class PointLocation> 01423 OutputIterator zone (Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 01424 const typename GeomTraits::X_monotone_curve_2& c, 01425 OutputIterator oi, 01426 const PointLocation& pl) 01427 { 01428 // Obtain an arrangement accessor. 01429 typedef Arrangement_on_surface_2<GeomTraits,TopTraits> 01430 Arrangement_on_surface_2; 01431 01432 // Define a zone-computation object an a visitor that performs the 01433 // intersection check. 01434 typedef Arr_compute_zone_visitor<Arrangement_on_surface_2, OutputIterator> 01435 Zone_visitor; 01436 01437 Zone_visitor visitor (oi); 01438 Arrangement_zone_2<Arrangement_on_surface_2, Zone_visitor> 01439 arr_zone (arr, &visitor); 01440 01441 arr_zone.init (c, pl); 01442 arr_zone.compute_zone(); 01443 01444 return (oi); 01445 } 01446 01447 //----------------------------------------------------------------------------- 01448 // Compute the zone of the given x-monotone curve in the existing arrangement.b 01449 // Overloaded version with no point location object - the walk point-location 01450 // strategy is used as default. 01451 // 01452 template <class GeomTraits, class TopTraits, class OutputIterator> 01453 OutputIterator zone (Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 01454 const typename GeomTraits::X_monotone_curve_2& c, 01455 OutputIterator oi) 01456 { 01457 typedef Arrangement_on_surface_2<GeomTraits, TopTraits> 01458 Arrangement_on_surface_2; 01459 01460 // Create a default point-location object and use it to insert the curve. 01461 typename TopTraits::Default_point_location_strategy def_pl (arr); 01462 01463 //insert the curve using the walk point location 01464 zone (arr, c, oi, def_pl); 01465 return oi; 01466 } 01467 01468 01469 //----------------------------------------------------------------------------- 01470 // Checks if the given x-monotone curve intersects the existing arrangement. 01471 // The last parameter is used to resolve ambiguity between this function and 01472 // do_intersect of Curve_2 in case that X_monotone_curve_2 and Curve_2 are the 01473 // same class. The last parameter should be boost::true_type but we used a 01474 // workaround since it didn't compile in FC3_g++-3.4.4 with the error of: 01475 // 01476 // error: no matching function for call to `do_intersect(Arrangement_on_surface_2<>&, 01477 // const Arr_segment_2&, const Arr_walk_along_line_point_location<>&, mpl_::bool_< true>)' 01478 // 01479 template <class GeomTraits, class TopTraits, class PointLocation> 01480 bool do_intersect (Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 01481 const typename GeomTraits::X_monotone_curve_2& c, 01482 const PointLocation& pl, boost::is_same<int, int>::type) 01483 { 01484 // Obtain an arrangement accessor. 01485 typedef Arrangement_on_surface_2<GeomTraits,TopTraits> 01486 Arrangement_on_surface_2; 01487 01488 // Define a zone-computation object an a visitor that performs the 01489 // intersection check. 01490 typedef Arr_do_intersect_zone_visitor<Arrangement_on_surface_2> Zone_visitor; 01491 01492 Zone_visitor visitor; 01493 Arrangement_zone_2<Arrangement_on_surface_2, Zone_visitor> 01494 arr_zone (arr, &visitor); 01495 01496 arr_zone.init (c, pl); 01497 arr_zone.compute_zone(); 01498 01499 return (visitor.do_intersect()); 01500 } 01501 01502 //----------------------------------------------------------------------------- 01503 // Checks if the given curve intersects the existing arrangement. 01504 // The last parameter is used to resolve ambiguity between this function and 01505 // do_intersect of X_monotone_curve_2 in case that X_monotone_curve_2 and 01506 // Curve_2 are the same class. 01507 // The last parameter should be boost::false_type but we used a 01508 // workaround since it didn't compile in FC3_g++-3.4.4 with the error of: 01509 // 01510 // error: no matching function for call to `do_intersect(Arrangement_on_surface_2<>&, 01511 // const Arr_segment_2&, const Arr_walk_along_line_point_location<>&, mpl_::bool_< true>)' 01512 // 01513 template <class GeomTraits, class TopTraits, class PointLocation> 01514 bool do_intersect (Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 01515 const typename GeomTraits::X_monotone_curve_2& c, 01516 const PointLocation& pl, boost::is_same<int, double>::type) 01517 { 01518 // Obtain an arrangement accessor. 01519 typedef Arrangement_on_surface_2<GeomTraits,TopTraits> 01520 Arrangement_on_surface_2; 01521 01522 // Break the input curve into x-monotone subcurves and isolated points. 01523 typedef Arr_traits_adaptor_2<GeomTraits> Traits_adaptor_2; 01524 01525 const Traits_adaptor_2 * traits = 01526 static_cast<const Traits_adaptor_2*> (arr.traits()); 01527 01528 std::list<CGAL::Object> x_objects; 01529 std::list<CGAL::Object>::const_iterator obj_iter; 01530 const typename GeomTraits::X_monotone_curve_2 *x_curve; 01531 const typename GeomTraits::Point_2 *iso_p; 01532 01533 traits->make_x_monotone_2_object() (c, 01534 std::back_inserter (x_objects)); 01535 01536 // Insert each x-monotone curve into the arrangement. 01537 for (obj_iter = x_objects.begin(); obj_iter != x_objects.end(); ++obj_iter) 01538 { 01539 // Act according to the type of the current object. 01540 x_curve = object_cast<typename GeomTraits::X_monotone_curve_2> 01541 (&(*obj_iter)); 01542 if (x_curve != NULL) 01543 { 01544 // Check if the x-monotone subcurve intersects the arrangement. 01545 if (do_intersect(arr, *x_curve, pl) == true) 01546 return true; 01547 } 01548 else 01549 { 01550 iso_p = object_cast<typename GeomTraits::Point_2> (&(*obj_iter)); 01551 CGAL_assertion (iso_p != NULL); 01552 01553 // Check whether the isolated point lies inside a face (otherwise, 01554 // it conincides with a vertex or an edge). 01555 CGAL::Object obj = pl.locate (*iso_p); 01556 01557 return (object_cast<typename 01558 Arrangement_on_surface_2::Face_const_handle>(&obj) != NULL); 01559 } 01560 } 01561 01562 // If we reached here, the curve does not intersect the arrangement. 01563 return (false); 01564 } 01565 01566 //----------------------------------------------------------------------------- 01567 // Common interface for the do_intersect of the Curve_2 and X_monotone_curve_2 01568 template <class GeomTraits, class TopTraits, class Curve, class PointLocation> 01569 bool do_intersect (Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 01570 const Curve& c, const PointLocation& pl) 01571 { 01572 typedef typename GeomTraits::X_monotone_curve_2 X_monotone_curve_2; 01573 01574 typedef typename boost::is_same<Curve, X_monotone_curve_2>::type 01575 Is_x_monotone; 01576 01577 return do_intersect(arr, c, pl, Is_x_monotone()); 01578 } 01579 01580 //----------------------------------------------------------------------------- 01581 // Checks if the given curve intersects the existing arrangement. 01582 // Overloaded version with no point location object - the walk point-location 01583 // strategy is used as default. 01584 template <class GeomTraits, class TopTraits, class Curve> 01585 bool do_intersect (Arrangement_on_surface_2<GeomTraits, TopTraits>& arr, 01586 const Curve& c) 01587 { 01588 typedef Arrangement_on_surface_2<GeomTraits, TopTraits> 01589 Arrangement_on_surface_2; 01590 01591 // Create a default point-location object and use it to insert the curve. 01592 typename TopTraits::Default_point_location_strategy def_pl (arr); 01593 01594 // check if the curve intersects the arrangement using the walk point 01595 // location. 01596 return do_intersect (arr, c, def_pl); 01597 } 01598 01599 01600 CGAL_END_NAMESPACE 01601 01602 #endif