BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Boolean_set_operations_2/Gps_on_surface_base_2.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 //                 Ophir Setter    <ophir.setter@cs.tau.ac.il>
00020 //                 Guy Zucker <guyzucke@post.tau.ac.il> 
00021 
00022 
00023 #ifndef CGAL_GPS_ON_SURFACE_BASE_2_H
00024 #define CGAL_GPS_ON_SURFACE_BASE_2_H
00025 
00026 #include <CGAL/basic.h>
00027 #include <CGAL/Object.h>
00028 #include <CGAL/enum.h>
00029 #include <CGAL/iterator.h> 
00030 #include <CGAL/Arrangement_on_surface_2.h>
00031 #include <CGAL/Arrangement_2/Arr_traits_adaptor_2.h>
00032 
00033 #include <CGAL/Arr_overlay_2.h>
00034 #include <CGAL/Boolean_set_operations_2/Gps_do_intersect_functor.h>
00035 #include <CGAL/Boolean_set_operations_2/Gps_intersection_functor.h>
00036 #include <CGAL/Boolean_set_operations_2/Gps_join_functor.h>
00037 #include <CGAL/Boolean_set_operations_2/Gps_difference_functor.h>
00038 #include <CGAL/Boolean_set_operations_2/Gps_sym_diff_functor.h>
00039 #include <CGAL/Boolean_set_operations_2/Gps_merge.h>
00040 #include <CGAL/Boolean_set_operations_2/Gps_polygon_simplifier.h>
00041 #include <CGAL/Boolean_set_operations_2/Ccb_curve_iterator.h>
00042 
00054 CGAL_BEGIN_NAMESPACE
00055 
00056 namespace Boolean_set_operation_2_internal
00057 {
00058   struct NoValidationPolicy
00059   {
00064     template <class Polygon, class Traits>
00065     inline static void is_valid(const Polygon&, Traits&) {}
00066   };
00067 }
00068 
00070 
00076 template <class Traits_, class TopTraits_, 
00077           class ValidationPolicy = 
00078           Boolean_set_operation_2_internal::NoValidationPolicy>
00079 class Gps_on_surface_base_2
00080 {
00081 public:
00082   typedef Traits_                                      Traits_2;
00083   typedef TopTraits_                                   Topology_traits;
00084   typedef typename Traits_2::Polygon_2                 Polygon_2;
00085   typedef typename Traits_2::Polygon_with_holes_2      Polygon_with_holes_2;
00086   typedef CGAL::Arrangement_on_surface_2<Traits_2, Topology_traits>
00087                                                        Arrangement_on_surface_2;
00088   typedef typename Arrangement_on_surface_2::Size      Size;
00089 
00090 private:
00091   typedef Arrangement_on_surface_2                     Aos_2;
00092 
00093   typedef Gps_on_surface_base_2 <
00094     Traits_2, Topology_traits, ValidationPolicy>       Self;
00095   typedef typename Traits_2::Point_2                   Point_2;
00096   typedef typename Traits_2::X_monotone_curve_2        X_monotone_curve_2;
00097   
00098   typedef typename Polygon_with_holes_2::Hole_const_iterator
00099     GP_Holes_const_iterator;
00100   typedef typename Traits_2::Curve_const_iterator      Curve_const_iterator;
00101   typedef typename Traits_2::Compare_endpoints_xy_2
00102                                                        Compare_endpoints_xy_2;
00103   typedef typename Traits_2::Construct_opposite_2      Construct_opposite_2;
00104 
00105   typedef typename Aos_2::Face_const_iterator          Face_const_iterator;
00106   typedef typename Aos_2::Halfedge_const_iterator      Halfedge_const_iterator;
00107   typedef typename Aos_2::Vertex_const_iterator        Vertex_const_iterator;
00108   typedef typename Aos_2::Edge_const_iterator          Edge_const_iterator;
00109   typedef typename Aos_2::Outer_ccb_const_iterator     Outer_ccb_const_iterator;
00110   typedef typename Aos_2::Inner_ccb_const_iterator     Inner_ccb_const_iterator;
00111   typedef typename Aos_2::Ccb_halfedge_const_circulator 
00112     Ccb_halfedge_const_circulator;
00113   typedef typename Aos_2::Face_iterator                Face_iterator;
00114   typedef typename Aos_2::Halfedge_iterator            Halfedge_iterator;
00115   typedef typename Aos_2::Vertex_iterator              Vertex_iterator;
00116   typedef typename Aos_2::Edge_iterator                Edge_iterator;
00117   typedef typename Aos_2::Outer_ccb_iterator           Outer_ccb_iterator;
00118   typedef typename Aos_2::Inner_ccb_iterator           Inner_ccb_iterator;
00119   typedef typename Aos_2::Ccb_halfedge_circulator      Ccb_halfedge_circulator;
00120   typedef typename Aos_2::Face_handle                  Face_handle;
00121   typedef typename Aos_2::Halfedge_handle              Halfedge_handle;
00122   typedef typename Aos_2::Vertex_handle                Vertex_handle;
00123 
00124   typedef typename Aos_2::Face_const_handle            Face_const_handle;
00125   typedef typename Aos_2::Halfedge_const_handle        Halfedge_const_handle;
00126   typedef typename Aos_2::Vertex_const_handle          Vertex_const_handle;
00127 
00128   typedef typename Aos_2::Halfedge_around_vertex_const_circulator
00129     Halfedge_around_vertex_const_circulator;
00130 
00131   typedef std::pair<Aos_2 *, 
00132                     std::vector<Vertex_handle> *>      Arr_entry;
00133 
00134   typedef typename Arrangement_on_surface_2::
00135     Topology_traits::Default_point_location_strategy   Point_location;
00136 
00137 protected:
00138 
00139   // Traits* should be removed and only m_traits should be used.
00140   // If you, who reads this text, have time, replace m_traits 
00141   // with m_traits_adaptor and try to do something about m_traits_owner.
00142   Traits_2*                                  m_traits;
00143   CGAL::Arr_traits_adaptor_2<Traits_2>       m_traits_adaptor;
00144   bool                                       m_traits_owner;
00145 
00146   // the underlying arrangement
00147   Aos_2*        m_arr;
00148 
00149 
00150 public:
00151 
00152   // default costructor
00153   Gps_on_surface_base_2() : m_traits(new Traits_2()),
00154                             m_traits_adaptor(*m_traits),
00155                             m_traits_owner(true),
00156                             m_arr(new Aos_2(m_traits))       
00157   {}
00158 
00159 
00160   // constructor with traits object
00161   Gps_on_surface_base_2(Traits_2& tr) : m_traits(&tr),
00162                                         m_traits_adaptor(*m_traits),
00163                                         m_traits_owner(false),
00164                                         m_arr(new Aos_2(m_traits)) 
00165   {}
00166 
00167 
00168   Gps_on_surface_base_2(const Self& ps) :
00169     m_traits(new Traits_2(*(ps.m_traits))),
00170     m_traits_adaptor(*m_traits),
00171     m_traits_owner(true),
00172     m_arr(new Aos_2(*(ps.m_arr)))
00173   {}
00174 
00175   
00176   Gps_on_surface_base_2& operator=(const Self& ps)
00177   {
00178     if (this == &ps)
00179       return (*this);
00180 
00181     if (m_traits_owner)
00182       delete m_traits;
00183     delete m_arr;
00184     m_traits = new Traits_2(*(ps.m_traits));
00185     m_traits_adaptor = CGAL::Arr_traits_adaptor_2<Traits_2>(*m_traits);
00186     m_traits_owner = true;
00187     m_arr = new Aos_2(*(ps.m_arr));
00188     return (*this);
00189   }
00190 
00191 
00192   explicit Gps_on_surface_base_2(const Polygon_2& pgn) : 
00193     m_traits(new Traits_2()),
00194     m_traits_adaptor(*m_traits),
00195     m_traits_owner(true),
00196     m_arr(new Aos_2(m_traits)) 
00197   {
00198     ValidationPolicy::is_valid(pgn, *m_traits);
00199     _insert(pgn, *m_arr);
00200   }
00201 
00202   explicit Gps_on_surface_base_2(const Polygon_with_holes_2& pgn_with_holes): 
00203     m_traits(new Traits_2()),
00204     m_traits_adaptor(*m_traits),
00205     m_traits_owner(true),
00206     m_arr(new Aos_2(m_traits))
00207   {
00208     ValidationPolicy::is_valid(pgn_with_holes,*m_traits);
00209     _insert(pgn_with_holes, *m_arr);
00210   }
00211 
00212 protected:
00213   Gps_on_surface_base_2(Aos_2* arr) : m_traits(new Traits_2()),
00214                                               m_traits_adaptor(*m_traits),
00215                                               m_traits_owner(true),
00216                                               m_arr(arr)
00217    {}
00218 
00219 public:
00220   //destructor
00221   virtual ~Gps_on_surface_base_2()
00222   {
00223     delete m_arr;
00224 
00225     if (m_traits_owner)
00226       delete m_traits;
00227   }
00228 
00229   void simplify(const Polygon_2& pgn, Polygon_with_holes_2& res)
00230   {
00231     typedef Gps_polygon_simplifier<Aos_2>  Simplifier;
00232 
00233     Aos_2*  arr = new Aos_2();
00234 
00235     Simplifier simp(*arr, *m_traits);
00236     simp.simplify(pgn);
00237     _remove_redundant_edges(arr);
00238     Self gps(arr);
00239     gps._reset_faces();
00240   
00241     typedef Oneset_iterator<Polygon_with_holes_2>    OutputItr;
00242     OutputItr oi (res);
00243     gps.polygons_with_holes(oi);
00244   }
00245 
00246   // insert a simple polygon
00247   void insert(const Polygon_2& pgn)
00248   {
00249     ValidationPolicy::is_valid(pgn, *m_traits);
00250     _insert(pgn, *m_arr);
00251   }
00252 
00253   // insert a polygon with holes
00254   void insert(const Polygon_with_holes_2& pgn_with_holes)
00255   {
00256     ValidationPolicy::is_valid(pgn_with_holes, *m_traits);
00257     _insert(pgn_with_holes, *m_arr);
00258   }
00259   
00260   // insert a range of polygons that can be either simple polygons
00261   // or polygons with holes
00262   // precondition: the polygons are disjoint and simple
00263   template <class PolygonIterator>
00264     void insert(PolygonIterator pgn_begin, PolygonIterator pgn_end);
00265 
00266 
00267   // insert two ranges of : the first one for simple polygons,
00268   // the second one for polygons with holes
00269   // precondition: the first range is disjoint simple polygons 
00270   //               the second range is disjoint polygons with holes
00271   template <class PolygonIterator, class PolygonWithHolesIterator>
00272     void insert(PolygonIterator pgn_begin, PolygonIterator pgn_end,
00273                 PolygonWithHolesIterator pgn_with_holes_begin,
00274                 PolygonWithHolesIterator pgn_with_holes_end);
00275 
00276   // test for intersection with a simple polygon
00277   bool do_intersect(const Polygon_2 &pgn) const
00278   {
00279     ValidationPolicy::is_valid(pgn,*m_traits);
00280     Self other(pgn);
00281     return (do_intersect(other));
00282   }
00283 
00284   // test for intersection with a polygon with holes
00285   bool do_intersect(const Polygon_with_holes_2& pgn_with_holes) const
00286   {
00287     ValidationPolicy::is_valid(pgn_with_holes, *m_traits);
00288     Self other(pgn_with_holes);
00289     return (do_intersect(other));
00290   }
00291 
00292   //test for intersection with another Gps_on_surface_base_2 object
00293   bool do_intersect(const Self& other) const
00294   {
00295     if (this->is_empty() || other.is_empty())
00296       return false;
00297 
00298     if (this->is_plane() || other.is_plane())
00299       return true;
00300     
00301     Aos_2 res_arr;
00302 
00303     Gps_do_intersect_functor<Aos_2>  func;
00304     overlay(*m_arr, *(other.m_arr), res_arr, func);
00305     return func.found_reg_intersection();
00306   }
00307 
00308   template <class InputIterator>
00309     bool do_intersect(InputIterator begin, InputIterator end)
00310   {
00311     Self other(*this);
00312     other.intersection(begin, end);
00313     return (other.is_empty());
00314   }
00315 
00316   template <class InputIterator1, class InputIterator2>
00317     bool do_intersect(InputIterator1 begin1, InputIterator1 end1,
00318                       InputIterator2 begin2, InputIterator2 end2)
00319   {
00320     Self other(*this);
00321     other.intersection(begin1, end1, begin2, end2);
00322     return (other.is_empty());
00323   }
00324 
00325 
00326   // intersection with a simple polygon
00327   void intersection(const Polygon_2& pgn)
00328   {
00329     ValidationPolicy::is_valid(pgn, *m_traits);
00330     _intersection(pgn);
00331   }
00332 
00333   // intersection with a polygon with holes
00334   void intersection(const Polygon_with_holes_2& pgn)
00335   {
00336     ValidationPolicy::is_valid(pgn, *m_traits);
00337     _intersection(pgn);
00338   }
00339 
00340   //intersection with another Gps_on_surface_base_2 object
00341   void intersection(const Self& other)
00342   {
00343     _intersection(other);
00344   }
00345 
00346   void intersection(const Self& gps1, const Self& gps2)
00347   {
00348     this->clear();
00349     _intersection(*(gps1.m_arr), *(gps2.m_arr), *(this->m_arr));
00350   }
00351 
00352 
00353   // join with a simple polygon
00354   void join(const Polygon_2& pgn)
00355   {
00356     ValidationPolicy::is_valid(pgn, *m_traits);
00357     _join(pgn);
00358   }
00359 
00360   // join with a polygon with holes
00361   void join(const Polygon_with_holes_2& pgn)
00362   {
00363     ValidationPolicy::is_valid(pgn, *m_traits);
00364     _join(pgn);
00365   }
00366 
00367   //join with another Gps_on_surface_base_2 object
00368   void join(const Self& other)
00369   {
00370     _join(other);
00371   }
00372 
00373   void join(const Self& gps1, const Self& gps2)
00374   {
00375     this->clear();
00376     _join(*(gps1.m_arr), *(gps2.m_arr), *(this->m_arr));
00377   }
00378 
00379   // difference with a simple polygon
00380   void difference (const Polygon_2& pgn)
00381   {
00382     ValidationPolicy::is_valid(pgn, *m_traits);
00383     _difference(pgn);
00384   }
00385 
00386   // difference with a polygon with holes
00387   void difference (const Polygon_with_holes_2& pgn)
00388   {
00389     ValidationPolicy::is_valid(pgn, *m_traits);
00390     _difference(pgn);
00391   }
00392   
00393   //difference with another Gps_on_surface_base_2 object
00394   void difference (const Self& other)
00395   {
00396     _difference(other);
00397   }
00398 
00399   void difference(const Self& gps1, const Self& gps2)
00400   {
00401     this->clear();
00402     _difference(*(gps1.m_arr), *(gps2.m_arr), *(this->m_arr));
00403   }
00404 
00405 
00406   // symmetric_difference with a simple polygon
00407   void symmetric_difference(const Polygon_2& pgn)
00408   {
00409     ValidationPolicy::is_valid(pgn, *m_traits);
00410     _symmetric_difference(pgn);
00411   }
00412 
00413   // symmetric_difference with a polygon with holes
00414   void symmetric_difference(const Polygon_with_holes_2& pgn)
00415   {
00416     ValidationPolicy::is_valid(pgn, *m_traits);
00417     _symmetric_difference(pgn);
00418   }
00419 
00420   //symmetric_difference with another Gps_on_surface_base_2 object
00421   void symmetric_difference(const Self& other)
00422   {
00423     _symmetric_difference(other);
00424   }
00425 
00426   void symmetric_difference(const Self& gps1, const Self& gps2)
00427   {
00428     this->clear();
00429     _symmetric_difference(*(gps1.m_arr), *(gps2.m_arr), *(this->m_arr));
00430   }
00431 
00432 
00433   void complement()
00434   {
00435     this->_complement(m_arr);
00436   }
00437 
00438   void complement(const Self& other)
00439   {
00440     *(this->m_arr) = *(other.m_arr);
00441     this->complement();
00442   }
00443 
00444   void fix_curves_direction()
00445   {
00446     _fix_curves_direction(*m_arr);
00447   }
00448          
00449   Size number_of_polygons_with_holes() const;
00450 
00451   Traits_2& traits()
00452   {
00453     return *m_traits;
00454   }
00455 
00456   const Traits_2& traits() const
00457   {
00458     return *m_traits;
00459   }
00460 
00461   bool is_empty() const
00462   {
00463     // We have to check that all the faces of an empty arrangement are not
00464     // conained in the polygon set (there can be several faces in an empty
00465     // arrangement, dependant on the topology traits.
00466     // The point is that if the arrangement is "empty" (meaning that no curve
00467     // or point were inserted and that it is in its original state) then 
00468     // all the faces (created by the topology traits) should have the same
00469     // result for contained() --- from Boolean operations point of view there
00470     // can not be an empty arrangement which has serveral faces with different
00471     // attributes.
00472     return (m_arr->is_empty() && !m_arr->faces_begin()->contained());
00473   }
00474 
00475   bool is_plane() const
00476   {
00477     // Same comment as in "is_empty" above, just with adjustments.
00478     return (m_arr->is_empty() &&  m_arr->faces_begin()->contained());
00479   }
00480 
00481   void clear()
00482   {
00483     m_arr->clear();
00484   }
00485 
00486   
00487   Oriented_side oriented_side(const Point_2& q) const
00488   {
00489     Point_location pl(*m_arr);
00490 
00491     Object obj = pl.locate(q);
00492     Face_const_iterator f;
00493     if (CGAL::assign(f, obj))
00494     {
00495       if (f->contained())
00496         return ON_POSITIVE_SIDE;
00497 
00498       return ON_NEGATIVE_SIDE ;
00499     }  
00500     return ON_ORIENTED_BOUNDARY ;
00501   }
00502 
00503   Oriented_side oriented_side(const Polygon_2& pgn) const
00504   {
00505     ValidationPolicy::is_valid(pgn, *m_traits);
00506     Self other(pgn);
00507     return (oriented_side(other));
00508   }
00509 
00510   Oriented_side oriented_side(const Polygon_with_holes_2& pgn) const
00511   {
00512     ValidationPolicy::is_valid(pgn, *m_traits);
00513     Self other(pgn);
00514     return (oriented_side(other));
00515   }
00516 
00517   Oriented_side oriented_side(const Self& other) const
00518   {
00519     if (this->is_empty() || other.is_empty())
00520       return ON_NEGATIVE_SIDE;
00521 
00522     if (this->is_plane() || other.is_plane())
00523       return ON_POSITIVE_SIDE;
00524     
00525     Aos_2 res_arr;
00526 
00527     Gps_do_intersect_functor<Aos_2>  func;
00528     overlay(*m_arr, *(other.m_arr), res_arr, func);
00529     if (func.found_reg_intersection())
00530       return ON_POSITIVE_SIDE;
00531     
00532     if (func.found_boundary_intersection())
00533       return ON_ORIENTED_BOUNDARY;
00534 
00535     return ON_NEGATIVE_SIDE;
00536   }
00537 
00538 
00539   // returns the location of the query point
00540   bool locate(const Point_2& q, Polygon_with_holes_2& pgn) const;
00541 
00545   const Aos_2& arrangement() const
00546   {
00547     return *m_arr;
00548   }
00549 
00553   Aos_2& arrangement()
00554   {
00555     return *m_arr;
00556   }
00557   
00559   bool is_valid() const
00560   {
00561     if (!CGAL::is_valid(*m_arr))
00562       return false;
00563 
00564     Compare_endpoints_xy_2 cmp_endpoints =
00565       m_traits->compare_endpoints_xy_2_object();
00566     Construct_opposite_2 ctr_opp = m_traits->construct_opposite_2_object();
00567 
00568     for (Edge_const_iterator eci = m_arr->edges_begin();
00569          eci != m_arr->edges_end();
00570          ++eci)
00571     {
00572       Halfedge_const_handle he = eci;
00573       if (he->face() == he->twin()->face())
00574       {
00575         return false;
00576       }
00577       if (he->face()->contained() == he->twin()->face()->contained())
00578       {
00579         return false;
00580       }
00581 
00582       const X_monotone_curve_2&  cv = he->curve();
00583       const bool                 is_cont = he->face()->contained();
00584       const Comparison_result    he_res = 
00585         ((Arr_halfedge_direction)he->direction() == ARR_LEFT_TO_RIGHT) ?
00586         SMALLER : LARGER;
00587       const bool                 has_same_dir = (cmp_endpoints(cv) == he_res);
00588 
00589       if ((is_cont && !has_same_dir) || (!is_cont && has_same_dir))
00590         return false;
00591     }
00592     return true;
00593   }
00594 
00595   // get the simple polygons, takes O(n)
00596   template <class OutputIterator>
00597     OutputIterator polygons_with_holes(OutputIterator out) const;
00598 
00599   // join a range of polygons
00600   template <class InputIterator>
00601     void join(InputIterator begin, InputIterator end, unsigned int k = 5)
00602   {
00603     typename std::iterator_traits<InputIterator>::value_type pgn;
00604     this->join(begin, end, pgn, k);
00605     this->remove_redundant_edges();
00606     this->_reset_faces();
00607   }
00608 
00609   // join range of simple polygons
00610   // 5 is the magic number in which we switch to a sweep-based algorithm
00611   // instead of a D&C algorithm. This point should be further studies, as
00612   // it is hard to believe that this is the best value for all applications.
00613   template <class InputIterator>
00614     inline void join(InputIterator begin,
00615                      InputIterator end,
00616                      Polygon_2&,
00617                      unsigned int k=5)
00618   {
00619     std::vector<Arr_entry> arr_vec (std::distance(begin, end) + 1);
00620  
00621     arr_vec[0].first = this->m_arr;
00622     unsigned int i = 1;
00623     for (InputIterator itr = begin; itr!=end; ++itr, ++i)
00624     {
00625       arr_vec[i].first = new Aos_2(m_traits);
00626       _insert(*itr, *(arr_vec[i].first));
00627     }
00628 
00629     Join_merge<Aos_2> join_merge;
00630     _build_sorted_vertices_vectors (arr_vec);
00631     _divide_and_conquer(0, arr_vec.size()-1, arr_vec, k, join_merge);
00632   
00633     //the result arrangement is at index 0
00634     this->m_arr = arr_vec[0].first;
00635     delete arr_vec[0].second;
00636   }
00637 
00638   //join range of polygons with holes (see previous comment about k=5).
00639   template <class InputIterator>
00640     inline void join(InputIterator begin, InputIterator end,
00641                      Polygon_with_holes_2&, unsigned int k=5)
00642   {
00643     std::vector<Arr_entry> arr_vec (std::distance(begin, end) + 1);
00644     arr_vec[0].first = this->m_arr;
00645  
00646     unsigned int i = 1;
00647     for (InputIterator itr = begin; itr!=end; ++itr, ++i)
00648     {
00649       arr_vec[i].first = new Aos_2(m_traits);
00650       _insert(*itr, *(arr_vec[i].first));
00651     }
00652 
00653     Join_merge<Aos_2> join_merge;
00654     _build_sorted_vertices_vectors (arr_vec);
00655     _divide_and_conquer(0, arr_vec.size()-1, arr_vec, k, join_merge);
00656 
00657     //the result arrangement is at index 0
00658     this->m_arr = arr_vec[0].first;
00659     delete arr_vec[0].second;
00660   }
00661 
00662   // (see previous comment about k=5).
00663   template <class InputIterator1, class InputIterator2>
00664     inline void join(InputIterator1 begin1, InputIterator1 end1,
00665                      InputIterator2 begin2, InputIterator2 end2,
00666                      unsigned int k=5)
00667   {
00668     std::vector<Arr_entry> arr_vec (std::distance(begin1, end1)+
00669                                     std::distance(begin2, end2)+1);
00670  
00671     arr_vec[0].first = this->m_arr;
00672     unsigned int i = 1;
00673     
00674     for (InputIterator1 itr1 = begin1; itr1!=end1; ++itr1, ++i)
00675     {
00676       arr_vec[i].first = new Aos_2(m_traits);
00677       _insert(*itr1, *(arr_vec[i].first));
00678     }
00679     
00680     for (InputIterator2 itr2 = begin2; itr2!=end2; ++itr2, ++i)
00681     {
00682       arr_vec[i].first = new Aos_2(m_traits);
00683       _insert(*itr2, *(arr_vec[i].first));
00684     }
00685 
00686     Join_merge<Aos_2> join_merge;
00687     _build_sorted_vertices_vectors (arr_vec);
00688     _divide_and_conquer(0, arr_vec.size()-1, arr_vec, k, join_merge);
00689 
00690     //the result arrangement is at index 0
00691     this->m_arr = arr_vec[0].first;
00692     delete arr_vec[0].second;
00693     this->remove_redundant_edges();
00694     this->_reset_faces();
00695   }
00696 
00697 
00698   // intersect range of polygins (see previous comment about k=5).
00699   template <class InputIterator>
00700     inline void intersection(InputIterator begin, InputIterator end,
00701                              unsigned int k=5)
00702   {
00703     typename std::iterator_traits<InputIterator>::value_type pgn;
00704     this->intersection(begin, end, pgn, k);
00705     this->remove_redundant_edges();
00706     this->_reset_faces();
00707   }
00708   
00709   
00710   // intersect range of simple polygons
00711   template <class InputIterator>
00712     inline void intersection(InputIterator begin, InputIterator end,
00713                              Polygon_2&, unsigned int k)
00714   {
00715     std::vector<Arr_entry> arr_vec (std::distance(begin, end) + 1);
00716     arr_vec[0].first = this->m_arr;
00717     unsigned int i = 1;
00718     
00719     for (InputIterator itr = begin; itr!=end; ++itr, ++i)
00720     {
00721       ValidationPolicy::is_valid((*itr), *m_traits);
00722       arr_vec[i].first = new Aos_2(m_traits);
00723       _insert(*itr, *(arr_vec[i].first));
00724     }
00725     
00726     Intersection_merge<Aos_2> intersection_merge;
00727     _build_sorted_vertices_vectors (arr_vec);
00728     _divide_and_conquer(0, arr_vec.size()-1, arr_vec, k, intersection_merge);
00729     
00730     //the result arrangement is at index 0
00731     this->m_arr = arr_vec[0].first;
00732     delete arr_vec[0].second;
00733   }
00734   
00735   //intersect range of polygons with holes
00736   template <class InputIterator>
00737     inline void intersection(InputIterator begin, InputIterator end,
00738                              Polygon_with_holes_2&, unsigned int k)
00739   {
00740     std::vector<Arr_entry> arr_vec (std::distance(begin, end) + 1);
00741     arr_vec[0].first = this->m_arr;
00742     unsigned int i = 1;
00743     
00744     for (InputIterator itr = begin; itr!=end; ++itr, ++i)
00745     {
00746       ValidationPolicy::is_valid((*itr), *m_traits);
00747       arr_vec[i].first = new Aos_2(m_traits);
00748       _insert(*itr, *(arr_vec[i].first));
00749     }
00750     
00751     Intersection_merge<Aos_2> intersection_merge;
00752     _build_sorted_vertices_vectors (arr_vec);
00753     _divide_and_conquer(0, arr_vec.size()-1, arr_vec, k, intersection_merge);
00754     
00755     //the result arrangement is at index 0
00756     this->m_arr = arr_vec[0].first;
00757     delete arr_vec[0].second;
00758   }
00759   
00760   
00761   template <class InputIterator1, class InputIterator2>
00762     inline void intersection(InputIterator1 begin1, InputIterator1 end1,
00763                              InputIterator2 begin2, InputIterator2 end2,
00764                              unsigned int k=5)
00765   {
00766     std::vector<Arr_entry> arr_vec (std::distance(begin1, end1)+
00767                                     std::distance(begin2, end2)+1);
00768     arr_vec[0].first = this->m_arr;
00769     unsigned int i = 1;
00770     
00771     for (InputIterator1 itr1 = begin1; itr1!=end1; ++itr1, ++i)
00772     {
00773       ValidationPolicy::is_valid(*itr1, *m_traits);
00774       arr_vec[i].first = new Aos_2(m_traits);
00775       _insert(*itr1, *(arr_vec[i].first));
00776     }
00777     
00778     for (InputIterator2 itr2 = begin2; itr2!=end2; ++itr2, ++i)
00779     {
00780       ValidationPolicy::is_valid(*itr2,*m_traits);
00781       arr_vec[i].first = new Aos_2(m_traits);
00782       _insert(*itr2, *(arr_vec[i].first));
00783     }
00784     
00785     Intersection_merge<Aos_2> intersection_merge;
00786     _build_sorted_vertices_vectors (arr_vec);
00787     _divide_and_conquer(0, arr_vec.size()-1, arr_vec, k, intersection_merge);
00788     
00789     //the result arrangement is at index 0
00790     this->m_arr = arr_vec[0].first;
00791     delete arr_vec[0].second;
00792     this->remove_redundant_edges();
00793     this->_reset_faces();
00794   }
00795   
00796   
00797   
00798   // symmetric_difference of a range of polygons (similar to xor)
00799   // (see previous comment about k=5).
00800   template <class InputIterator>
00801     inline void symmetric_difference(InputIterator begin, InputIterator end,
00802                                      unsigned int k=5)
00803   {
00804     typename std::iterator_traits<InputIterator>::value_type pgn;
00805     this->symmetric_difference(begin, end, pgn, k);
00806     this->remove_redundant_edges();
00807     this->_reset_faces();
00808   }
00809   
00810   
00811   // intersect range of simple polygons (see previous comment about k=5).
00812   template <class InputIterator>
00813     inline void symmetric_difference(InputIterator begin, InputIterator end,
00814                                      Polygon_2&, unsigned int k=5)
00815   {
00816     std::vector<Arr_entry> arr_vec (std::distance(begin, end) + 1);
00817     arr_vec[0].first = this->m_arr;
00818     unsigned int i = 1;
00819     
00820     for (InputIterator itr = begin; itr!=end; ++itr, ++i)
00821     {
00822       ValidationPolicy::is_valid(*itr,*m_traits);
00823       arr_vec[i].first = new Aos_2(m_traits);
00824       _insert(*itr, *(arr_vec[i].first));
00825     }
00826     
00827     Xor_merge<Aos_2> xor_merge;
00828     _build_sorted_vertices_vectors (arr_vec);
00829     _divide_and_conquer(0, arr_vec.size()-1, arr_vec, k, xor_merge);
00830     
00831     //the result arrangement is at index 0
00832     this->m_arr = arr_vec[0].first;
00833     delete arr_vec[0].second;
00834   }
00835   
00836   //intersect range of polygons with holes (see previous comment about k=5).
00837   template <class InputIterator>
00838     inline void symmetric_difference(InputIterator begin, InputIterator end,
00839                                      Polygon_with_holes_2&, unsigned int k=5)
00840   {
00841     std::vector<Arr_entry> arr_vec (std::distance(begin, end) + 1);
00842     arr_vec[0].first = this->m_arr;
00843     unsigned int i = 1;
00844     
00845     for (InputIterator itr = begin; itr!=end; ++itr, ++i)
00846     {
00847       ValidationPolicy::is_valid(*itr,*m_traits);
00848       arr_vec[i].first = new Aos_2(m_traits);
00849       _insert(*itr, *(arr_vec[i].first));
00850     }
00851     
00852     Xor_merge<Aos_2> xor_merge;
00853     _build_sorted_vertices_vectors (arr_vec);
00854     _divide_and_conquer(0, arr_vec.size()-1, arr_vec, k, xor_merge);
00855     
00856     //the result arrangement is at index 0
00857     this->m_arr = arr_vec[0].first;
00858     delete arr_vec[0].second;
00859   }
00860   
00861   // (see previous comment about k=5).
00862   template <class InputIterator1, class InputIterator2>
00863     inline void symmetric_difference(InputIterator1 begin1, InputIterator1 end1,
00864                                      InputIterator2 begin2, InputIterator2 end2,
00865                                      unsigned int k=5)
00866   {
00867     std::vector<Arr_entry> arr_vec (std::distance(begin1, end1)+
00868                                     std::distance(begin2, end2)+1);
00869     arr_vec[0].first = this->m_arr;
00870     unsigned int i = 1;
00871     
00872     for (InputIterator1 itr1 = begin1; itr1!=end1; ++itr1, ++i)
00873     {
00874       ValidationPolicy::is_valid(*itr1, *m_traits);
00875       arr_vec[i].first = new Aos_2(m_traits);
00876       _insert(*itr1, *(arr_vec[i].first));
00877     }
00878     
00879     for (InputIterator2 itr2 = begin2; itr2!=end2; ++itr2, ++i)
00880     {
00881       ValidationPolicy::is_valid(*itr2, *m_traits);
00882       arr_vec[i].first = new Aos_2(m_traits);
00883       _insert(*itr2, *(arr_vec[i].first));
00884     }
00885     
00886     Xor_merge<Aos_2> xor_merge;
00887     _build_sorted_vertices_vectors (arr_vec);
00888     _divide_and_conquer(0, arr_vec.size()-1, arr_vec, k, xor_merge);
00889     
00890     //the result arrangement is at index 0
00891     this->m_arr = arr_vec[0].first;
00892     delete arr_vec[0].second;
00893     this->remove_redundant_edges();
00894     this->_reset_faces();
00895   }
00896   
00897   static void construct_polygon(Ccb_halfedge_const_circulator ccb,
00898                                 Polygon_2 & pgn, Traits_2 * tr);
00899   
00900   bool is_hole_of_face(Face_const_handle f, Halfedge_const_handle he) const;
00901   
00902   Ccb_halfedge_const_circulator
00903     get_boundary_of_polygon(Face_const_iterator f) const;
00904   
00905   void remove_redundant_edges()
00906   {
00907     this->_remove_redundant_edges(m_arr);
00908   }
00909 
00910 protected:
00911   
00912   void _remove_redundant_edges(Aos_2* arr)
00913   {
00914     for (Edge_iterator itr = arr->edges_begin(); itr != arr->edges_end(); )
00915     {
00916       Halfedge_handle he = itr;
00917       if (he->face()->contained() == he->twin()->face()->contained())
00918       {
00919         Edge_iterator next = itr;
00920         ++next;
00921         arr->remove_edge(he);
00922         itr = next;
00923       }
00924       else
00925         ++itr;
00926     }
00927   }
00928   
00929   class Less_vertex_handle
00930   {
00931     typename Traits_2::Compare_xy_2     comp_xy;
00932     
00933   public:
00934     
00935     Less_vertex_handle (const typename Traits_2::Compare_xy_2& cmp) :
00936     comp_xy (cmp)
00937     {}
00938     
00939     bool operator() (Vertex_handle v1, Vertex_handle v2) const
00940     {
00941       return (comp_xy (v1->point(), v2->point()) == SMALLER);
00942     }
00943   };
00944   
00945 
00946   void _complement(Aos_2* arr)
00947   {
00948     for (Face_iterator fit = arr->faces_begin();
00949          fit != arr->faces_end();
00950          ++fit)
00951     {
00952       fit->set_contained(!fit->contained());
00953     }
00954 
00955     Construct_opposite_2 ctr_opp = m_traits->construct_opposite_2_object();
00956     for (Edge_iterator eit = arr->edges_begin();
00957          eit != arr->edges_end();
00958          ++eit)
00959     {
00960       Halfedge_handle he = eit;
00961       const X_monotone_curve_2& cv = he->curve();
00962       arr->modify_edge(he, ctr_opp(cv));
00963     }
00964   }
00965 
00966   //fix the directions of the curves (given correct marked face)
00967   // it should be called mostly after  symmetric_difference.
00968   void _fix_curves_direction(Aos_2& arr)
00969   {
00970     Compare_endpoints_xy_2 cmp_endpoints =
00971       m_traits->compare_endpoints_xy_2_object();
00972     Construct_opposite_2 ctr_opp = m_traits->construct_opposite_2_object();
00973 
00974     for (Edge_iterator eit = arr.edges_begin();
00975          eit != arr.edges_end();
00976          ++eit)
00977     {
00978       Halfedge_handle            he = eit;
00979       const X_monotone_curve_2&  cv = he->curve();
00980       const bool                 is_cont = he->face()->contained();
00981       const Comparison_result    he_res = 
00982         ((Arr_halfedge_direction)he->direction() == ARR_LEFT_TO_RIGHT) ?
00983         SMALLER : LARGER;
00984       const bool                 has_same_dir = (cmp_endpoints(cv) == he_res);
00985 
00986       if ((is_cont && !has_same_dir) || (!is_cont && has_same_dir))
00987         arr.modify_edge(he, ctr_opp(cv));
00988     }
00989   }
00990 
00991   void _build_sorted_vertices_vectors (std::vector<Arr_entry>& arr_vec)
00992   {
00993     Less_vertex_handle    comp (m_traits->compare_xy_2_object());
00994     Aos_2                 *p_arr;
00995     Vertex_iterator       vit;
00996     const std::size_t     n = arr_vec.size();
00997     std::size_t           i, j;
00998     
00999     for (i = 0; i < n; i++)
01000     {
01001       // Allocate a vector of handles to all vertices in the current
01002       // arrangement.
01003       p_arr = arr_vec[i].first;
01004       arr_vec[i].second = new std::vector<Vertex_handle>;
01005       arr_vec[i].second->resize (p_arr->number_of_vertices());
01006       
01007       for (j = 0, vit = p_arr->vertices_begin();
01008            vit != p_arr->vertices_end();
01009            j++, ++vit)
01010       {
01011         (*(arr_vec[i].second))[j] = vit;
01012       }
01013       
01014       // Sort the vector.
01015       std::sort (arr_vec[i].second->begin(), arr_vec[i].second->end(), comp);
01016     }
01017   }
01018   
01019   template <class Merge>
01020     void _divide_and_conquer (unsigned int lower, unsigned int upper,
01021                               std::vector<Arr_entry>& arr_vec,
01022                               unsigned int k, Merge merge_func)
01023   {
01024     if ((upper - lower) < k)
01025     {
01026       merge_func(lower, upper, 1, arr_vec);
01027       return;
01028     }
01029     
01030     unsigned int sub_size = ((upper - lower + 1) / k);
01031     unsigned int i = 0;
01032     unsigned int curr_lower = lower;
01033     
01034     for (; i<k-1; ++i, curr_lower += sub_size )
01035     {
01036       _divide_and_conquer(curr_lower, curr_lower + sub_size-1, arr_vec, k,
01037                           merge_func);
01038     }
01039     _divide_and_conquer (curr_lower, upper,arr_vec, k, merge_func);
01040     merge_func (lower, curr_lower, sub_size ,arr_vec);
01041     
01042     return;
01043   }
01044   
01045   // mark all faces as non-visited
01046   void _reset_faces() const
01047   {
01048     _reset_faces(m_arr);
01049   }
01050   
01051   void _reset_faces(Aos_2* arr) const
01052   {
01053     Face_const_iterator fit = arr->faces_begin();
01054     for ( ; fit != arr->faces_end(); ++fit)
01055     {
01056       fit->set_visited(false);
01057     }
01058   }
01059 
01060 
01061   void _insert(const Polygon_2& pgn, Aos_2& arr);
01062   
01063 // The function below is public because are_holes_and_boundary_pairwise_disjoint
01064 // of Gps_polygon_validation is using it.
01065 // I have tried to define it as friend function, but with no success (probably
01066 // did something wrong with templates and friend.) Besides, it was like this
01067 // before I touched it, so I did not have the energy.
01068 public:  
01069   void _insert(const Polygon_with_holes_2& pgn, Aos_2& arr);
01070   
01071 protected:
01072   template<class PolygonIter>
01073     void _insert(PolygonIter p_begin, PolygonIter p_end, Polygon_2& pgn);
01074   
01075   template<class PolygonIter>
01076     void _insert(PolygonIter p_begin, PolygonIter p_end,
01077                  Polygon_with_holes_2& pgn);
01078   
01079   template <class OutputIterator>
01080     void _construct_curves(const Polygon_2& pgn, OutputIterator oi);
01081   
01082   template <class OutputIterator>
01083     void _construct_curves(const Polygon_with_holes_2& pgn, OutputIterator oi);
01084   
01085   
01086   bool _is_empty(const Polygon_2& pgn) const
01087   {
01088     const std::pair<Curve_const_iterator, Curve_const_iterator>& itr_pair = 
01089       m_traits->construct_curves_2_object()(pgn);
01090     return (itr_pair.first == itr_pair.second);
01091   }
01092   
01093   bool _is_empty(const Polygon_with_holes_2& ) const
01094   {
01095     return (false);
01096   }
01097   
01098   bool _is_plane(const Polygon_2& ) const
01099   {
01100     return (false);
01101   }
01102   
01103   bool _is_plane(const Polygon_with_holes_2& pgn) const
01104   {
01105     //typedef typename  Traits_2::Is_unbounded  Is_unbounded;
01106     bool unbounded = m_traits->construct_is_unbounded_object()(pgn);
01107     std::pair<GP_Holes_const_iterator, 
01108       GP_Holes_const_iterator> pair = 
01109       m_traits->construct_holes_object()(pgn);
01110     return (unbounded && (pair.first == pair.second));
01111     //used to return
01112     //  (pgn.is_unbounded() && (pgn.holes_begin() == pgn.holes_end()))
01113   }
01114   
01115   void _intersection(const Aos_2& arr)
01116   {
01117     Aos_2* res_arr = new Aos_2(m_traits);
01118     Gps_intersection_functor<Aos_2> func;
01119     overlay(*m_arr, arr, *res_arr, func);
01120     delete m_arr; // delete the previous arrangement
01121     
01122     m_arr = res_arr;
01123     remove_redundant_edges();
01124   }
01125   
01126   void _intersection(const Aos_2& arr1,
01127                      const Aos_2& arr2,
01128                      Aos_2& res) 
01129   {
01130     Gps_intersection_functor<Aos_2> func;
01131     overlay(arr1, arr2, res, func);
01132     _remove_redundant_edges(&res);
01133     
01134   }
01135   
01136   template <class Polygon_>
01137     void _intersection(const Polygon_& pgn)
01138   {
01139     if (_is_empty(pgn))
01140       this->clear();
01141     if (_is_plane(pgn)) return;
01142     if (this->is_empty()) return;
01143     if (this->is_plane())
01144     {
01145       Aos_2* arr = new Aos_2(m_traits);
01146       _insert(pgn, *arr);
01147       delete (this->m_arr);
01148       this->m_arr = arr;
01149       return;
01150     }
01151     
01152     Aos_2 second_arr;
01153     _insert(pgn, second_arr);
01154     _intersection(second_arr);
01155   }
01156   
01157   void _intersection(const Self& other)
01158   {
01159     if (other.is_empty())
01160     {
01161       m_arr->clear();
01162       return;
01163     }
01164     if (other.is_plane()) return;
01165     if (this->is_empty()) return;
01166     if (this->is_plane())
01167     {
01168       *(this->m_arr) = *(other.m_arr);
01169       return;
01170     }
01171     
01172     _intersection(*(other.m_arr));
01173   }
01174   
01175   void _join(const Aos_2& arr)
01176   {
01177     Aos_2* res_arr = new Aos_2(m_traits);
01178     Gps_join_functor<Aos_2> func;
01179     overlay(*m_arr, arr, *res_arr, func);
01180     delete m_arr; // delete the previous arrangement
01181     
01182     m_arr = res_arr;
01183     remove_redundant_edges();
01184   }
01185   
01186   void _join(const Aos_2& arr1, const Aos_2& arr2,
01187              Aos_2& res) 
01188   {
01189     Gps_join_functor<Aos_2> func;
01190     overlay(arr1, arr2, res, func);
01191     _remove_redundant_edges(&res);
01192     
01193   }
01194   
01195   template <class Polygon_>
01196     void _join(const Polygon_& pgn)
01197   {
01198     if (_is_empty(pgn)) return;
01199     if (_is_plane(pgn))
01200     {
01201       this->clear();
01202       
01203       // Even in an empty arrangement there can be several faces
01204       // (because of the topology traits).
01205       for (Face_iterator fit = this->m_arr->faces_begin();
01206            fit != this->m_arr->faces_end(); ++fit)
01207         fit->set_contained(true);
01208       return;
01209     }
01210     if (this->is_empty())
01211     {
01212       Aos_2* arr = new Aos_2(m_traits);
01213       _insert(pgn, *arr);
01214       delete (this->m_arr);
01215       this->m_arr = arr;
01216       return;
01217     }
01218     if (this->is_plane()) return;
01219     
01220     Aos_2 second_arr;
01221     _insert(pgn, second_arr);
01222     _join(second_arr);
01223   }
01224   
01225   
01226   void _join(const Self& other)
01227   {
01228     if (other.is_empty()) return;
01229     if (other.is_plane())
01230     {
01231       this->clear();
01232 
01233       // Even in an empty arrangement there can be several faces
01234       // (because of the topology traits).
01235       for (Face_iterator fit = this->m_arr->faces_begin();
01236            fit != this->m_arr->faces_end(); ++fit)
01237         fit->set_contained(true);
01238       return;
01239     }
01240     if (this->is_empty())
01241     {
01242       *(this->m_arr) = *(other.m_arr);
01243       return;
01244     }
01245     if (this->is_plane()) return;
01246     _join(*(other.m_arr));
01247   }
01248   
01249   void _difference(const Aos_2& arr)
01250   {
01251     Aos_2* res_arr = new Aos_2(m_traits);
01252     Gps_difference_functor<Aos_2> func;
01253     overlay(*m_arr, arr, *res_arr, func);
01254     delete m_arr; // delete the previous arrangement
01255     
01256     m_arr = res_arr;
01257     remove_redundant_edges();
01258     fix_curves_direction();
01259   }
01260   
01261   void _difference(const Aos_2& arr1, const Aos_2& arr2,
01262                    Aos_2& res) 
01263   {
01264     Gps_difference_functor<Aos_2> func;
01265     overlay(arr1, arr2, res, func);
01266     _remove_redundant_edges(&res);
01267     _fix_curves_direction(res);
01268     
01269   }
01270   
01271   template <class Polygon_>
01272     void _difference(const Polygon_& pgn)
01273   {
01274     if (_is_empty(pgn)) return;
01275     if (_is_plane(pgn))
01276     {
01277       this->clear();
01278       return;
01279     }
01280     if (this->is_empty()) return;    
01281     if (this->is_plane())
01282     {
01283       Aos_2* arr = new Aos_2(m_traits);
01284       _insert(pgn, *arr);
01285       delete (this->m_arr);
01286       this->m_arr = arr;
01287       this->complement();
01288       return;
01289     }
01290     
01291     Aos_2 second_arr;
01292     _insert(pgn, second_arr);
01293     _difference(second_arr);
01294   }
01295   
01296   
01297   void _difference(const Self& other)
01298   {
01299     if (other.is_empty()) return;
01300     if (other.is_plane())
01301     {
01302       this->clear();
01303       return;
01304     }
01305     if (this->is_empty()) return;
01306     if (this->is_plane())
01307     {
01308       *(this->m_arr) = *(other.m_arr);
01309       this->complement();
01310       return;
01311     }
01312     
01313     _difference(*(other.m_arr));
01314   }
01315   
01316   void _symmetric_difference(const Aos_2& arr)
01317   {
01318     Aos_2* res_arr = new Aos_2(m_traits);
01319     Gps_sym_diff_functor<Aos_2> func;
01320     overlay(*m_arr, arr, *res_arr, func);
01321     delete m_arr; // delete the previous arrangement
01322     
01323     m_arr = res_arr;
01324     remove_redundant_edges();
01325     fix_curves_direction();
01326   }
01327   
01328   void _symmetric_difference(const Aos_2& arr1,
01329                              const Aos_2& arr2,
01330                              Aos_2& res) 
01331   {
01332     Gps_sym_diff_functor<Aos_2> func;
01333     overlay(arr1, arr2, res, func);
01334     _remove_redundant_edges(&res);
01335     _fix_curves_direction(res);
01336   }
01337   
01338   template <class Polygon_>
01339     void _symmetric_difference(const Polygon_& pgn)
01340   {
01341     if (_is_empty(pgn)) return;
01342     
01343     if (_is_plane(pgn))
01344     {
01345       this->complement();
01346       return;
01347     }
01348     if (this->is_empty())
01349     {
01350       Aos_2* arr = new Aos_2(m_traits);
01351       _insert(pgn, *arr);
01352       delete (this->m_arr);
01353       this->m_arr = arr;
01354       return;
01355     }
01356     
01357     if (this->is_plane())
01358     {
01359       Aos_2* arr = new Aos_2(m_traits);
01360       _insert(pgn, *arr);
01361       delete (this->m_arr);
01362       this->m_arr = arr;
01363       this->complement();
01364       return;
01365     }
01366     
01367     Aos_2 second_arr;
01368     _insert(pgn, second_arr);
01369     _symmetric_difference(second_arr);
01370   }
01371   
01372   
01373   void _symmetric_difference(const Self& other)
01374   {
01375     if (other.is_empty()) return;
01376     
01377     if (other.is_plane())
01378     {
01379       this->complement();
01380       return;
01381     }
01382     if (this->is_empty())
01383     {
01384       *(this->m_arr) = *(other.m_arr);
01385       return;
01386     }
01387     
01388     if (this->is_plane())
01389     {
01390       *(this->m_arr) = *(other.m_arr);
01391       this->complement();
01392       return;
01393     }
01394     
01395     _symmetric_difference(*(other.m_arr));
01396   }
01397   
01398 };
01399 
01400 #include <CGAL/Boolean_set_operations_2/Gps_on_surface_base_2_impl.h>
01401 
01402 CGAL_END_NAMESPACE
01403 
01404 #endif // CGAL_GPS_ON_SURFACE_BASE_2_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines