BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Arrangement_2/Arrangement_on_surface_2_impl.h
Go to the documentation of this file.
00001 // Copyright (c) 2005, 2009  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: 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_impl.h $
00015 // $Id: Arrangement_on_surface_2_impl.h 50552 2009-07-11 14:37:26Z efif $
00016 // 
00017 //
00018 // Author(s)     : Ron Wein          <wein@post.tau.ac.il>
00019 //                 Efi Fogel         <efif@post.tau.ac.il>
00020 //                 Eric Berberich    <ericb@post.tau.ac.il>
00021 //                 (based on old version by: Iddo Hanniel,
00022 //                                           Eyal Flato,
00023 //                                           Oren Nechushtan,
00024 //                                           Ester Ezra,
00025 //                                           Shai Hirsch,
00026 //                                           and Eugene Lipovetsky)
00027 //
00028 #ifndef CGAL_ARRANGEMENT_ON_SURFACE_2_IMPL_H
00029 #define CGAL_ARRANGEMENT_ON_SURFACE_2_IMPL_H
00030 
00031 #ifndef CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE
00032 #define CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE 0
00033 #endif
00034 
00040 #include <CGAL/function_objects.h> 
00041 
00042 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE
00043 #include <CGAL/Arr_topology_traits/Sign_of_path.h>
00044 #endif
00045 
00046 CGAL_BEGIN_NAMESPACE
00047 
00048 //-----------------------------------------------------------------------------
00049 // Default constructor.
00050 //
00051 template<class GeomTraits, class TopTraits>
00052 Arrangement_on_surface_2<GeomTraits, TopTraits>::Arrangement_on_surface_2 () :
00053   m_topol_traits()
00054 {
00055   
00056   typedef has_Arr_left_side_tag<GeomTraits> Cond_left;
00057   typedef CGALi::Validate_left_side_tag< GeomTraits, Cond_left::value > 
00058     Validate_left_side_tag;
00059   void (Validate_left_side_tag::*pleft)(void) =
00060     &Validate_left_side_tag::missing__Arr_left_side_tag;
00061   (void)pleft;
00062   
00063  typedef has_Arr_bottom_side_tag<GeomTraits> Cond_bottom;
00064   typedef CGALi::Validate_bottom_side_tag< GeomTraits, Cond_bottom::value > 
00065     Validate_bottom_side_tag;
00066   void (Validate_bottom_side_tag::*pbottom)(void) =
00067     &Validate_bottom_side_tag::missing__Arr_bottom_side_tag;
00068   (void)pbottom;
00069 
00070  typedef has_Arr_top_side_tag<GeomTraits> Cond_top;
00071   typedef CGALi::Validate_top_side_tag< GeomTraits, Cond_top::value > 
00072     Validate_top_side_tag;
00073   void (Validate_top_side_tag::*ptop)(void) =
00074     &Validate_top_side_tag::missing__Arr_top_side_tag;
00075   (void)ptop;
00076 
00077  typedef has_Arr_right_side_tag<GeomTraits> Cond_right;
00078   typedef CGALi::Validate_right_side_tag< GeomTraits, Cond_right::value > 
00079     Validate_right_side_tag;
00080   void (Validate_right_side_tag::*pright)(void) =
00081     &Validate_right_side_tag::missing__Arr_right_side_tag;
00082   (void)pright;
00083 
00084   // Initialize the DCEL structure to represent an empty arrangement.
00085   m_topol_traits.init_dcel ();
00086 
00087   // Allocate the traits.
00088   m_geom_traits = new Traits_adaptor_2;
00089   m_own_traits = true;
00090 
00091   init_boundary_types();
00092 }
00093 
00094 //-----------------------------------------------------------------------------
00095 // Copy constructor.
00096 //
00097 template<class GeomTraits, class TopTraits>
00098 Arrangement_on_surface_2<GeomTraits, TopTraits>::
00099 Arrangement_on_surface_2(const Self& arr) :
00100   m_geom_traits (NULL),
00101   m_own_traits (false)
00102 {
00103   assign (arr);
00104 }
00105 
00106 //-----------------------------------------------------------------------------
00107 // Constructor given a traits object.
00108 //
00109 template<class GeomTraits, class TopTraits>
00110 Arrangement_on_surface_2<GeomTraits, TopTraits>::
00111 Arrangement_on_surface_2(const Geometry_traits_2 * geom_traits) :
00112   m_topol_traits (geom_traits)
00113 {
00114   
00115  typedef has_Arr_left_side_tag<GeomTraits> Cond_left;
00116   typedef CGALi::Validate_left_side_tag< GeomTraits, Cond_left::value > 
00117     Validate_left_side_tag;
00118   void (Validate_left_side_tag::*pleft)(void) =
00119     &Validate_left_side_tag::missing__Arr_left_side_tag;
00120   (void)pleft;
00121   
00122  typedef has_Arr_bottom_side_tag<GeomTraits> Cond_bottom;
00123   typedef CGALi::Validate_bottom_side_tag< GeomTraits, Cond_bottom::value > 
00124     Validate_bottom_side_tag;
00125   void (Validate_bottom_side_tag::*pbottom)(void) =
00126     &Validate_bottom_side_tag::missing__Arr_bottom_side_tag;
00127   (void)pbottom;
00128 
00129  typedef has_Arr_top_side_tag<GeomTraits> Cond_top;
00130   typedef CGALi::Validate_top_side_tag< GeomTraits, Cond_top::value > 
00131     Validate_top_side_tag;
00132   void (Validate_top_side_tag::*ptop)(void) =
00133     &Validate_top_side_tag::missing__Arr_top_side_tag;
00134   (void)ptop;
00135 
00136  typedef has_Arr_right_side_tag<GeomTraits> Cond_right;
00137   typedef CGALi::Validate_right_side_tag< GeomTraits, Cond_right::value > 
00138     Validate_right_side_tag;
00139   void (Validate_right_side_tag::*pright)(void) =
00140     &Validate_right_side_tag::missing__Arr_right_side_tag;
00141   (void)pright;
00142 
00143   // Initialize the DCEL structure to represent an empty arrangement.
00144   m_topol_traits.init_dcel ();
00145 
00146   // Set the traits.
00147   m_geom_traits = static_cast<const Traits_adaptor_2*> (geom_traits);
00148   m_own_traits = false;
00149 
00150   init_boundary_types();
00151 }
00152 
00153 //-----------------------------------------------------------------------------
00154 // Assignment operator.
00155 //
00156 template<class GeomTraits, class TopTraits>
00157 Arrangement_on_surface_2<GeomTraits, TopTraits>&
00158 Arrangement_on_surface_2<GeomTraits, TopTraits>::operator= (const Self& arr)
00159 {
00160   // Check for self-assignment.
00161   if (this == &arr)
00162     return (*this);
00163 
00164   assign (arr);
00165   return (*this);
00166 }
00167 
00168 //-----------------------------------------------------------------------------
00169 // Assign an arrangement.
00170 //
00171 template<class GeomTraits, class TopTraits>
00172 void Arrangement_on_surface_2<GeomTraits, TopTraits>::assign (const Self& arr)
00173 {
00174   // Clear the current contents of the arrangement.
00175   clear();
00176 
00177   // Notify the observers that an assignment is to take place.
00178   _notify_before_assign (arr);
00179 
00180   // Assign the topology-traits object.
00181   m_topol_traits.assign (arr.m_topol_traits);
00182 
00183   // Go over the vertices and create duplicates of the stored points.
00184   typename Dcel::Vertex_iterator  vit;
00185   Point_2                        *dup_p;
00186   DVertex                        *p_v;
00187 
00188   for (vit = _dcel().vertices_begin(); vit != _dcel().vertices_end(); ++vit)
00189   {
00190     p_v = &(*vit);
00191 
00192     if (! p_v->has_null_point())
00193     {
00194       // Create the duplicate point and store it in the points container.
00195       dup_p = _new_point (p_v->point());
00196 
00197       // Associate the vertex with the duplicated point.
00198       p_v->set_point (dup_p);
00199     }
00200   }
00201 
00202   // Go over the edge and create duplicates of the stored curves.
00203   typename Dcel::Edge_iterator     eit;
00204   X_monotone_curve_2              *dup_cv;
00205   DHalfedge                       *p_e;
00206 
00207   for (eit = _dcel().edges_begin(); eit != _dcel().edges_end(); ++eit)
00208   {
00209     p_e = &(*eit);
00210 
00211     if (! p_e->has_null_curve())
00212     {
00213       // Create the duplicate curve and store it in the curves container.
00214       dup_cv = _new_curve (p_e->curve());
00215 
00216       // Associate the halfedge (and its twin) with the duplicated curve. 
00217       p_e->set_curve (dup_cv);
00218     }
00219   }
00220 
00221   // Take care of the traits object.
00222   if (m_own_traits && m_geom_traits != NULL)
00223     delete m_geom_traits;
00224 
00225   if (arr.m_own_traits)
00226     m_geom_traits = new Traits_adaptor_2;
00227   else
00228     m_geom_traits = arr.m_geom_traits;
00229   m_own_traits = arr.m_own_traits;
00230 
00231   // Notify the observers that the assignment has been performed.
00232   _notify_after_assign ();
00233 
00234   init_boundary_types();
00235 
00236   return;
00237 }
00238 
00239 //-----------------------------------------------------------------------------
00240 // Destructor.
00241 //
00242 template<class GeomTraits, class TopTraits>
00243 Arrangement_on_surface_2<GeomTraits, TopTraits>::~Arrangement_on_surface_2 ()
00244 {  
00245   // Free all stored points.
00246   typename Dcel::Vertex_iterator       vit;
00247 
00248   for (vit = _dcel().vertices_begin(); vit != _dcel().vertices_end(); ++vit)
00249   {
00250     if (! vit->has_null_point())
00251       _delete_point (vit->point());
00252   }
00253 
00254   // Free all stores curves.
00255   typename Dcel::Edge_iterator         eit;
00256 
00257   for (eit = _dcel().edges_begin(); eit != _dcel().edges_end(); ++eit)
00258   {
00259     if (! eit->has_null_curve())
00260       _delete_curve (eit->curve());
00261   }
00262 
00263   // Clear the DCEL.
00264   _dcel().delete_all();
00265 
00266   // Free the traits object, if necessary.
00267   if (m_own_traits)
00268     delete m_geom_traits;
00269 
00270   // Detach all observers still attached to the arrangement.
00271   Observers_iterator  iter = m_observers.begin();
00272   Observers_iterator  next;
00273   Observers_iterator  end = m_observers.end();
00274 
00275   while (iter != end)
00276   {
00277     next = iter;
00278     ++next;
00279     (*iter)->detach();
00280     iter = next;
00281   }
00282 }
00283 
00284 //-----------------------------------------------------------------------------
00285 // Clear the arrangement.
00286 //
00287 template<class GeomTraits, class TopTraits>
00288 void Arrangement_on_surface_2<GeomTraits, TopTraits>::clear ()
00289 {
00290   // Notify the observers that we are about to clear the arragement.
00291   _notify_before_clear ();
00292 
00293   // Free all stored points.
00294   typename Dcel::Vertex_iterator       vit;
00295 
00296   for (vit = _dcel().vertices_begin(); vit != _dcel().vertices_end(); ++vit)
00297   {
00298     if (! vit->has_null_point())
00299       _delete_point (vit->point());
00300   }
00301 
00302   // Free all stores curves.
00303   typename Dcel::Edge_iterator         eit;
00304 
00305   for (eit = _dcel().edges_begin(); eit != _dcel().edges_end(); ++eit)
00306   {
00307     if (! eit->has_null_curve())
00308       _delete_curve (eit->curve());
00309   }
00310 
00311   // Clear the DCEL and construct an empty arrangement.
00312   _dcel().delete_all();
00313   m_topol_traits.init_dcel ();
00314 
00315   // Notify the observers that we have just cleared the arragement.
00316   _notify_after_clear ();
00317 
00318   return;
00319 }
00320 
00321 //-----------------------------------------------------------------------------
00322 // Insert a point as an isolated vertex in the interior of a given face.
00323 //
00324 template<class GeomTraits, class TopTraits>
00325 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Vertex_handle
00326 Arrangement_on_surface_2<GeomTraits, TopTraits>::
00327 insert_in_face_interior(const Point_2& p, Face_handle f)
00328 {
00329   DFace          *p_f = _face (f);
00330 
00331 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE
00332     std::cout << "Aos_2: insert_in_face_interior (interface)" << std::endl;
00333     std::cout << "pt   : " << p << std::endl;
00334     std::cout << "face : " << &(*f) << std::endl;
00335 #endif
00336 
00337   // Create a new vertex associated with the given point.
00338   // We assume the point has no boundary conditions.
00339   DVertex         *v = _create_vertex (p);
00340   Vertex_handle   vh (v);
00341 
00342   // Insert v as an isolated vertex inside the given face.
00343   _insert_isolated_vertex (p_f, v);
00344 
00345   // Return a handle to the new isolated vertex.
00346   return (vh);
00347 }
00348 
00349 //-----------------------------------------------------------------------------
00350 // Insert an x-monotone curve into the arrangement as a new hole (inner
00351 // component) inside the given face.
00352 //
00353 template<class GeomTraits, class TopTraits>
00354 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Halfedge_handle
00355 Arrangement_on_surface_2<GeomTraits, TopTraits>::
00356 insert_in_face_interior(const X_monotone_curve_2& cv, Face_handle f)
00357 {
00358 
00359 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE
00360     std::cout << "Aos_2: insert_in_face_interior (interface)" << std::endl;
00361     std::cout << "cv   : " << cv << std::endl;
00362     std::cout << "face : " << &(*f) << std::endl;
00363 #endif
00364 
00365   DFace               *p_f = _face (f);
00366 
00367   // Check if cv's left end has boundary conditions, and obtain a vertex v1
00368   // that corresponds to this end.
00369   const Arr_parameter_space  ps_x1 =
00370     m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MIN_END);
00371   const Arr_parameter_space  ps_y1 =
00372     m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MIN_END);
00373   DHalfedge           *fict_prev1 = NULL;
00374 
00375   DVertex * v1 = (ps_x1 == ARR_INTERIOR && ps_y1 == ARR_INTERIOR) ?
00376     // The curve has a valid left endpoint: Create a new vertex associated
00377     // with the curve's left endpoint.
00378     _create_vertex (m_geom_traits->construct_min_vertex_2_object()(cv)) :
00379     // Locate the DCEL features that will be used for inserting the curve's
00380     // left end.
00381     _place_and_set_curve_end (p_f, cv, ARR_MIN_END, ps_x1, ps_y1, &fict_prev1);
00382 
00383   // Check if cv's right end has boundary conditions, and obtain a vertex v2
00384   // that corresponds to this end.
00385   const Arr_parameter_space  ps_x2 =
00386     m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MAX_END);
00387   const Arr_parameter_space  ps_y2 =
00388     m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MAX_END);
00389   DHalfedge           *fict_prev2 = NULL;
00390 
00391   DVertex * v2 = (ps_x2 == ARR_INTERIOR && ps_y2 == ARR_INTERIOR) ?
00392     // The curve has a valid right endpoint: Create a new vertex associated
00393     // with the curve's right endpoint.
00394     _create_vertex (m_geom_traits->construct_max_vertex_2_object()(cv)) :
00395     // Locate the DCEL features that will be used for inserting the curve's
00396     // right end.
00397     _place_and_set_curve_end (p_f, cv, ARR_MAX_END, ps_x2, ps_y2, &fict_prev2);
00398 
00399   // Create the edge connecting the two vertices (note we know v1 is 
00400   // lexicographically smaller than v2).
00401   DHalfedge       *new_he;
00402 
00403   if (fict_prev1 == NULL && fict_prev2 == NULL)
00404   {
00405     // Both vertices represent valid points.
00406     new_he = _insert_in_face_interior (cv, p_f, v1, v2, SMALLER);
00407   }
00408   else if (fict_prev1 == NULL && fict_prev2 != NULL)
00409   {
00410     // v1 represents a valid point and v2 is inserted using its predecessor.
00411     new_he = _insert_from_vertex (cv, fict_prev2, v1, LARGER);
00412     new_he = new_he->opposite();
00413   }
00414   else if (fict_prev1 != NULL && fict_prev2 == NULL)
00415   {
00416     // v1 is inserted using its predecessor and v2 represents a valid point.
00417     new_he = _insert_from_vertex (cv, fict_prev1, v2, SMALLER);
00418   }
00419   else
00420   {
00421     // Both vertices are inserted using their predecessor halfedges.
00422     // Note that in this case we may create a new face.
00423     bool        new_face_created = false;
00424 
00425     new_he = _insert_at_vertices (cv,
00426                                   fict_prev1, 
00427                                   fict_prev2,
00428                                   SMALLER,
00429                                   new_face_created);
00430   
00431     if (new_face_created)
00432     {
00433       CGAL_assertion (! new_he->is_on_inner_ccb());
00434       _relocate_in_new_face (new_he);
00435     }
00436   }
00437 
00438   // Return a handle to the new halfedge directed from left to right.
00439   return (Halfedge_handle (new_he));
00440 }
00441 
00442 //-----------------------------------------------------------------------------
00443 // Insert an x-monotone curve into the arrangement, such that its left 
00444 // endpoint corresponds to a given arrangement vertex.
00445 //
00446 template<class GeomTraits, class TopTraits>
00447 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Halfedge_handle
00448 Arrangement_on_surface_2<GeomTraits, TopTraits>::
00449 insert_from_left_vertex(const X_monotone_curve_2& cv, 
00450                         Vertex_handle v,
00451                         Face_handle f)
00452 {
00453   CGAL_precondition_code (
00454     const bool at_obnd1 = !m_geom_traits->is_closed_2_object()(cv, ARR_MIN_END));
00455   CGAL_precondition_msg 
00456     ((! at_obnd1 &&
00457       m_geom_traits->equal_2_object()
00458       (v->point(), 
00459        m_geom_traits->construct_min_vertex_2_object()(cv))) ||
00460      (at_obnd1 && v->is_at_open_boundary()),
00461      "The input vertex should be the left curve end.");
00462 
00463   // Check if cv's right end has boundary conditions. If not, create a vertex
00464   // that corresponds to the right endpoint.
00465   const Arr_parameter_space  ps_x2 =
00466     m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MAX_END);
00467   const Arr_parameter_space  ps_y2 =
00468     m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MAX_END);
00469   DVertex             *v2 = NULL;
00470   DHalfedge           *fict_prev2 = NULL;
00471 
00472   if (ps_x2 == ARR_INTERIOR && ps_y2 == ARR_INTERIOR)
00473   {
00474     // The curve has a valid right endpoint: Create a new vertex associated
00475     // with the curve's right endpoint.
00476     v2 = _create_vertex (m_geom_traits->construct_max_vertex_2_object()(cv));
00477   }
00478 
00479   // Check if the given vertex, corresponding to the left curve end, has no
00480   // incident edges. 
00481   if (v->degree() == 0)
00482   {
00483     // The given vertex is an isolated one: We should in fact insert the curve
00484     // in the interior of the face containing this vertex.
00485     DVertex      *v1 = _vertex (v);
00486     DIso_vertex  *iv = NULL;
00487     DFace        *p_f = NULL;
00488 
00489     if (v->is_isolated())
00490     {
00491       // Obtain the face from the isolated vertex.
00492       iv = v1->isolated_vertex();
00493       p_f = iv->face();
00494     }
00495     else
00496     {
00497       // In this case the face that contains v should be provided by the user.
00498       CGAL_precondition (f != Face_handle());
00499       p_f = _face (f);
00500     }
00501 
00502     // If the vertex that corresponds to cv's right end has boundary
00503     // conditions, create it now.
00504     if (v2 == NULL)
00505     {    
00506       // Locate the DCEL features that will be used for inserting the curve's
00507       // right end.
00508       v2 = _place_and_set_curve_end (p_f, cv, ARR_MAX_END, ps_x2, ps_y2,
00509                                      &fict_prev2);
00510     }
00511 
00512     if (iv != NULL)
00513     {
00514       // Remove the isolated vertex v1, as it will not be isolated any more.
00515       p_f->erase_isolated_vertex (iv);
00516       _dcel().delete_isolated_vertex (iv);
00517     }
00518 
00519     // Create the edge connecting the two vertices (note that we know that
00520     // v1 is smaller than v2).
00521     DHalfedge  *new_he;
00522 
00523     if (fict_prev2 == NULL)
00524     {
00525       new_he = _insert_in_face_interior (cv, p_f, v1, v2,
00526                                          SMALLER);
00527     }
00528     else
00529     {
00530       new_he = _insert_from_vertex (cv,
00531                                     fict_prev2, v1,
00532                                     LARGER);
00533       new_he = new_he->opposite();
00534     }
00535 
00536     // Return a handle to the new halfedge directed from v1 to v2.
00537     return (Halfedge_handle (new_he));
00538   }
00539 
00540   // Go over the incident halfedges around v and find the halfedge after
00541   // which the new curve should be inserted.
00542   DHalfedge  *prev1 = _locate_around_vertex (_vertex (v), cv, ARR_MIN_END);
00543   DFace      *f1 = prev1->is_on_inner_ccb() ? prev1->inner_ccb()->face() :
00544                                               prev1->outer_ccb()->face();
00545 
00546   CGAL_assertion_msg
00547     (prev1 != NULL,
00548      "The inserted curve cannot be located in the arrangement.");
00549 
00550   // If the vertex that corresponds to cv's right end has boundary conditions,
00551   // create it now.
00552   if (v2 == NULL)
00553   {    
00554     // Locate the DCEL features that will be used for inserting the curve's
00555     // right end.
00556     v2 = _place_and_set_curve_end (f1, cv, ARR_MAX_END, ps_x2, ps_y2,
00557                                    &fict_prev2);
00558   }
00559 
00560   // Perform the insertion (note that we know that prev1->vertex is smaller
00561   // than v2).
00562   DHalfedge  *new_he;
00563 
00564   if (fict_prev2 == NULL)
00565   {
00566     // Insert the halfedge given the predecessor halfedge of v1.
00567     new_he = _insert_from_vertex (cv, prev1, v2, SMALLER);
00568   }
00569   else
00570   {
00571     // Insert the halfedge given the two predecessor halfedges.
00572     // Note that in this case we may create a new face.
00573     bool        new_face_created = false;
00574 
00575     new_he = _insert_at_vertices (cv,
00576                                   prev1, 
00577                                   fict_prev2,
00578                                   SMALLER,
00579                                   new_face_created);
00580   
00581     if (new_face_created)
00582     {
00583       CGAL_assertion (! new_he->is_on_inner_ccb());
00584       _relocate_in_new_face (new_he);
00585     }
00586   }
00587 
00588   // Return a handle to the halfedge directed toward the new vertex v2.
00589   return (Halfedge_handle (new_he));
00590 }
00591 
00592 //-----------------------------------------------------------------------------
00593 // Insert an x-monotone curve into the arrangement, such that one its left
00594 // endpoint corresponds to a given arrangement vertex, given the exact place
00595 // for the curve in the circular list around this vertex.
00596 //
00597 template<class GeomTraits, class TopTraits>
00598 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Halfedge_handle
00599 Arrangement_on_surface_2<GeomTraits, TopTraits>::
00600 insert_from_left_vertex(const X_monotone_curve_2& cv,
00601                         Halfedge_handle prev)
00602 {
00603 
00604 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE
00605     std::cout << "Aos_2: insert_from_left_vertex (interface)" << std::endl;
00606     std::cout << "cv   : " << cv << std::endl;
00607     if (!prev->has_null_curve()) {
00608         std::cout << "prev : " << prev ->curve() << std::endl;
00609     } else {
00610       std::cout << "prev : fictitious" << std::endl;
00611   }
00612   std::cout << "dir  : " << prev ->direction() << std::endl;
00613 #endif
00614 
00615   CGAL_precondition_code (
00616     const bool at_obnd1 = !m_geom_traits->is_closed_2_object()(cv, ARR_MIN_END));
00617   CGAL_precondition_msg
00618     ((! at_obnd1 &&
00619       m_geom_traits->equal_2_object()
00620       (prev->target()->point(), 
00621        m_geom_traits->construct_min_vertex_2_object()(cv))) ||
00622      (at_obnd1 && prev->target()->is_at_open_boundary()),
00623      "The target of the input halfedge should be the left curve end.");
00624 
00625   CGAL_precondition_msg
00626     (at_obnd1 || _locate_around_vertex (_vertex(prev->target()),
00627                                        cv, ARR_MIN_END) == _halfedge(prev),
00628      "In the clockwise order of curves around the vertex, "
00629      " cv must succeed the curve of prev.");
00630 
00631   // Get the predecessor halfedge for the insertion of the left curve end.
00632   DHalfedge           *prev1 = _halfedge (prev);
00633   DFace               *f1 = _face (prev->face());
00634 
00635   // Check if cv's right end has boundary conditions, and obtain a vertex
00636   // that corresponds to this end.
00637   const Arr_parameter_space  ps_x2 =
00638     m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MAX_END);
00639   const Arr_parameter_space  ps_y2 =
00640     m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MAX_END);
00641   DHalfedge           *fict_prev2 = NULL;
00642 
00643   DVertex * v2 = (ps_x2 == ARR_INTERIOR && ps_y2 == ARR_INTERIOR) ?
00644     // The curve has a valid right endpoint: Create a new vertex associated
00645     // with the curve's right endpoint.
00646     _create_vertex (m_geom_traits->construct_max_vertex_2_object()(cv)) :
00647     // Locate the DCEL features that will be used for inserting the curve's
00648     // right end.
00649     _place_and_set_curve_end (f1, cv, ARR_MAX_END, ps_x2, ps_y2, &fict_prev2);
00650 
00651   // Perform the insertion (note that we know that prev1->vertex is smaller
00652   // than v2).
00653   DHalfedge  *new_he;
00654 
00655   if (fict_prev2 == NULL)
00656   {
00657     // Insert the halfedge given the predecessor halfedge of the left vertex.
00658     new_he = _insert_from_vertex (cv, prev1, v2, SMALLER);
00659   }
00660   else
00661   {
00662     // Insert the halfedge given the two predecessor halfedges.
00663     // Note that in this case we may create a new face.
00664     bool        new_face_created = false;
00665 
00666     new_he = _insert_at_vertices (cv, prev1, fict_prev2, SMALLER,
00667                                   new_face_created);
00668   
00669     if (new_face_created)
00670     {
00671       CGAL_assertion (! new_he->is_on_inner_ccb());
00672       _relocate_in_new_face (new_he);
00673     }
00674   }
00675 
00676   // Return a handle to the halfedge directed toward the new vertex v2.
00677   return (Halfedge_handle (new_he));
00678 }
00679 
00680 //-----------------------------------------------------------------------------
00681 // Insert an x-monotone curve into the arrangement, such that its right
00682 // endpoint corresponds to a given arrangement vertex.
00683 //
00684 template<class GeomTraits, class TopTraits>
00685 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Halfedge_handle
00686 Arrangement_on_surface_2<GeomTraits, TopTraits>::
00687 insert_from_right_vertex(const X_monotone_curve_2& cv,
00688                          Vertex_handle v, Face_handle f)
00689 {
00690   CGAL_precondition_code
00691     (const bool at_obnd2 = 
00692      !m_geom_traits->is_closed_2_object()(cv, ARR_MAX_END));
00693   CGAL_precondition_msg 
00694     ((! at_obnd2 &&
00695       m_geom_traits->equal_2_object()
00696       (v->point(), 
00697        m_geom_traits->construct_max_vertex_2_object()(cv))) ||
00698      (at_obnd2 && v->is_at_open_boundary()),
00699      "The input vertex should be the right curve end.");
00700 
00701   // Check if cv's left end has boundary conditions. If not, create a vertex
00702   // that corresponds to the left endpoint.
00703   const Arr_parameter_space  ps_x1 =
00704     m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MIN_END);
00705   const Arr_parameter_space  ps_y1 =
00706     m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MIN_END);
00707   DVertex             *v1 = NULL;
00708   DHalfedge           *fict_prev1 = NULL;
00709 
00710   if (ps_x1 == ARR_INTERIOR && ps_y1 == ARR_INTERIOR)
00711   {
00712     // The curve has a valid left endpoint: Create a new vertex associated
00713     // with the curve's left endpoint.
00714     v1 = _create_vertex (m_geom_traits->construct_min_vertex_2_object()(cv));
00715   }
00716 
00717   // Check if the given vertex, corresponding to the right curve end, has no
00718   // incident edges. 
00719   if (v->degree() == 0)
00720   {
00721     // The given vertex is an isolated one: We should in fact insert the curve
00722     // in the interior of the face containing this vertex.
00723     DVertex      *v2 = _vertex (v);
00724     DIso_vertex  *iv = NULL;
00725     DFace        *p_f = NULL;
00726 
00727     if (v->is_isolated())
00728     {
00729       // Obtain the face from the isolated vertex.
00730       iv = v2->isolated_vertex();
00731       p_f = iv->face();
00732     }
00733     else
00734     {
00735       // In this case the face that contains v should be provided by the user.
00736       CGAL_precondition (f != Face_handle());
00737       p_f = _face (f);
00738     }
00739 
00740     // If the vertex that corresponds to cv's left end has boundary
00741     // conditions, create it now.
00742     if (v1 == NULL)
00743     {    
00744       // Locate the DCEL features that will be used for inserting the curve's
00745       // left end.
00746       v1 = _place_and_set_curve_end (p_f, cv, ARR_MIN_END, ps_x1, ps_y1,
00747                                      &fict_prev1);
00748     }
00749 
00750     if (iv != NULL)
00751     {
00752       // Remove the isolated vertex v2, as it will not be isolated any more.
00753       p_f->erase_isolated_vertex (iv);
00754       _dcel().delete_isolated_vertex (iv);
00755     }
00756 
00757     // Create the edge connecting the two vertices (note that we know that
00758     // v1 is smaller than v2).
00759     DHalfedge  *new_he;
00760 
00761     if (fict_prev1 == NULL)
00762     {
00763       new_he = _insert_in_face_interior (cv, p_f, v1, v2, SMALLER);
00764     }
00765     else
00766     {
00767       new_he = _insert_from_vertex (cv, fict_prev1, v2, SMALLER);
00768     }
00769     
00770     // Return a handle to the new halfedge whose target is the new vertex v1.
00771     return (Halfedge_handle (new_he->opposite()));
00772   }
00773 
00774   // Go over the incident halfedges around v and find the halfedge after
00775   // which the new curve should be inserted.
00776   DHalfedge  *prev2 = _locate_around_vertex (_vertex (v), cv, ARR_MAX_END);
00777   DFace      *f2 = prev2->is_on_inner_ccb() ? prev2->inner_ccb()->face() :
00778                                               prev2->outer_ccb()->face();
00779 
00780   CGAL_assertion_msg
00781     (prev2 != NULL,
00782      "The inserted curve cannot be located in the arrangement.");
00783 
00784   // If the vertex that corresponds to cv's left end has boundary conditions,
00785   // create it now.
00786   if (v1 == NULL)
00787   {    
00788     // Locate the DCEL features that will be used for inserting the curve's
00789     // left end.
00790     v1 = _place_and_set_curve_end (f2, cv, ARR_MIN_END, ps_x1, ps_y1,
00791                                    &fict_prev1);
00792   }
00793 
00794   // Perform the insertion (note that we know that prev2->vertex is larger
00795   // than v1).
00796   DHalfedge  *new_he;
00797 
00798   if (fict_prev1 == NULL)
00799   {
00800     // Insert the halfedge given the predecessor halfedge of v2.
00801     new_he = _insert_from_vertex (cv, prev2, v1, LARGER);
00802   }
00803   else
00804   {
00805     // Insert the halfedge given the two predecessor halfedges.
00806     // Note that in this case we may create a new face.
00807     bool        new_face_created = false;
00808 
00809     new_he = _insert_at_vertices (cv, prev2, fict_prev1, LARGER,
00810                                   new_face_created);
00811   
00812     if (new_face_created)
00813     {
00814       CGAL_assertion (! new_he->is_on_inner_ccb());
00815       _relocate_in_new_face (new_he);
00816     }
00817   }
00818 
00819   // Return a handle to the halfedge directed toward the new vertex v1.
00820   return (Halfedge_handle (new_he));
00821 }
00822 
00823 //-----------------------------------------------------------------------------
00824 // Insert an x-monotone curve into the arrangement, such that its right
00825 // endpoint corresponds to a given arrangement vertex, given the exact place
00826 // for the curve in the circular list around this vertex.
00827 //
00828 template<class GeomTraits, class TopTraits>
00829 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Halfedge_handle
00830 Arrangement_on_surface_2<GeomTraits, TopTraits>::
00831 insert_from_right_vertex(const X_monotone_curve_2& cv,
00832                          Halfedge_handle prev)
00833 {
00834 
00835 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE
00836     std::cout << "Aos_2: insert_from_right_vertexs (interface)" << std::endl;
00837     std::cout << "cv   : " << cv << std::endl;
00838     if (!prev->has_null_curve()) {
00839       std::cout << "prev : " << prev ->curve() << std::endl;
00840   } else {
00841       std::cout << "prev : fictitious" << std::endl;
00842   }
00843   std::cout << "dir  : " << prev->direction() << std::endl;
00844 #endif
00845 
00846   CGAL_precondition_code
00847     (const bool at_obnd2 = 
00848      !m_geom_traits->is_closed_2_object()(cv, ARR_MAX_END));
00849   CGAL_precondition_msg 
00850     ((! at_obnd2 &&
00851       m_geom_traits->equal_2_object()
00852       (prev->target()->point(), 
00853        m_geom_traits->construct_max_vertex_2_object()(cv))) ||
00854      (at_obnd2 && prev->target()->is_at_open_boundary()),
00855      "The input vertex should be the right curve end.");
00856 
00857   CGAL_precondition_msg
00858     (at_obnd2 ||
00859      _locate_around_vertex (_vertex(prev->target()), cv, ARR_MAX_END) ==
00860      _halfedge(prev),
00861      "In the clockwise order of curves around the vertex, "
00862      " cv must succeed the curve of prev.");
00863 
00864   // Get the predecessor halfedge for the insertion of the right curve end.
00865   DHalfedge           *prev2 = _halfedge (prev);
00866   DFace               *f2 = _face (prev->face());
00867 
00868   // Check if cv's left end has boundary conditions, and obtain a vertex v1
00869   // that corresponds to this end.
00870   const Arr_parameter_space  ps_x1 =
00871     m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MIN_END);
00872   const Arr_parameter_space  ps_y1 =
00873     m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MIN_END);
00874   DHalfedge           *fict_prev1 = NULL;
00875 
00876   DVertex * v1 = (ps_x1 == ARR_INTERIOR && ps_y1 == ARR_INTERIOR) ?
00877     // The curve has a valid left endpoint: Create a new vertex associated
00878     // with the curve's left endpoint.
00879     _create_vertex (m_geom_traits->construct_min_vertex_2_object()(cv)) :
00880     // Locate the DCEL features that will be used for inserting the curve's
00881     // left end.
00882     _place_and_set_curve_end (f2, cv, ARR_MIN_END, ps_x1, ps_y1, &fict_prev1);
00883 
00884   // Perform the insertion (note that we know that prev2->vertex is larger
00885   // than v1).
00886   DHalfedge  *new_he;
00887 
00888   if (fict_prev1 == NULL)
00889   {
00890     // Insert the halfedge given the predecessor halfedge of the right vertex.
00891     new_he = _insert_from_vertex (cv, prev2, v1, LARGER);
00892   }
00893   else
00894   {
00895     // Insert the halfedge given the two predecessor halfedges.
00896     // Note that in this case we may create a new face.
00897     bool        new_face_created = false;
00898 
00899     new_he = _insert_at_vertices (cv, prev2, fict_prev1, LARGER,
00900                                   new_face_created);
00901   
00902     if (new_face_created)
00903     {
00904       CGAL_assertion (! new_he->is_on_inner_ccb());
00905       _relocate_in_new_face (new_he);
00906     }
00907   }
00908 
00909   // Return a handle to the halfedge directed toward the new vertex v1.
00910   return (Halfedge_handle (new_he));
00911 }
00912 
00913 //-----------------------------------------------------------------------------
00914 // Insert an x-monotone curve into the arrangement, such that both its
00915 // endpoints corresponds to a given arrangement vertex.
00916 //
00917 template<class GeomTraits, class TopTraits>
00918 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Halfedge_handle
00919 Arrangement_on_surface_2<GeomTraits, TopTraits>::
00920 insert_at_vertices(const X_monotone_curve_2& cv,
00921                    Vertex_handle v1, Vertex_handle v2,
00922                    Face_handle f)
00923 {
00924   // Determine which one of the given vertices mathces the left end of the
00925   // given curve.
00926   const bool at_obnd1 = !m_geom_traits->is_closed_2_object()(cv, ARR_MIN_END);
00927   const bool at_obnd2 = !m_geom_traits->is_closed_2_object()(cv, ARR_MAX_END);
00928 
00929   Arr_curve_end      ind1;
00930   Arr_curve_end      ind2;
00931 
00932   if (! at_obnd1)
00933   {
00934     CGAL_precondition_code (Vertex_handle v_right);
00935 
00936     if (! v1->is_at_open_boundary() &&
00937         m_geom_traits->equal_2_object()
00938         (v1->point(), 
00939          m_geom_traits->construct_min_vertex_2_object()(cv)))
00940     {
00941       ind1 = ARR_MIN_END;
00942       ind2 = ARR_MAX_END;
00943       CGAL_precondition_code ( v_right = v2; );
00944     }
00945     else
00946     {
00947       CGAL_precondition_msg
00948         (! v2->is_at_open_boundary() &&
00949          m_geom_traits->equal_2_object()
00950          (v2->point(), 
00951           m_geom_traits->construct_min_vertex_2_object()(cv)),
00952          "One of the input vertices should be the left curve end.");
00953 
00954       ind1 = ARR_MAX_END;
00955       ind2 = ARR_MIN_END;
00956       CGAL_precondition_code ( v_right = v1; );
00957     }
00958 
00959     CGAL_precondition_msg 
00960       ((! at_obnd2 &&
00961         m_geom_traits->equal_2_object()
00962         (v_right->point(), 
00963          m_geom_traits->construct_max_vertex_2_object()(cv))) ||
00964        (at_obnd2 && v_right->is_at_open_boundary()),
00965        "One of the input vertices should be the right curve end.");
00966   }
00967   else
00968   {
00969     if (! at_obnd2)
00970     {
00971       CGAL_precondition_code (Vertex_handle v_left);
00972 
00973       if (! v1->is_at_open_boundary() &&
00974           m_geom_traits->equal_2_object()
00975           (v1->point(), 
00976            m_geom_traits->construct_max_vertex_2_object()(cv)))
00977       {
00978         ind1 = ARR_MAX_END;
00979         ind2 = ARR_MIN_END;
00980         CGAL_precondition_code ( v_left = v2; );
00981       }
00982       else
00983       {
00984         CGAL_precondition_msg
00985           (! v2->is_at_open_boundary() &&
00986            m_geom_traits->equal_2_object()
00987            (v2->point(), 
00988             m_geom_traits->construct_max_vertex_2_object()(cv)),
00989            "One of the input vertices should be the right curve end.");
00990 
00991         ind1 = ARR_MIN_END;
00992         ind2 = ARR_MAX_END;
00993         CGAL_precondition_code ( v_left = v1; );
00994       }
00995 
00996       CGAL_precondition_msg
00997         (at_obnd1 && v_left->is_at_open_boundary(),
00998          "One of the input vertices should be the left curve end.");
00999     }
01000     else
01001     {
01002       Arr_parameter_space  ps_x1 =
01003         m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MIN_END);
01004       Arr_parameter_space  ps_y1 =
01005         m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MIN_END);
01006 
01007       // Check which vertex should be associated with the minimal curve-end
01008       // (so the other is associated with the maximal curve-end).
01009       if (m_topol_traits.are_equal (_vertex (v1), cv, ARR_MIN_END, ps_x1, ps_y1))
01010       {
01011         CGAL_assertion
01012           (m_topol_traits.are_equal
01013            (_vertex (v2), cv, ARR_MAX_END,
01014             m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MAX_END),
01015             m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MAX_END)));
01016 
01017         ind1 = ARR_MIN_END;
01018         ind2 = ARR_MAX_END;
01019       }
01020       else
01021       {
01022         CGAL_assertion (m_topol_traits.are_equal
01023                         (_vertex (v2), cv, ARR_MIN_END, ps_x1, ps_y1));
01024         CGAL_assertion
01025           (m_topol_traits.are_equal
01026            (_vertex (v1), cv, ARR_MAX_END,
01027             m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MAX_END),
01028             m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MAX_END)));
01029 
01030         ind1 = ARR_MAX_END;
01031         ind2 = ARR_MIN_END;
01032       }
01033     }
01034   }
01035 
01036   // Check whether one of the vertices has no incident halfedges.
01037   if (v1->degree() == 0)
01038   {
01039     // Get the face containing the isolated vertex v1.
01040     DVertex      *p_v1 = _vertex (v1);
01041     DIso_vertex  *iv1 = NULL;
01042     DFace        *f1 = NULL;
01043 
01044     if (p_v1->is_isolated())
01045     {
01046       // Obtain the containing face from the isolated vertex record.
01047       iv1 = p_v1->isolated_vertex();
01048       f1 = iv1->face();
01049 
01050       // Remove the isolated vertex v1, as it will not be isolated any more.
01051       f1->erase_isolated_vertex (iv1);
01052       _dcel().delete_isolated_vertex (iv1);
01053     }
01054 
01055     // Check whether the other vertex also has no incident halfedges.
01056     if (v2->degree() == 0)
01057     {
01058       // Both end-vertices are isolated. Make sure they are contained inside
01059       // the same face.
01060       DVertex      *p_v2 = _vertex (v2);
01061       DIso_vertex  *iv2 = NULL;
01062       DFace        *f2 = NULL;
01063 
01064       if (p_v2->is_isolated())
01065       {
01066         // Obtain the containing face from the isolated vertex record.
01067         iv2 = p_v2->isolated_vertex();
01068         f2 = iv2->face();
01069 
01070         CGAL_assertion_msg
01071           (f1 == NULL || f1 == f2,
01072            "The two isolated vertices must be located inside the same face.");
01073 
01074         // Remove the isolated vertex v2, as it will not be isolated any more.
01075         f2->erase_isolated_vertex (iv2);
01076         _dcel().delete_isolated_vertex (iv2);
01077       }
01078       else if(f1 == NULL)
01079       {
01080         // In this case the containing face must be given by the user.
01081         CGAL_precondition (f != Face_handle());
01082       }
01083 
01084       // Perform the insertion.
01085       Comparison_result  res = (ind1 == ARR_MIN_END) ? SMALLER : LARGER;
01086       DHalfedge * new_he = _insert_in_face_interior (cv, f1, p_v1, p_v2, res);
01087 
01088       return (Halfedge_handle (new_he));
01089     }
01090 
01091     // Go over the incident halfedges around v2 and find the halfedge after
01092     // which the new curve should be inserted.
01093     DHalfedge  *prev2 = _locate_around_vertex (_vertex (v2), cv, ind2);
01094     CGAL_assertion_code (
01095       DFace      *f2 = prev2->is_on_inner_ccb() ? prev2->inner_ccb()->face() :
01096                                                   prev2->outer_ccb()->face();
01097     );
01098 
01099     CGAL_assertion_msg
01100       (prev2 != NULL,
01101        "The inserted curve cannot be located in the arrangement.");
01102 
01103     CGAL_assertion_msg
01104       (f1 == NULL || f1 == f2,
01105        "The inserted curve should not intersect the existing arrangement.");
01106 
01107     // Perform the insertion. Note that the returned halfedge is directed
01108     // toward v1 (and not toward v2), so we return its twin.
01109     Comparison_result  res = (ind2 == ARR_MIN_END) ? SMALLER : LARGER;
01110     DHalfedge * new_he = _insert_from_vertex (cv, prev2, p_v1, res);
01111 
01112     return (Halfedge_handle (new_he->opposite()));
01113   }
01114   else if (v2->degree() == 0)
01115   {
01116     // Get the face containing the isolated vertex v2.
01117     DVertex      *p_v2 = _vertex (v2);
01118     DIso_vertex  *iv2 = NULL;
01119     DFace        *f2 = NULL;
01120 
01121     if (v2->is_isolated())
01122     {
01123       // Obtain the containing face from the isolated vertex record.
01124       iv2 = p_v2->isolated_vertex();
01125       f2 = iv2->face();
01126 
01127       // Remove the isolated vertex v2, as it will not be isolated any more.
01128       f2->erase_isolated_vertex (iv2);
01129       _dcel().delete_isolated_vertex (iv2);
01130     }
01131 
01132     // Go over the incident halfedges around v1 and find the halfedge after
01133     // which the new curve should be inserted.
01134     DHalfedge  *prev1 = _locate_around_vertex (_vertex (v1), cv, ind1);
01135     CGAL_assertion_code (
01136       DFace      *f1 = prev1->is_on_inner_ccb() ? prev1->inner_ccb()->face() :
01137                                                   prev1->outer_ccb()->face();
01138     );
01139 
01140     CGAL_assertion_msg
01141       (prev1 != NULL,
01142        "The inserted curve cannot be located in the arrangement.");
01143 
01144     CGAL_assertion_msg
01145       (f2 == NULL || f2 == f1,
01146        "The inserted curve should not intersect the existing arrangement.");
01147 
01148     // Perform the insertion.
01149     Comparison_result  res = (ind1 == ARR_MIN_END) ? SMALLER : LARGER;
01150     DHalfedge         *new_he = _insert_from_vertex (cv, prev1, p_v2, res);
01151 
01152     return (Halfedge_handle (new_he));
01153   }
01154 
01155   // Go over the incident halfedges around v1 and v2 and find the two
01156   // halfedges after which the new curve should be inserted, respectively.
01157   DHalfedge  *prev1 = _locate_around_vertex (_vertex (v1), cv, ind1);
01158   DHalfedge  *prev2 = _locate_around_vertex (_vertex (v2), cv, ind2);
01159 
01160   CGAL_assertion_msg
01161     (prev1 != NULL && prev2 != NULL,
01162      "The inserted curve cannot be located in the arrangement.");
01163 
01164   // Perform the insertion.
01165   return insert_at_vertices(cv, Halfedge_handle(prev1), Halfedge_handle(prev2));
01166 }
01167 
01168 //-----------------------------------------------------------------------------
01169 // Insert an x-monotone curve into the arrangement, such that both its
01170 // endpoints correspond to given arrangement vertices, given the exact
01171 // place for the curve in one of the circular lists around a vertex.
01172 //
01173 template<class GeomTraits, class TopTraits>
01174 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Halfedge_handle
01175 Arrangement_on_surface_2<GeomTraits, TopTraits>::
01176 insert_at_vertices(const X_monotone_curve_2& cv,
01177                    Halfedge_handle prev1,
01178                    Vertex_handle v2)
01179 {
01180   // Determine which one of the given vertices mathces the left end of the
01181   // given curve.
01182   const bool at_obnd1 = !m_geom_traits->is_closed_2_object()(cv, ARR_MIN_END);
01183   const bool at_obnd2 = !m_geom_traits->is_closed_2_object()(cv, ARR_MAX_END);
01184 
01185   Arr_curve_end      ind2;
01186 
01187   if (! at_obnd1)
01188   {
01189     CGAL_precondition_code ( Vertex_handle  v_right; );
01190 
01191     if (! prev1->target()->is_at_open_boundary() &&
01192         m_geom_traits->equal_2_object()
01193         (prev1->target()->point(), 
01194          m_geom_traits->construct_min_vertex_2_object()(cv)))
01195     {
01196       ind2 = ARR_MAX_END;
01197       CGAL_precondition_code ( v_right = v2; );
01198     }
01199     else
01200     {
01201       CGAL_precondition_msg
01202         (! v2->is_at_open_boundary() &&
01203          m_geom_traits->equal_2_object()
01204          (v2->point(), 
01205           m_geom_traits->construct_min_vertex_2_object()(cv)),
01206          "One of the input vertices should be the left curve end.");
01207 
01208       ind2 = ARR_MIN_END;
01209       CGAL_precondition_code ( v_right = prev1->target(); );
01210     }
01211 
01212     CGAL_precondition_msg 
01213       ((! at_obnd2 &&
01214         m_geom_traits->equal_2_object()
01215         (v_right->point(), 
01216          m_geom_traits->construct_max_vertex_2_object()(cv))) ||
01217        (at_obnd2 && v_right->is_at_open_boundary()),
01218        "One of the input vertices should be the right curve end.");
01219   }
01220   else
01221   {
01222     if (! at_obnd2)
01223     {
01224       CGAL_precondition_code ( Vertex_handle  v_left; );
01225 
01226       if (! prev1->target()->is_at_open_boundary() &&
01227           m_geom_traits->equal_2_object()
01228           (prev1->target()->point(), 
01229            m_geom_traits->construct_max_vertex_2_object()(cv)))
01230       {
01231         ind2 = ARR_MIN_END;
01232         CGAL_precondition_code ( v_left = v2; );
01233       }
01234       else
01235       {
01236         CGAL_precondition_msg
01237           (! v2->is_at_open_boundary() &&
01238            m_geom_traits->equal_2_object()
01239            (v2->point(), 
01240             m_geom_traits->construct_max_vertex_2_object()(cv)),
01241            "One of the input vertices should be the right curve end.");
01242 
01243         ind2 = ARR_MAX_END;
01244         CGAL_precondition_code ( v_left = prev1->target(); );
01245       }
01246 
01247       CGAL_precondition_msg
01248         (at_obnd1 && v_left->is_at_open_boundary(),
01249          "One of the input vertices should be the left curve end.");
01250     }
01251     else
01252     {
01253       Arr_parameter_space  ps_x1 =
01254         m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MIN_END);
01255       Arr_parameter_space  ps_y1 =
01256         m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MIN_END);
01257 
01258       // Check which vertex should be associated with the minimal curve-end
01259       // (so the other is associated with the maximal curve-end).
01260       if (m_topol_traits.are_equal (_vertex (prev1->target()),
01261                                 cv, ARR_MIN_END, ps_x1, ps_y1))
01262       {
01263         CGAL_assertion
01264           (m_topol_traits.are_equal
01265            (_vertex (v2), cv, ARR_MAX_END,
01266             m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MAX_END),
01267             m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MAX_END)));
01268 
01269         ind2 = ARR_MAX_END;
01270       }
01271       else
01272       {
01273         CGAL_assertion (m_topol_traits.are_equal
01274                         (_vertex (v2), cv, ARR_MIN_END, ps_x1, ps_y1));
01275         CGAL_assertion
01276           (m_topol_traits.are_equal
01277            (_vertex (prev1->target()), cv, ARR_MAX_END,
01278             m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MAX_END),
01279             m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MAX_END)));
01280 
01281         ind2 = ARR_MIN_END;
01282       }
01283     }
01284   }
01285 
01286   // Check whether v2 is has no incident edges.
01287   if (v2->degree() == 0)
01288   {
01289     // Get the face containing the isolated vertex v2.
01290     DVertex      *p_v2 = _vertex (v2);
01291     DIso_vertex  *iv2 = NULL;
01292     DFace        *f2 = NULL;
01293 
01294     if (v2->is_isolated())
01295     {
01296       iv2 = p_v2->isolated_vertex();
01297       f2 = iv2->face();
01298 
01299       CGAL_assertion_msg
01300         (f2 == _face (prev1->face()),
01301          "The inserted curve should not intersect the existing arrangement.");
01302 
01303       // Remove the isolated vertex v2, as it will not be isolated any more.
01304       f2->erase_isolated_vertex (iv2);
01305       _dcel().delete_isolated_vertex (iv2);
01306     }
01307 
01308     // Perform the insertion.
01309     Comparison_result  res = (ind2 == ARR_MAX_END) ? SMALLER : LARGER;
01310     DHalfedge         *new_he = _insert_from_vertex (cv,
01311                                                      _halfedge (prev1), p_v2,
01312                                                      res);
01313 
01314     return (Halfedge_handle (new_he));
01315   }
01316 
01317   // Go over the incident halfedges around v2 and find the halfedge after
01318   // which the new curve should be inserted.
01319   DHalfedge  *prev2 = _locate_around_vertex (_vertex (v2), cv, ind2);
01320 
01321   CGAL_assertion_msg
01322     (prev2 != NULL,
01323      "The inserted curve cannot be located in the arrangement.");
01324 
01325   // Perform the insertion.
01326   return (insert_at_vertices (cv,
01327                               prev1,
01328                               Halfedge_handle(prev2)));
01329 }
01330 
01331 //-----------------------------------------------------------------------------
01332 // Insert an x-monotone curve into the arrangement, such that both its
01333 // endpoints correspond to given arrangement vertices, given the exact
01334 // place for the curve in both circular lists around these two vertices.
01335 //
01336 template<class GeomTraits, class TopTraits>
01337 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Halfedge_handle
01338 Arrangement_on_surface_2<GeomTraits, TopTraits>::
01339 insert_at_vertices(const X_monotone_curve_2& cv,
01340                    Halfedge_handle prev1,
01341                    Halfedge_handle prev2)
01342 {
01343 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE
01344     std::cout << "Aos_2: insert_at_vertices (interface)" << std::endl;
01345     std::cout << "cv   : " << cv << std::endl;
01346     if (!prev1->is_fictitious()) {
01347         std::cout << "prev1: " << prev1->curve() << std::endl;
01348     } else {
01349       std::cout << "prev1: fictitious" << std::endl;
01350   }
01351   std::cout << "dir1 : " << prev1->direction() << std::endl;
01352   if (!prev2->is_fictitious()) {
01353       std::cout << "prev2: " << prev2->curve() << std::endl;
01354   } else {
01355       std::cout << "prev2: fictitious" << std::endl;
01356   }
01357   std::cout << "dir2 : " << prev2->direction() << std::endl;
01358 #endif
01359     
01360   // Determine which one of the given vertices (the target vertices of the
01361   // given halfedges) mathces the left end of the given curve.
01362   // Thus, we can determine the comparison result between prev1->target()
01363   // and prev2->target().
01364   const bool at_obnd1 = !m_geom_traits->is_closed_2_object()(cv, ARR_MIN_END);
01365   const bool at_obnd2 = !m_geom_traits->is_closed_2_object()(cv, ARR_MAX_END);
01366   Comparison_result  res;
01367 
01368   if (! at_obnd1)
01369   {
01370     CGAL_precondition_code ( Vertex_handle  v_right; );
01371 
01372     if (! prev1->target()->is_at_open_boundary() &&
01373         m_geom_traits->equal_2_object()
01374         (prev1->target()->point(), 
01375          m_geom_traits->construct_min_vertex_2_object()(cv)))
01376     {
01377       res = SMALLER;
01378       CGAL_precondition_code ( v_right = prev2->target(); );
01379     }
01380     else
01381     {
01382       CGAL_precondition_msg
01383         (! prev2->target()->is_at_open_boundary() &&
01384          m_geom_traits->equal_2_object()
01385          (prev2->target()->point(), 
01386           m_geom_traits->construct_min_vertex_2_object()(cv)),
01387          "One of the input vertices should be the left curve end.");
01388 
01389       res = LARGER;
01390       CGAL_precondition_code ( v_right = prev1->target(); );
01391     }
01392 
01393     CGAL_precondition_msg 
01394       ((! at_obnd2 &&
01395         m_geom_traits->equal_2_object()
01396         (v_right->point(), 
01397          m_geom_traits->construct_max_vertex_2_object()(cv))) ||
01398        (at_obnd2 && v_right->is_at_open_boundary()),
01399        "One of the input vertices should be the right curve end.");
01400   }
01401   else
01402   {
01403     if (! at_obnd2)
01404     {
01405       CGAL_precondition_code ( Vertex_handle  v_left; );
01406 
01407       if (! prev1->target()->is_at_open_boundary() &&
01408           m_geom_traits->equal_2_object()
01409           (prev1->target()->point(), 
01410            m_geom_traits->construct_max_vertex_2_object()(cv)))
01411       {
01412         res = LARGER;
01413         CGAL_precondition_code ( v_left = prev2->target(); );
01414       }
01415       else
01416       {
01417         CGAL_precondition_msg
01418           (! prev2->target()->is_at_open_boundary() &&
01419            m_geom_traits->equal_2_object()
01420            (prev2->target()->point(), 
01421             m_geom_traits->construct_max_vertex_2_object()(cv)),
01422            "One of the input vertices should be the right curve end.");
01423 
01424         res = SMALLER;
01425         CGAL_precondition_code ( v_left = prev1->target(); );
01426       }
01427 
01428       CGAL_precondition_msg
01429         (at_obnd1 && v_left->is_at_open_boundary(),
01430          "One of the input vertices should be the left curve end.");
01431     }
01432     else
01433     {
01434       Arr_parameter_space  ps_x1 =
01435         m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MIN_END);
01436       Arr_parameter_space  ps_y1 =
01437         m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MIN_END);
01438       // Check which vertex should be associated with the minimal curve-end
01439       // (so the other is associated with the maximal curve-end), and
01440       // determine the comparison result of the two vertices accordingly.
01441       if (m_topol_traits.are_equal (_vertex (prev1->target()),
01442                                 cv, ARR_MIN_END, ps_x1, ps_y1))
01443       {
01444         CGAL_assertion
01445           (m_topol_traits.are_equal
01446            (_vertex (prev2->target()), cv, ARR_MAX_END,
01447             m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MAX_END),
01448             m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MAX_END)));
01449 
01450         res = SMALLER;
01451       }
01452       else
01453       {
01454         CGAL_assertion
01455           (m_topol_traits.are_equal
01456            (_vertex (prev2->target()), cv, ARR_MIN_END,
01457             m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MIN_END),
01458             m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MIN_END)));
01459         CGAL_assertion
01460           (m_topol_traits.are_equal
01461            (_vertex (prev1->target()), cv, ARR_MAX_END,
01462             m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MAX_END),
01463             m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MAX_END)));
01464 
01465         res = LARGER;
01466       }
01467     }
01468   }
01469 
01470   // Check if e1 and e2 are on the same connected component.
01471   DHalfedge   *p_prev1 = _halfedge (prev1);
01472   DHalfedge   *p_prev2 = _halfedge (prev2);
01473   DInner_ccb  *hole1 = (p_prev1->is_on_inner_ccb()) ? p_prev1->inner_ccb() :
01474                                                       NULL;
01475   DInner_ccb  *hole2 = (p_prev2->is_on_inner_ccb()) ? p_prev2->inner_ccb() :
01476                                                       NULL;
01477   bool         prev1_before_prev2 = true;
01478 
01479   if (hole1 == hole2 && hole1 != NULL)
01480   {
01481     // If prev1 and prev2 are on different components, the insertion of the
01482     // new curve does not generate a new face, so the way we send these
01483     // halfedge pointers to the auxiliary function _insert_at_vertices() does
01484     // not matter.
01485     // However, in our case, where the two halfedges are reachable from one
01486     // another and are located on the same hole, a new face will be created
01487     // and form a hole inside their current incident face. In this case we
01488     // have to arrange prev1 and prev2 so that the new face (hole) will be
01489     // incident to the correct halfedge, directed from prev1's target to
01490     // prev2's target.
01491     // To do this, we use the topology traits to determine whether prev1 lies
01492     // inside the new face we are about to create (or alternatively, whether
01493     // prev2 does not lie inside this new face).
01494     const unsigned int  dist1 = _halfedge_distance (p_prev1, p_prev2);
01495     const unsigned int  dist2 = _halfedge_distance (p_prev2, p_prev1);
01496 
01497     prev1_before_prev2 = (dist1 > dist2) ?
01498       (_is_inside_new_face (p_prev1, p_prev2, cv)) :
01499       (! _is_inside_new_face (p_prev2, p_prev1, cv));
01500   }
01501 
01502   // We already have the comparsion result of the target vertices of prev1
01503   // and prev2. If however we swap the order of the halfedges, we take the
01504   // opposite comparison result.
01505   if (! prev1_before_prev2)
01506     res = CGAL::opposite (res);
01507 
01508   // Perform the insertion.
01509   bool        new_face_created = false;
01510   DHalfedge  *new_he = (prev1_before_prev2) ?
01511     _insert_at_vertices (cv, p_prev1, p_prev2, res, new_face_created) :
01512     _insert_at_vertices (cv, p_prev2, p_prev1, res, new_face_created);
01513 
01514   if (new_face_created)
01515   {
01516     // In case a new face has been created (pointed by the new halfedge we
01517     // obtained), we have to examine the holes and isolated vertices in the
01518     // existing face (pointed by the twin halfedge) and move the relevant
01519     // holes and isolated vertices into the new face.
01520     _relocate_in_new_face (new_he);
01521   }
01522 
01523   // Return a handle to the new halfedge directed from prev1's target to
01524   // prev2's target. Note that this may be the twin halfedge of the one
01525   // returned by _insert_at_vertices();
01526   if (! prev1_before_prev2)
01527     new_he = new_he->opposite();
01528 
01529   return (Halfedge_handle (new_he));
01530 }
01531 
01532 //-----------------------------------------------------------------------------
01533 // Replace the point associated with the given vertex.
01534 //
01535 template<class GeomTraits, class TopTraits>
01536 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Vertex_handle
01537 Arrangement_on_surface_2<GeomTraits, TopTraits>::
01538 modify_vertex(Vertex_handle vh, const Point_2& p)
01539 {
01540   CGAL_precondition_msg
01541     (! vh->is_at_open_boundary(),
01542      "The modified vertex must not lie on open boundary.");
01543   CGAL_precondition_msg (m_geom_traits->equal_2_object() (vh->point(), p),
01544                          "The new point is different from the current one.");
01545 
01546   // Modify the vertex.
01547   _modify_vertex (_vertex (vh), p);
01548 
01549   // Return a handle to the modified vertex.
01550   return (vh);
01551 }
01552 
01553 //-----------------------------------------------------------------------------
01554 // Remove an isolated vertex from the interior of a given face.
01555 //
01556 template<class GeomTraits, class TopTraits>
01557 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Face_handle
01558 Arrangement_on_surface_2<GeomTraits, TopTraits>::
01559 remove_isolated_vertex(Vertex_handle v)
01560 {
01561   CGAL_precondition (v->is_isolated());
01562 
01563   // Get the face containing v.
01564   DVertex      *p_v = _vertex (v);
01565   DIso_vertex  *iv = p_v->isolated_vertex();
01566   DFace        *p_f = iv->face();
01567   Face_handle   f = Face_handle (p_f);
01568   
01569   // Notify the observers that we are abount to remove a vertex.
01570   _notify_before_remove_vertex (v);
01571 
01572   // Remove the isolated vertex from the face that contains it.
01573   p_f->erase_isolated_vertex (iv);
01574   _dcel().delete_isolated_vertex (iv);
01575 
01576   // Delete the vertex.
01577   _delete_point (p_v->point());
01578   _dcel().delete_vertex (p_v);
01579 
01580   // Notify the observers that the vertex has been removed.
01581   _notify_after_remove_vertex ();
01582 
01583   // Return a handle for the face that used to contain the deleted vertex.
01584   return (f);
01585 }
01586 
01587 //-----------------------------------------------------------------------------
01588 // Replace the x-monotone curve associated with the given edge.
01589 //
01590 template<class GeomTraits, class TopTraits>
01591 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Halfedge_handle
01592 Arrangement_on_surface_2<GeomTraits, TopTraits>::
01593 modify_edge(Halfedge_handle e, const X_monotone_curve_2& cv)
01594 {
01595   CGAL_precondition_msg (! e->is_fictitious(),
01596                          "The edge must be a valid one.");
01597   CGAL_precondition_msg (m_geom_traits->equal_2_object() (e->curve(), cv),
01598                          "The new curve is different from the current one.");
01599 
01600   // Modify the edge.
01601   _modify_edge (_halfedge (e), cv);
01602 
01603   // Return a handle to the modified halfedge.
01604   return (e);
01605 }
01606 
01607 //-----------------------------------------------------------------------------
01608 // Split a given edge into two, and associate the given x-monotone
01609 // curves with the split edges.
01610 //
01611 template<class GeomTraits, class TopTraits>
01612 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Halfedge_handle
01613 Arrangement_on_surface_2<GeomTraits, TopTraits>::
01614 split_edge(Halfedge_handle e,
01615            const X_monotone_curve_2& cv1, const X_monotone_curve_2& cv2)
01616 {
01617   CGAL_precondition_msg (! e->is_fictitious(),
01618                          "The edge must be a valid one.");
01619 
01620   // Get the split halfedge and its twin, its source and target.
01621   DHalfedge * he1 = _halfedge(e);
01622   DHalfedge * he2 = he1->opposite();
01623   DVertex   * source = he2->vertex();
01624   CGAL_precondition_code(DVertex * target = he1->vertex(););
01625 
01626   // Determine the point where we split the halfedge. We also determine which
01627   // curve should be associated with he1 (and he2), which is the curve who
01628   // has an endpoint that equals e's source, and which should be associated
01629   // with the new pair of halfedges we are about to split (the one who has
01630   // an endpoint which equals e's target).
01631   if (m_geom_traits->parameter_space_in_x_2_object()(cv1, ARR_MAX_END) ==
01632       ARR_INTERIOR &&
01633       m_geom_traits->parameter_space_in_y_2_object()(cv1, ARR_MAX_END) ==
01634       ARR_INTERIOR)
01635   {
01636     const Point_2 & cv1_right = 
01637       m_geom_traits->construct_max_vertex_2_object() (cv1);
01638 
01639     if (m_geom_traits->parameter_space_in_x_2_object()(cv2, ARR_MIN_END) ==
01640         ARR_INTERIOR &&
01641         m_geom_traits->parameter_space_in_y_2_object()(cv2, ARR_MIN_END) ==
01642         ARR_INTERIOR &&
01643         m_geom_traits->equal_2_object()(m_geom_traits->
01644                                         construct_min_vertex_2_object()(cv2),
01645                                         cv1_right))
01646     {
01647       // cv1's right endpoint and cv2's left endpoint are equal, so this should
01648       // be the split point. Now we check whether cv1 is incident to e's source
01649       // and cv2 to its target, or vice versa.
01650       if (_are_equal (source, cv1, ARR_MIN_END)) {
01651         CGAL_precondition_msg
01652           (_are_equal (target, cv2, ARR_MAX_END),
01653            "The subcurve endpoints must match e's end vertices.");
01654 
01655         return (Halfedge_handle (_split_edge (he1, cv1_right, cv1, cv2)));
01656       }
01657 
01658       CGAL_precondition_msg
01659         (_are_equal (source, cv2, ARR_MAX_END) &&
01660          _are_equal (target, cv1, ARR_MIN_END),
01661          "The subcurve endpoints must match e's end vertices.");
01662 
01663       return (Halfedge_handle (_split_edge (he1, cv1_right, cv2, cv1)));
01664     }
01665   }
01666   
01667   if (m_geom_traits->parameter_space_in_x_2_object()(cv1, ARR_MIN_END) ==
01668       ARR_INTERIOR &&
01669       m_geom_traits->parameter_space_in_y_2_object()(cv1, ARR_MIN_END) ==
01670       ARR_INTERIOR)
01671   {
01672     const Point_2 & cv1_left = 
01673       m_geom_traits->construct_min_vertex_2_object() (cv1);
01674 
01675     if (m_geom_traits->parameter_space_in_x_2_object()(cv2, ARR_MAX_END) ==
01676         ARR_INTERIOR &&
01677         m_geom_traits->parameter_space_in_y_2_object()(cv2, ARR_MAX_END) ==
01678         ARR_INTERIOR &&
01679         m_geom_traits->equal_2_object()(m_geom_traits->
01680                                         construct_max_vertex_2_object()(cv2),
01681                                         cv1_left))
01682     {
01683       // cv1's left endpoint and cv2's right endpoint are equal, so this should
01684       // be the split point. Now we check whether cv1 is incident to e's source
01685       // and cv2 to its target, or vice versa.
01686       if (_are_equal (source, cv2, ARR_MIN_END)) {
01687         CGAL_precondition_msg
01688           (_are_equal (target, cv1, ARR_MAX_END),
01689            "The subcurve endpoints must match e's end vertices.");
01690 
01691         return (Halfedge_handle (_split_edge (he1, cv1_left, cv2, cv1)));
01692       }
01693 
01694       CGAL_precondition_msg
01695         (_are_equal (source, cv1, ARR_MAX_END) && 
01696          _are_equal (target, cv2, ARR_MIN_END),
01697          "The subcurve endpoints must match e's end vertices.");
01698 
01699       return (Halfedge_handle (_split_edge (he1, cv1_left, cv1, cv2)));
01700     }
01701   }
01702 
01703   CGAL_error_msg ("The two subcurves must have a common endpoint.");
01704   return Halfedge_handle();
01705 }
01706 
01707 //-----------------------------------------------------------------------------
01708 // Merge two edges to form a single edge, and associate the given x-monotone
01709 // curve with the merged edge.
01710 //
01711 template<class GeomTraits, class TopTraits>
01712 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Halfedge_handle
01713 Arrangement_on_surface_2<GeomTraits, TopTraits>::
01714 merge_edge(Halfedge_handle e1, Halfedge_handle e2,
01715            const X_monotone_curve_2& cv)
01716 {
01717   CGAL_precondition_msg (! e1->is_fictitious() && ! e2->is_fictitious(),
01718                          "The edges must be a valid.");
01719 
01720   // Assign pointers to the existing halfedges, such that we have:
01721   //
01722   //            he1      he3
01723   //         -------> ------->
01724   //       (.)      (.)v     (.)
01725   //         <------- <-------
01726   //            he2      he4
01727   //
01728   DHalfedge   *_e1 = _halfedge (e1);
01729   DHalfedge   *_e2 = _halfedge (e2);
01730   DHalfedge   *he1 = NULL;
01731   DHalfedge   *he2 = NULL;
01732   DHalfedge   *he3 = NULL;
01733   DHalfedge   *he4 = NULL;
01734 
01735   if (_e1->vertex() == _e2->opposite()->vertex())
01736   {
01737     he1 = _e1;
01738     he2 = he1->opposite();
01739     he3 = _e2;
01740     he4 = he3->opposite();
01741   }
01742   else if (_e1->opposite()->vertex() == _e2->opposite()->vertex())
01743   {
01744     he2 = _e1;
01745     he1 = he2->opposite();
01746     he3 = _e2;
01747     he4 = he3->opposite();
01748   }
01749   else if (_e1->vertex() == _e2->vertex())
01750   {
01751     he1 = _e1;
01752     he2 = he1->opposite();
01753     he4 = _e2;
01754     he3 = he4->opposite();
01755   }
01756   else if (_e1->opposite()->vertex() == _e2->vertex())
01757   {
01758     he2 = _e1;
01759     he1 = he2->opposite();
01760     he4 = _e2;
01761     he3 = he4->opposite();
01762   }
01763   else
01764   {
01765     CGAL_precondition_msg (false,
01766                            "The input edges do not share a common vertex.");
01767     return Halfedge_handle();
01768   }
01769 
01770   // The vertex we are about to delete is now he1's target vertex.
01771   // Make sure that he1 and he4 are the only halfedges directed to v.
01772   DVertex    *v = he1->vertex();
01773 
01774   CGAL_precondition_msg
01775     (! v->has_null_point(),
01776      "The vertex removed by the merge must not lie on open boundary.");
01777   CGAL_precondition_msg
01778     (he1->next()->opposite() == he4 &&
01779      he4->next()->opposite() == he1,
01780      "The degree of the deleted vertex is greater than 2.");
01781 
01782   // Make sure the curve ends match the end vertices of the merged edge.
01783   CGAL_precondition_msg
01784     ((_are_equal (he2->vertex(), cv, ARR_MIN_END) && 
01785       _are_equal (he3->vertex(), cv, ARR_MAX_END)) ||
01786      (_are_equal (he3->vertex(), cv, ARR_MIN_END) && 
01787       _are_equal (he2->vertex(), cv, ARR_MAX_END)),
01788      "The endpoints of the merged curve must match the end vertices.");
01789 
01790   // Keep pointers to the components that contain two halfedges he3 and he2,
01791   // pointing at the end vertices of the merged halfedge.
01792   DInner_ccb  *ic1 = (he3->is_on_inner_ccb()) ? he3->inner_ccb() : NULL;
01793   DOuter_ccb  *oc1 = (ic1 == NULL) ? he3->outer_ccb() : NULL;
01794 
01795   DInner_ccb  *ic2 = (he4->is_on_inner_ccb()) ? he4->inner_ccb() : NULL;
01796   DOuter_ccb  *oc2 = (ic2 == NULL) ? he4->outer_ccb() : NULL;
01797 
01798   // Notify the observers that we are about to merge an edge.
01799   _notify_before_merge_edge (e1, e2, cv);
01800 
01801   // As he1 and he2 will evetually represent the merged edge, while he3 and he4
01802   // will be deleted, check if the deleted halfedges are represantatives of a
01803   // the CCBs they belong to. If so, replace he3 by he1 and he4 by he2. Note
01804   // that as we just change the component representatives, we do not have to
01805   // notify the observers on the change.
01806   if (oc1 != NULL && oc1->halfedge() == he3)
01807     oc1->set_halfedge (he1);
01808   else if (ic1 != NULL && ic1->halfedge() == he3)
01809     ic1->set_halfedge (he1);
01810 
01811   if (oc2 != NULL && oc2->halfedge() == he4)
01812     oc2->set_halfedge (he2);
01813   else if (ic2 != NULL && ic2->halfedge() == he4)
01814     ic2->set_halfedge (he2);
01815 
01816   // If he3 is the incident halfedge to its target, replace it by he1.
01817   if (he3->vertex()->halfedge() == he3)
01818     he3->vertex()->set_halfedge (he1);
01819 
01820   // Disconnect he3 and he4 from the edge list.
01821   if (he3->next() == he4)
01822   {
01823     // he3 and he4 form an "antenna", so he1 and he2 must be connected
01824     // together.
01825     he1->set_next(he2);
01826   }
01827   else
01828   {
01829     he1->set_next (he3->next());
01830     he4->prev()->set_next (he2);
01831   }
01832 
01833   // Note that he1 (and its twin) is going to represent the merged edge while
01834   // he3 (and its twin) is going to be removed. We therefore associate the
01835   // merged curve with he1 and delete the curve associated with he3.
01836   he1->curve() = cv;
01837   _delete_curve (he3->curve());
01838 
01839   // Set the properties of the merged edge.
01840   he1->set_vertex (he3->vertex());
01841 
01842   // Notify the observers that we are about to delete a vertex.
01843   _notify_before_remove_vertex (Vertex_handle (v));
01844 
01845   // Delete the point associated with the merged vertex.
01846   _delete_point (v->point());
01847 
01848   // Delete the merged vertex.
01849   _dcel().delete_vertex (v);
01850 
01851   // Notify the observers that the vertex has been deleted.
01852   _notify_after_remove_vertex ();
01853 
01854   // Delete the redundant halfedge pair.
01855   _dcel().delete_edge (he3);
01856 
01857   // Create a handle for one of the merged halfedges.
01858   Halfedge_handle   hh (he1);
01859 
01860   // Notify the observers that the edge has been merge.
01861   _notify_after_merge_edge (hh);
01862 
01863   // Return a handle for one of the merged halfedges.
01864   return (hh);
01865 }
01866 
01867 //-----------------------------------------------------------------------------
01868 // Remove an edge from the arrangement.
01869 //
01870 template<class GeomTraits, class TopTraits>
01871 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Face_handle
01872 Arrangement_on_surface_2<GeomTraits, TopTraits>::
01873 remove_edge(Halfedge_handle e, bool remove_source, bool remove_target)
01874 {
01875   CGAL_precondition_msg (! e->is_fictitious(),
01876                          "The edge must be a valid one.");
01877 
01878   DHalfedge   *he1 = _halfedge (e);
01879   DHalfedge   *he2 = he1->opposite();
01880   DInner_ccb  *ic1 = (he1->is_on_inner_ccb()) ? he1->inner_ccb() : NULL;
01881   DOuter_ccb  *oc1 = (ic1 == NULL) ? he1->outer_ccb() : NULL;
01882   DFace       *f1 = (ic1 != NULL) ? ic1->face() : oc1->face();
01883   DInner_ccb  *ic2 = (he2->is_on_inner_ccb()) ? he2->inner_ccb() : NULL;
01884   DOuter_ccb  *oc2 = (ic2 == NULL) ? he2->outer_ccb() : NULL;
01885   DFace       *f2 = (ic2 != NULL) ? ic2->face() : oc2->face();
01886   DFace       *f;
01887 
01888   if (f1 != f2 ||
01889       he1->next() == he2 || he2->next() == he1)
01890   {
01891     // Either the removal of he1 (and its twin halfedge) will cause the two
01892     // incident faces to merge, or these two halfedges form an "antenna".
01893     // In either case, it does not matter which halfedge we send to the
01894     // auxiliary function _remove_edge().
01895     f = _remove_edge (he1, remove_source, remove_target);
01896   }
01897   else
01898   {
01899     // In this case one of the following can happen: (a) a new hole will be
01900     // created by the removal of the edge (case 3.2.1 of the removal
01901     // procedure), or (b) an outer CCB will be split into two (case 3.2.2).
01902     // We begin by locating the leftmost vertex along the path from he1 to its
01903     // twin he2 and the leftmost vertex point along the path from the twin to
01904     // he1 (both paths do not include he1 and he2 themselves).
01905     bool                            is_perimetric1;
01906     bool                            at_open_bnd1;
01907     bool                            is_perimetric2;
01908     bool                            at_open_bnd2;
01909 
01910     std::pair<int, const DVertex*>  v_min1 =
01911       _find_leftmost_vertex_on_closed_loop (he1, is_perimetric1, at_open_bnd1);
01912 
01913     std::pair<int, const DVertex*>  v_min2 =
01914       _find_leftmost_vertex_on_closed_loop (he2, is_perimetric2, at_open_bnd2);
01915 
01916     if (! is_perimetric1 && ! is_perimetric2)
01917     {
01918       CGAL_assertion (! at_open_bnd1 || ! at_open_bnd2);
01919 
01920       // Both paths from he1 to he2 and back from he2 to he1 are not
01921       // perimetric, so case (a) occurs. As we want to determine which
01922       // halfedge points to the new hole that will be create (he1 or he2),
01923       // we have to compare the two leftmost vertices lexicographically,
01924       // first by the indices then by x and y. v_min2 lies to the left of
01925       // v_min1 if and only if he1 points at the hole we are about to create.
01926       //
01927       //         +---------------------+
01928       //         |                     |
01929       //         |   he1    +----+     |
01930       //         +--------->+    |     |
01931       //         |          +----+     |
01932       //         |      v_min1         |
01933       //         |                     |
01934       //  v_min2 +---------------------+
01935       //
01936       // Note that if one of the paths we have examined goes to open boundary
01937       // (and only of the paths may go to open boundary), 
01938       // then it is obvious that the other path becomes a hole in an 
01939       // open face.
01940       if (at_open_bnd2 ||
01941           (!at_open_bnd1 && (v_min1.first > v_min2.first ||
01942                              (v_min1.first == v_min2.first &&
01943                               m_geom_traits->compare_xy_2_object()
01944                               (v_min1.second->point(),
01945                                v_min2.second->point()) == LARGER))))
01946       {
01947         // he1 is directed to the new hole to be created.
01948         f = _remove_edge (he1, remove_source, remove_target);
01949       }
01950       else
01951       {
01952         CGAL_assertion (at_open_bnd1 ||
01953                         (v_min1.first < v_min2.first) ||
01954                         (v_min1.first == v_min2.first &&
01955                          m_geom_traits->compare_xy_2_object()
01956                          (v_min1.second->point(),
01957                           v_min2.second->point()) == SMALLER));
01958 
01959         // he2 is directed to the new hole to be created. As its source and
01960         // target are swapped with respect to the end-vertices of the given
01961         // halfedge e, we swap the roles of the two input flags.
01962         f = _remove_edge (he2, remove_target, remove_source);
01963       }
01964     }
01965     else if (! is_perimetric1 && is_perimetric2)
01966     {
01967       // Case (a) occurs and he1 is directed to the new hole that will be
01968       // created.
01969       f = _remove_edge (he1, remove_source, remove_target);
01970     }
01971     else if (is_perimetric1 && ! is_perimetric2)
01972     {
01973       // Case (a) occurs and he2 is directed to the new hole that will be
01974       // created. As its source and target are swapped with respect to the
01975       // end-vertices of the given halfedge e, we swap the roles of the two
01976       // input flags.
01977       f = _remove_edge (he2, remove_target, remove_source);
01978     }
01979     else
01980     {
01981       // If both paths are perimetric, then case (b) takes place:
01982       f = _remove_edge (he1, remove_source, remove_target);
01983     }
01984   }
01985 
01986   return (Face_handle (f));
01987 }
01988 
01989 //-----------------------------------------------------------------------------
01990 // Protected member functions (for internal use).
01991 //-----------------------------------------------------------------------------
01992 
01993 //-----------------------------------------------------------------------------
01994 // Locate the place for the given curve around the given vertex.
01995 //
01996 template<class GeomTraits, class TopTraits>
01997 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::DHalfedge*
01998 Arrangement_on_surface_2<GeomTraits, TopTraits>::
01999 _locate_around_vertex(DVertex *v,
02000                       const X_monotone_curve_2& cv, Arr_curve_end ind) const
02001 {
02002   // Check if the given curve-end has boundary conditions.
02003   const Arr_parameter_space  ps_x =
02004     m_geom_traits->parameter_space_in_x_2_object()(cv, ind);
02005   const Arr_parameter_space  ps_y =
02006     m_geom_traits->parameter_space_in_y_2_object()(cv, ind);
02007 
02008   if (ps_x != ARR_INTERIOR || ps_y != ARR_INTERIOR)
02009   {
02010     // Use the topology-traits class to locate the predecessor halfedge for
02011     // cv around the given vertex.
02012     return (m_topol_traits.locate_around_boundary_vertex (v, cv, ind, ps_x, ps_y));
02013   }
02014 
02015   // In case of a non-boundary vertex, we look for the predecessor around v.
02016   // Get the first incident halfedge around v and the next halfedge.
02017   DHalfedge   *first = v->halfedge();
02018   DHalfedge   *curr = first;
02019 
02020   if (curr == NULL)
02021     return (NULL);
02022 
02023   DHalfedge   *next = curr->next()->opposite();
02024 
02025   // In case there is only one halfedge incident to v, return this halfedge.
02026   if (curr == next)
02027     return (curr);
02028 
02029   // Otherwise, we traverse the halfedges around v until we find the pair
02030   // of adjacent halfedges between which we should insert cv.
02031   typename Traits_adaptor_2::Is_between_cw_2  is_between_cw =
02032     m_geom_traits->is_between_cw_2_object();
02033 
02034   bool       eq_curr, eq_next;
02035 
02036   while (! is_between_cw (cv, (ind == ARR_MIN_END),
02037                           curr->curve(), 
02038                           (curr->direction() == ARR_RIGHT_TO_LEFT),
02039                           next->curve(), 
02040                           (next->direction() == ARR_RIGHT_TO_LEFT),
02041                           v->point(), eq_curr, eq_next))
02042   {
02043     // If cv equals one of the curves associated with the halfedges, it is
02044     // an illegal input curve, as it already exists in the arrangement.
02045     if (eq_curr || eq_next)
02046       return (NULL);
02047 
02048     // Move to the next pair of incident halfedges.
02049     curr = next;
02050     next = curr->next()->opposite();
02051 
02052     // If we completed a full traversal around v without locating the
02053     // place for cv, it follows that cv overlaps and existing curve.
02054     if (curr == first)
02055       return (NULL);
02056   }
02057 
02058   // Return the halfedge we have located.
02059   return (curr);
02060 }
02061 
02062 //-----------------------------------------------------------------------------
02063 // Compute the distance (in halfedges) between two halfedges.
02064 //
02065 template<class GeomTraits, class TopTraits>
02066 unsigned int
02067 Arrangement_on_surface_2<GeomTraits, TopTraits>::
02068 _halfedge_distance(const DHalfedge *e1, const DHalfedge *e2) const
02069 {
02070   CGAL_precondition (e1 != e2);
02071   if (e1 == e2)
02072     return (0);
02073 
02074   // Traverse the halfedge chain from e1 until reaching e2.
02075   const DHalfedge   *curr = e1->next();
02076   unsigned int       dist = 1;
02077 
02078   while (curr != e2)
02079   {
02080     // If we have returned to e1, e2 is not reachable from e1.
02081     if (curr == e1)
02082     {
02083       CGAL_error();
02084       return (0);
02085     }
02086 
02087     curr = curr->next();
02088     dist++;
02089   }
02090 
02091   // We have located e2 along the boundary of e1's component - return the
02092   // distance (number of halfedges) between e1 and e2.
02093   return (dist);
02094 }
02095 
02096 //-----------------------------------------------------------------------------
02097 // Move a given outer CCB from one face to another.
02098 //
02099 template<class GeomTraits, class TopTraits>
02100 void Arrangement_on_surface_2<GeomTraits, TopTraits>::
02101 _move_outer_ccb (DFace *from_face, DFace *to_face, DHalfedge *he)
02102 {
02103   // Get the DCEL record that represents the outer CCB.
02104   DOuter_ccb  *oc = he->outer_ccb();
02105 
02106   CGAL_assertion (oc->face() == from_face);
02107 
02108   // Notify the observers that we are about to move an outer CCB.
02109   Ccb_halfedge_circulator   circ = (Halfedge_handle(he))->ccb();
02110 
02111   _notify_before_move_outer_ccb (Face_handle (from_face),
02112                                  Face_handle (to_face),
02113                                  circ);
02114 
02115   // Remove the hole from the current face.
02116   from_face->erase_outer_ccb (oc);
02117 
02118   // Modify the component that represents the hole.
02119   oc->set_face (to_face);
02120   to_face->add_outer_ccb (oc, he);
02121   
02122   // Notify the observers that we have moved the outer CCB.
02123   _notify_after_move_outer_ccb (circ);
02124 
02125   return;
02126 }
02127 
02128 //-----------------------------------------------------------------------------
02129 // Move a given inner CCB (hole) from one face to another.
02130 //
02131 template<class GeomTraits, class TopTraits>
02132 void Arrangement_on_surface_2<GeomTraits, TopTraits>::
02133 _move_inner_ccb (DFace *from_face, DFace *to_face, DHalfedge *he)
02134 {
02135   // Get the DCEL record that represents the inner CCB.
02136   DInner_ccb  *ic = he->inner_ccb();
02137 
02138   CGAL_assertion (ic->face() == from_face);
02139 
02140   // Notify the observers that we are about to move an inner CCB.
02141   Ccb_halfedge_circulator   circ = (Halfedge_handle(he))->ccb();
02142 
02143   _notify_before_move_inner_ccb (Face_handle (from_face),
02144                                  Face_handle (to_face),
02145                                  circ);
02146 
02147   // Remove the hole from the current face.
02148   from_face->erase_inner_ccb (ic);
02149 
02150   // Modify the component that represents the hole.
02151   ic->set_face (to_face);
02152   to_face->add_inner_ccb (ic, he);
02153   
02154   // Notify the observers that we have moved the inner CCB.
02155   _notify_after_move_inner_ccb (circ);
02156 
02157   return;
02158 }
02159 
02160 //-----------------------------------------------------------------------------
02161 // Insert the given vertex as an isolated vertex inside the given face.
02162 //
02163 template<class GeomTraits, class TopTraits>
02164 void Arrangement_on_surface_2<GeomTraits, TopTraits>::
02165 _insert_isolated_vertex (DFace *f, DVertex *v)
02166 {
02167 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE
02168   std::cout << "Aos_2: _insert_isolated_verteex (internal)" << std::endl;
02169   if (!v->has_null_point()) {
02170       std::cout << "v->point: " << v->point() << std::endl;
02171   }
02172   std::cout << "face   : " << f << std::endl;
02173 #endif
02174   
02175   Face_handle     fh (f);
02176   Vertex_handle   vh (v);
02177 
02178   // Notify the observers that we are about to insert an isolated vertex
02179   // inside f.
02180   _notify_before_add_isolated_vertex (fh, vh);
02181 
02182   // Create an isolated vertex-information object,
02183   DIso_vertex    *iv = _dcel().new_isolated_vertex();
02184 
02185   // Set a pointer to the face containing the vertex.
02186   iv->set_face (f);
02187 
02188   // Initiate a new hole inside the given face.
02189   f->add_isolated_vertex (iv, v);
02190   
02191   // Associate the information with the vertex.
02192   v->set_isolated_vertex (iv);
02193 
02194   // Notify the observers that we have formed a new isolated vertex.
02195   _notify_after_add_isolated_vertex (vh);
02196 
02197   return;
02198 }
02199 
02200 //-----------------------------------------------------------------------------
02201 // Move a given isolated vertex from one face to another.
02202 //
02203 template<class GeomTraits, class TopTraits>
02204 void Arrangement_on_surface_2<GeomTraits, TopTraits>::
02205 _move_isolated_vertex(DFace *from_face, DFace *to_face, DVertex *v)
02206 {
02207   // Get the DCEL isolated-vertex record.
02208   DIso_vertex  *iv = v->isolated_vertex();
02209 
02210   // Notify the observers that we are about to move an isolated vertex.
02211   Vertex_handle   vh (v);
02212 
02213   _notify_before_move_isolated_vertex (Face_handle (from_face),
02214                                        Face_handle (to_face),
02215                                        vh);
02216 
02217   // Set the new face is the isolated vertex-information object.
02218   iv->set_face (to_face);
02219 
02220   // Move the isolated vertex from the first face to the other.
02221   from_face->erase_isolated_vertex (iv);
02222   to_face->add_isolated_vertex (iv, v);
02223 
02224   // Notify the observers that we have moved the isolated vertex.
02225   _notify_after_move_isolated_vertex (vh);
02226 
02227   return;
02228 }
02229 
02230 //-----------------------------------------------------------------------------
02231 // Create a new vertex and associate it with the given point.
02232 //
02233 template<class GeomTraits, class TopTraits>
02234 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::DVertex*
02235 Arrangement_on_surface_2<GeomTraits, TopTraits>::
02236 _create_vertex (const Point_2& p)
02237 {
02238   // Notify the observers that we are about to create a new vertex.
02239   Point_2  *p_p = _new_point (p);
02240 
02241   _notify_before_create_vertex (*p_p);
02242 
02243   // Create a new vertex and associate it with the given point.
02244   DVertex         *v = _dcel().new_vertex();
02245 
02246   v->set_point (p_p);
02247   v->set_boundary (ARR_INTERIOR, ARR_INTERIOR);
02248 
02249   // Notify the observers that we have just created a new vertex.
02250   Vertex_handle   vh (v);
02251   _notify_after_create_vertex (vh);
02252 
02253   return (v);
02254 }
02255 
02256 //-----------------------------------------------------------------------------
02257 // Create a new vertex on boundary
02258 //
02259 template<class GeomTraits, class TopTraits>
02260 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::DVertex*
02261 Arrangement_on_surface_2<GeomTraits, TopTraits>::
02262 _create_boundary_vertex(const X_monotone_curve_2& cv, Arr_curve_end ind,
02263                         Arr_parameter_space ps_x, Arr_parameter_space ps_y)
02264 {
02265   CGAL_precondition (ps_x != ARR_INTERIOR || ps_y != ARR_INTERIOR);
02266 
02267   // Notify the observers that we are about to create a new boundary vertex.
02268   _notify_before_create_boundary_vertex (cv, ind, ps_x, ps_y);
02269 
02270   // Create a new vertex and set its boundary conditions.
02271   DVertex         *v = _dcel().new_vertex();
02272 
02273   v->set_boundary (ps_x, ps_y);
02274 
02275   // Act according to the boundary type if there is one:
02276   if (is_open (ps_x, ps_y))
02277   {
02278     // The curve-end lies on open boundary so the vertex is not associated with
02279     // a valid point.
02280     v->set_point (NULL);
02281   }
02282   else
02283   {
02284     // Create a boundary vertex associated with a valid point.
02285     Point_2 * p_p = (ind == ARR_MIN_END) ?
02286       _new_point (m_geom_traits->construct_min_vertex_2_object()(cv)) :
02287       _new_point (m_geom_traits->construct_max_vertex_2_object()(cv));
02288 
02289     v->set_point (p_p);
02290   }
02291 
02292   // Notify the observers that we have just created a new boundary vertex.
02293   Vertex_handle   vh (v);
02294   _notify_after_create_boundary_vertex (vh);
02295 
02296   return (v);
02297 }
02298 
02299 //-----------------------------------------------------------------------------
02300 // Locate the DCEL features that will be used for inserting the given curve
02301 // end, which has a boundary condition, and set the proper vertex there.
02302 //
02303 template<class GeomTraits, class TopTraits>
02304 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::DVertex* 
02305 Arrangement_on_surface_2<GeomTraits, TopTraits>::
02306 _place_and_set_curve_end(DFace *f,
02307                          const X_monotone_curve_2& cv, Arr_curve_end ind,
02308                          Arr_parameter_space ps_x, Arr_parameter_space ps_y,
02309                          DHalfedge **p_pred)
02310 {
02311   // Use the topology traits to locate the DCEL feature that contains the
02312   // given curve end.
02313   CGAL::Object obj = m_topol_traits.place_boundary_vertex (f, cv, ind, ps_x, ps_y);
02314   DVertex     *v;
02315   DHalfedge   *fict_he;
02316 
02317   // Act according to the result type.
02318   if (CGAL::assign (fict_he, obj))
02319   {
02320     // The curve end is located on a fictitious edge. We first create a new
02321     // vertex that corresponds to the curve end.
02322     v = _create_boundary_vertex (cv, ind, ps_x, ps_y);
02323 
02324     // Split the fictitious halfedge at the newly created vertex.
02325     // The returned halfedge is the predecessor for the insertion of the curve
02326     // end around v.
02327     _notify_before_split_fictitious_edge (Halfedge_handle (fict_he),
02328                                           Vertex_handle (v));
02329 
02330     *p_pred = m_topol_traits.split_fictitious_edge (fict_he, v);
02331 
02332     _notify_after_split_fictitious_edge (Halfedge_handle (*p_pred),
02333                                          Halfedge_handle ((*p_pred)->next()));
02334   }
02335   else if (CGAL::assign (v, obj))
02336   {
02337     // In this case we are given an existing vertex that represents the curve
02338     // end. We now have to locate the predecessor edge for the insertion of cv
02339     // around this vertex.
02340     *p_pred = m_topol_traits.locate_around_boundary_vertex(v, cv, ind, ps_x, ps_y);
02341   }
02342   else
02343   {
02344     CGAL_assertion (obj.is_empty());
02345 
02346     // In this case we have to create a new vertex that reprsents the given
02347     // curve end.
02348     v = _create_boundary_vertex (cv, ind, ps_x, ps_y);
02349 
02350     // Notify the topology traits on the creation of the boundary vertex.
02351     m_topol_traits.notify_on_boundary_vertex_creation (v, cv, ind, ps_x, ps_y);
02352 
02353     // There are no edges incident to v, therefore no predecessor halfedge.
02354     *p_pred = NULL;
02355   }
02356 
02357   // Return the vertex that represents the curve end.
02358   return (v);
02359 }
02360 
02361 //-----------------------------------------------------------------------------
02362 // Insert an x-monotone curve into the arrangement, such that both its
02363 // endpoints correspond to free arrangement vertices (newly created vertices
02364 // or existing isolated vertices), so a new inner CCB is formed in the face
02365 // that contains the two vertices.
02366 //
02367 template<class GeomTraits, class TopTraits>
02368 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::DHalfedge*
02369 Arrangement_on_surface_2<GeomTraits, TopTraits>::
02370 _insert_in_face_interior(const X_monotone_curve_2& cv,
02371                          DFace *f, DVertex *v1, DVertex *v2,
02372                          Comparison_result res)
02373 {
02374 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE
02375   std::cout << "Aos_2: _insert_in_face_interior (internal)" << std::endl;
02376   std::cout << "cv   : " << cv << std::endl;
02377   std::cout << "face   : " << f << std::endl;
02378   if (!v1->has_null_point()) {
02379     std::cout << "v1->point: " << v1->point() << std::endl;
02380   }
02381   if (!v2->has_null_point()) {
02382     std::cout << "v2->point: " << v2->point() << std::endl;
02383   }
02384 #endif
02385 
02386   // Notify the observers that we are about to create a new edge.
02387   _notify_before_create_edge (cv, Vertex_handle (v1), Vertex_handle (v2));
02388 
02389   // Create a pair of twin halfedges connecting the two vertices,
02390   // and link them together to form a new connected component, a hole in f.
02391   DHalfedge           *he1 = _dcel().new_edge();
02392   DHalfedge           *he2 = he1->opposite();
02393   DInner_ccb          *ic = _dcel().new_inner_ccb();
02394   X_monotone_curve_2  *dup_cv = _new_curve (cv);
02395 
02396   ic->set_face (f);
02397   he1->set_curve (dup_cv);
02398 
02399   he1->set_next (he2);
02400   he1->set_vertex (v1);
02401   he1->set_inner_ccb (ic);
02402 
02403   he2->set_next (he1);
02404   he2->set_vertex (v2);
02405   he2->set_inner_ccb (ic);
02406 
02407   // Assign the incident halfedges of the two new vertices.
02408   v1->set_halfedge (he1);
02409   v2->set_halfedge (he2);
02410 
02411   // Set the direction of the halfedges: res indicates the direction of he2,
02412   // as it is the comparison result between its source (v1) and target (v2).
02413   const Arr_halfedge_direction   dir =
02414     (res == SMALLER) ? ARR_LEFT_TO_RIGHT : ARR_RIGHT_TO_LEFT;
02415   he2->set_direction (dir);
02416 
02417   // Create a handle to the new halfedge pointing at the curve target.
02418   Halfedge_handle   hh (he2);
02419 
02420   // Notify the observers that we have created a new edge.
02421   _notify_after_create_edge (hh);
02422 
02423   // Notify the observers that we are about to form a new inner CCB inside f.
02424   _notify_before_add_inner_ccb (Face_handle (f), hh);
02425 
02426   // Initiate a new inner CCB inside the given face.
02427   f->add_inner_ccb (ic, he2);
02428 
02429   // Notify the observers that we have formed a new inner CCB.
02430   _notify_after_add_inner_ccb (hh->ccb());
02431 
02432   return (he2);
02433 }
02434 
02435 //-----------------------------------------------------------------------------
02436 // Insert an x-monotone curve into the arrangement, such that one of its
02437 // endpoints corresponds to a given arrangement vertex, given the exact
02438 // place for the curve in the circular list around this vertex. The other
02439 // endpoint corrsponds to a free vertex (a newly created vertex or an
02440 // isolated vertex).
02441 //
02442 template<class GeomTraits, class TopTraits>
02443 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::DHalfedge*
02444 Arrangement_on_surface_2<GeomTraits, TopTraits>::
02445 _insert_from_vertex(const X_monotone_curve_2& cv,
02446                     DHalfedge *prev, DVertex *v,
02447                     Comparison_result cmp)
02448 {
02449 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE
02450   std::cout << "Aos_2: _insert_from_vertex (internal)" << std::endl;
02451   std::cout << "cv   : " << cv << std::endl;
02452   if (!prev->has_null_curve()) {
02453     std::cout << "prev: " << prev->curve() << std::endl;
02454   } else {
02455     std::cout << "prev: fictitious" << std::endl;
02456   }
02457   std::cout << "pref: " << (prev->is_on_inner_ccb() ? 
02458                             prev->inner_ccb()->face() :
02459                             prev->outer_ccb()->face()) << std::endl;
02460   if (!v->has_null_point()) {
02461     std::cout << "v->point: " << v->point() << std::endl;
02462   }
02463   std::cout << "cmp  : " << cmp << std::endl;
02464 #endif
02465 
02466   // Get the incident face of the previous halfedge. Note that this will also
02467   // be the incident face of the two new halfedges we are about to create.
02468   DInner_ccb  *ic = (prev->is_on_inner_ccb()) ? prev->inner_ccb() : NULL;
02469   DOuter_ccb  *oc = (ic == NULL) ? prev->outer_ccb() : NULL;
02470 
02471   // The first vertex is the one that the prev halfedge points to.
02472   // The second vertex is given by v.
02473   DVertex     *v1 = prev->vertex();
02474   DVertex     *v2 = v;
02475 
02476   // Notify the observers that we are about to create a new edge.
02477   _notify_before_create_edge (cv, Vertex_handle (v1), Vertex_handle (v2));
02478 
02479   // Create a pair of twin halfedges connecting the two vertices,
02480   // and associate them with the given curve.
02481   DHalfedge           *he1 = _dcel().new_edge();
02482   DHalfedge           *he2 = he1->opposite();
02483   X_monotone_curve_2  *dup_cv = _new_curve (cv);
02484 
02485   he1->set_curve (dup_cv);
02486 
02487   he1->set_vertex (v1);
02488   he2->set_vertex (v2);
02489 
02490   // Set the component for the new halfedge pair.
02491   if (oc != NULL)
02492   {
02493     // On an outer component:
02494     he1->set_outer_ccb (oc);
02495     he2->set_outer_ccb (oc);
02496   }
02497   else
02498   {
02499     // On an inner component:
02500     he1->set_inner_ccb (ic);
02501     he2->set_inner_ccb (ic);
02502   }
02503 
02504   // Associate the incident halfedge of the new vertex.
02505   v2->set_halfedge (he2);
02506 
02507   // Link the new halfedges around the existing vertex v1.
02508   he2->set_next (he1);
02509   he1->set_next (prev->next());
02510 
02511   prev->set_next (he2);
02512 
02513   // Set the direction of the halfedges: res indicates the direction of he2,
02514   // as it is the comparison result between its source and target (v).
02515   const Arr_halfedge_direction   dir =
02516     (cmp == SMALLER) ? ARR_LEFT_TO_RIGHT : ARR_RIGHT_TO_LEFT;
02517   he2->set_direction (dir);
02518 
02519   // Notify the observers that we have created a new edge.
02520   _notify_after_create_edge (Halfedge_handle (he2));
02521 
02522   // Return a pointer to the new halfedge whose target is the free vertex v.
02523   return (he2);
02524 }
02525 
02526 //-----------------------------------------------------------------------------
02527 // Insert an x-monotone curve into the arrangement, where the end vertices
02528 // are given by the target points of two given halfedges.
02529 // The two halfedges should be given such that in case a new face is formed,
02530 // it will be the incident face of the halfedge directed from the first
02531 // vertex to the second vertex.
02532 //
02533 template<class GeomTraits, class TopTraits>
02534 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::DHalfedge*
02535 Arrangement_on_surface_2<GeomTraits, TopTraits>::
02536 _insert_at_vertices(const X_monotone_curve_2& cv,
02537                     DHalfedge *prev1, DHalfedge *prev2,
02538                     Comparison_result cmp,
02539                     bool& new_face)
02540 {
02541   CGAL_precondition(prev1 != NULL);
02542   CGAL_precondition(prev2 != NULL);
02543 
02544   // Get the vertices that match cv's endpoints.
02545   DVertex     *v1 = prev1->vertex();
02546   DVertex     *v2 = prev2->vertex();
02547 
02548 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE
02549   typedef CGALi::Sign_of_path< GeomTraits, TopTraits > Sign_of_path;
02550   
02551   std::cout << "Aos_2: _insert_at_vertices (internal)" << std::endl;
02552   
02553   std::cout << "cv   : " << cv << std::endl;
02554   if (!prev1->has_null_curve()) {
02555     std::cout << "prev1: " << prev1->curve() << std::endl;
02556   } else {
02557     std::cout << "prev1: fictitious" << std::endl;
02558   }
02559   std::cout << "dir1 : " << prev1->direction() << std::endl;
02560   std::cout << "pref: " << (prev1->is_on_inner_ccb() ? 
02561                             prev1->inner_ccb()->face() :
02562                             prev1->outer_ccb()->face()) << std::endl;
02563   if (!prev2->has_null_curve()) {
02564       std::cout << "prev2: " << prev2->curve() << std::endl;
02565   } else {
02566       std::cout << "prev2: fictitious" << std::endl;
02567   }
02568   std::cout << "dir 2: " << prev2->direction() << std::endl;
02569   std::cout << "pref2: " << (prev2->is_on_inner_ccb() ? 
02570                              prev2->inner_ccb()->face() :
02571                              prev2->outer_ccb()->face()) << std::endl;
02572   std::cout << "cmp  : " << cmp << std::endl;
02573 #endif
02574 
02575   // Get the components containing the two previous halfedges and the incident
02576   // face (which should be the same for the two components).
02577   DInner_ccb  *ic1 = (prev1->is_on_inner_ccb()) ? prev1->inner_ccb() : NULL;
02578   DOuter_ccb  *oc1 = (ic1 == NULL) ? prev1->outer_ccb() : NULL;
02579   DFace       *f = (ic1 != NULL) ? ic1->face() : oc1->face();
02580   DInner_ccb  *ic2 = (prev2->is_on_inner_ccb()) ? prev2->inner_ccb() : NULL;
02581   DOuter_ccb  *oc2 = (ic2 == NULL) ? prev2->outer_ccb() : NULL;
02582 
02583   CGAL_precondition_code
02584     (DFace       *f2 = (ic2 != NULL) ? ic2->face() : oc2->face(););
02585 
02586 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE
02587   std::cout << "ic1: " << ic1 << std::endl;
02588   std::cout << "ic2: " << ic2 << std::endl;
02589   std::cout << "oc1: " << oc1 << std::endl;
02590   std::cout << "oc2: " << oc2 << std::endl;
02591 
02592   std::cout << "f1: " << &(*f) << std::endl;
02593 
02594 #if 0
02595   DHalfedge *curr = prev1;
02596   if (curr != curr->next()) {
02597     curr = curr->next();
02598     while (curr != prev1) {
02599       if (!curr->has_null_curve()) {
02600         std::cout << "curr: " << curr->curve() << std::endl;
02601       } else {
02602         std::cout << "curr: fictitious" << std::endl;
02603       }
02604       std::cout << "dir: " 
02605                 << (curr->direction() == CGAL::LEFT_TO_RIGHT ? "L2R" : "R2L") 
02606                 << std::endl;
02607       curr = curr->next();
02608     }
02609   } else {
02610     std::cout << "only prev1" << std::endl;
02611   }
02612 #endif
02613 
02614   CGAL_precondition_code(std::cout << "f2: " << &(*f2) << std::endl;);
02615 
02616 #if 0
02617   curr = prev2;
02618   if (curr != curr->next()) {
02619     curr = curr->next();
02620     while (curr != prev2) {
02621       if (!curr->has_null_curve()) {
02622         std::cout << "curr: " << curr->curve() << std::endl;
02623       } else {
02624         std::cout << "curr: fictitious" << std::endl;
02625       }
02626       std::cout << "dir: " 
02627                 << (curr->direction() == CGAL::LEFT_TO_RIGHT ? "L2R" : "R2L") 
02628                 << std::endl;
02629       curr = curr->next();
02630     }
02631   } else {
02632     std::cout << "only prev2" << std::endl;
02633   }
02634 #endif
02635 #endif // CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE
02636 
02637   CGAL_precondition_msg
02638     (f == f2,
02639      "The two halfedges must share the same incident face.");
02640 
02641   // In case the two previous halfedges lie on the same inner component inside
02642   // the face f, we use the topology-traits class to determine whether we have
02643   // to create a new face by splitting f, and if so - whether new face is
02644   // contained in the existing face or just adjacent to it.
02645   bool         split_new_face = true;
02646   bool         is_split_face_contained = false;
02647 
02648   if (ic1 != NULL && ic1 == ic2)
02649   {
02650     std::pair<bool, bool>   res = 
02651         m_topol_traits.face_split_after_edge_insertion (prev1, prev2, cv);
02652 
02653     split_new_face = res.first;
02654     is_split_face_contained = res.second;
02655 
02656     // The result <false, true> is illegal:
02657     CGAL_assertion (split_new_face || ! is_split_face_contained);
02658   }
02659 
02660   // Notify the observers that we are about to create a new edge.
02661   _notify_before_create_edge (cv, Vertex_handle (v1), Vertex_handle (v2));
02662 
02663   // Create a pair of twin halfedges connecting v1 and v2 and associate them
02664   // with the given curve.
02665   DHalfedge           *he1 = _dcel().new_edge();
02666   DHalfedge           *he2 = he1->opposite();
02667   X_monotone_curve_2  *dup_cv = _new_curve (cv);
02668 
02669   he1->set_curve (dup_cv);
02670 
02671   he1->set_vertex (v1);
02672   he2->set_vertex (v2);
02673 
02674   // Connect the new halfedges to the existing halfedges around the two
02675   // incident vertices.
02676   he1->set_next (prev1->next());
02677   he2->set_next (prev2->next());
02678 
02679   prev1->set_next (he2);
02680   prev2->set_next (he1);
02681 
02682   // Set the direction of the halfedges: res indicates the direction of he2,
02683   // as it is the comparison result between its source and target.
02684   const Arr_halfedge_direction   dir =
02685     (cmp == SMALLER) ? ARR_LEFT_TO_RIGHT : ARR_RIGHT_TO_LEFT;
02686   he2->set_direction (dir);
02687 
02688   // Check the various cases of insertion (in the design document: the
02689   // various sub-cases of case 3 in the insertion procedure).
02690   if ((ic1 != NULL || ic2 != NULL) && ic1 != ic2)
02691   {
02692     // In case we have to connect two disconnected components, no new face
02693     // is created. 
02694     new_face = false;
02695 
02696     // Check whether both halfedges are inner components (holes) in the same
02697     // face, or whether one is a hole and the other is on the outer boundary
02698     // of the face. 
02699     Face_handle       fh (f);
02700 
02701     if (ic1 != NULL && ic2 != NULL)
02702     {
02703       // In this case (3.1) we have to connect to inner CCBs (holes) inside f.
02704       // Notify the observers that we are about to merge two holes in the face.
02705       _notify_before_merge_inner_ccb (fh,
02706                                       (Halfedge_handle(prev1))->ccb(),
02707                                       (Halfedge_handle(prev2))->ccb(),
02708                                       Halfedge_handle (he1));
02709 
02710       // Remove the inner component prev2 belongs to, and unite it with the
02711       // inner component that prev1 belongs to.
02712       f->erase_inner_ccb (ic2);
02713 
02714       // Set the merged component for the two new halfedges.
02715       he1->set_inner_ccb (ic1);
02716       he2->set_inner_ccb (ic1);
02717 
02718       // Make all halfedges along ic2 to point to ic1.
02719       DHalfedge       *curr;
02720 
02721       for (curr = he2->next(); curr != he1; curr = curr->next())
02722         curr->set_inner_ccb (ic1);
02723 
02724       // Delete the redundant inner CCB.
02725       _dcel().delete_inner_ccb (ic2);
02726 
02727       // Notify the observers that we have merged the two inner CCBs.
02728       _notify_after_merge_inner_ccb (fh, (Halfedge_handle(he1))->ccb());
02729     }
02730     else
02731     {
02732       // In this case (3.2) we connect a hole (inner CCB) with an outer CCB
02733       // of the face that contains it. We remove the hole and associate the
02734       // pair of new halfedges with the outer boundary of the face f.
02735       DInner_ccb  *del_ic;
02736       DOuter_ccb  *oc;
02737       DHalfedge   *ccb_first;
02738       DHalfedge   *ccb_last;
02739       
02740       if (ic1 != NULL)
02741       {
02742         // We remove the inner CCB ic1 and merge in with the outer CCB oc2.
02743         del_ic = ic1;
02744         oc = oc2;
02745         ccb_first = he1->next();
02746         ccb_last = he2;
02747       }
02748       else
02749       {
02750         // We remove the inner CCB ic2 and merge in with the outer CCB oc1.
02751         del_ic = ic2;
02752         oc = oc1;
02753         ccb_first = he2->next();
02754         ccb_last = he1;
02755       }
02756 
02757       he1->set_outer_ccb (oc);
02758       he2->set_outer_ccb (oc);
02759 
02760       // Notify the observers that we are about to remove an inner CCB from
02761       // the face.
02762       _notify_before_remove_inner_ccb(fh, (Halfedge_handle(ccb_first))->ccb());
02763 
02764       // Remove the inner CCB from the face, as we have just connected it to
02765       // the outer boundary of its incident face.
02766       f->erase_inner_ccb (del_ic);
02767 
02768       // Make all halfedges along the inner CCB to point to the outer CCB of f.
02769       DHalfedge       *curr;
02770 
02771       for (curr = ccb_first; curr != ccb_last; curr = curr->next())
02772         curr->set_outer_ccb (oc);
02773 
02774       // Delete the redundant hole.
02775       _dcel().delete_inner_ccb (del_ic);
02776 
02777       // Notify the observers that we have removed an inner ccb.
02778       _notify_after_remove_inner_ccb (fh);
02779     }
02780   }
02781   else if (! split_new_face)
02782   {
02783     // RWRW: NEW!
02784     CGAL_assertion (ic1 == ic2 && ic1 != NULL);
02785 
02786     // Handle the special case where we close an inner CCB, such that
02787     // we form two outer CCBs of the same face.
02788     Face_handle       fh (f);
02789 
02790     // Notify the obserers we are about to remove an inner CCB from f.
02791     _notify_before_remove_inner_ccb (fh, (Halfedge_handle(he1))->ccb());
02792 
02793     // Erase the inner CCB from the incident face and delete the
02794     // corresponding component.
02795     f->erase_inner_ccb (ic1);
02796 
02797     _dcel().delete_inner_ccb (ic1);
02798 
02799     // Notify the observers that the inner CCB has been removed.
02800     _notify_after_remove_inner_ccb (fh);
02801 
02802     // Handle the first split outer CCB (the one containing he1):
02803     // Notify the obserers we are about to add an outer CCB to f.
02804     _notify_before_add_outer_ccb (fh, Halfedge_handle (he1));
02805 
02806     // Create a new outer CCB that for the face f, and make he1 the
02807     // representative halfedge of this component.
02808     DOuter_ccb  *f_oc1 = _dcel().new_outer_ccb();
02809 
02810     f->add_outer_ccb (f_oc1, he1);
02811     f_oc1->set_face (f);
02812     he1->set_outer_ccb (f_oc1);
02813 
02814     // Set the component of all halfedges that used to belong to he1's CCB.
02815     DHalfedge       *curr;
02816 
02817     for (curr = he1->next(); curr != he1; curr = curr->next())
02818       curr->set_outer_ccb (f_oc1);
02819 
02820     // Notify the observers that we have added an outer CCB to f.
02821     _notify_after_add_outer_ccb ((Halfedge_handle (he1))->ccb());
02822 
02823     // Handle the second split outer CCB (the one containing he2):
02824     // Notify the obserers we are about to add an outer CCB to f.
02825     _notify_before_add_outer_ccb (fh, Halfedge_handle (he2));
02826 
02827     // Create a new outer CCB that for the face f, and make he2 the
02828     // representative halfedge of this component.
02829     DOuter_ccb  *f_oc2 = _dcel().new_outer_ccb();
02830 
02831     f->add_outer_ccb (f_oc2, he2);
02832     f_oc2->set_face (f);
02833     he2->set_outer_ccb (f_oc2);
02834 
02835     // Set the component of all halfedges that used to belong to he2's CCB.
02836     for (curr = he2->next(); curr != he2; curr = curr->next())
02837       curr->set_outer_ccb (f_oc2);
02838 
02839     // Notify the observers that we have added an outer CCB to f.
02840     _notify_after_add_outer_ccb ((Halfedge_handle (he2))->ccb());
02841 
02842     // Mark that in this case no new face is created:
02843     new_face = false;
02844   }
02845   else if (ic1 == ic2 && oc1 == oc2)
02846   {
02847     // In this case we created a pair of halfedge that connect halfedges that
02848     // already belong to the same component. This means we have to cretae a
02849     // new face by splitting the existing face f. 
02850     // Notify the observers that we are about to split a face.
02851     Face_handle       fh (f);
02852 
02853     _notify_before_split_face (fh, Halfedge_handle (he1));
02854 
02855     // Create the new face and create a single outer component which should
02856     // point to he2.
02857     DFace       *new_f = _dcel().new_face();
02858     //std::cout << "New face: " << &(*new_f) << std::endl;
02859 
02860 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE
02861     std::cout << "new face: " << new_f << std::endl;
02862 #endif
02863     
02864     DOuter_ccb  *new_oc = _dcel().new_outer_ccb();
02865 
02866     new_face = true;
02867     new_f->add_outer_ccb (new_oc, he2);
02868     new_oc->set_face (new_f);
02869 
02870     // Set the components of the new halfedge he2, which should be the new
02871     // outer comoponent of the new face.
02872     // Note that there are several cases for setting he1's component, so we
02873     // do not do it yet.
02874     he2->set_outer_ccb (new_oc);
02875 
02876     // Set the component of all halfedges that used to belong to he2's CCB.
02877     DHalfedge       *curr;
02878 
02879     for (curr = he2->next(); curr != he2; curr = curr->next())
02880       curr->set_outer_ccb (new_oc);
02881 
02882 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE
02883     std::cout << "he2 (=> prev1) defines new outer CCB" << std::endl;
02884     std::cout << "prev1->face(): " << (prev1->is_on_inner_ccb() ? 
02885                                        prev1->inner_ccb()->face() :
02886                                        prev1->outer_ccb()->face())
02887               << std::endl;
02888     Sign_of_path sign_of_path(topology_traits());
02889     //std::cout << "prev1sign: " << sign_of_path(prev1, prev1) << std::endl;
02890 #endif
02891 
02892     // Check whether the two previous halfedges lie on the same innder CCB
02893     // or on the same outer CCB (distinguish case 3.3 and case 3.4).
02894     bool   is_hole;
02895 
02896     if (ic1 != NULL)
02897     {
02898       // In this case (3.3) we have two distinguish two sub-cases.
02899       if (is_split_face_contained)
02900       {
02901         // The halfedges prev1 and prev2 belong to the same inner component
02902         // (hole) inside the face f, such that the new edge creates a new
02903         // face that is contained in f (case 3.3.1).
02904         is_hole = true;
02905 
02906         // In this case, he1 lies on an inner CCB of f.
02907         he1->set_inner_ccb (ic1);
02908         
02909         // Note that the current representative of the inner CCB may not
02910         // belong to the hole any more. In this case we replace the hole
02911         // representative by he1.
02912         if (! ic1->halfedge()->is_on_inner_ccb())
02913           ic1->set_halfedge (he1);
02914 
02915 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE
02916         std::cout << "he1 (=> prev2) defines new inner CCB" << std::endl;
02917         std::cout << "prev2->face(): " << (prev2->is_on_inner_ccb() ? 
02918                                            prev2->inner_ccb()->face() :
02919                                            prev2->outer_ccb()->face())
02920                   << std::endl;
02921         Sign_of_path sign_of_path(topology_traits());
02922         //std::cout << "prev2sign: " << sign_of_path(prev2, prev2) << std::endl;
02923 #endif
02924 
02925       }
02926       else
02927       {
02928         // The new face we have created should be adjacent to the existing
02929         // face (case 3.3.2).
02930         is_hole = false;
02931 
02932         // Notify the obserers we are about to add an outer CCB to f.
02933         _notify_before_add_outer_ccb (fh, Halfedge_handle (he1));
02934 
02935         // Create a new outer CCB that for the face f, and make he1 the
02936         // representative halfedge of this component.
02937         DOuter_ccb  *f_oc = _dcel().new_outer_ccb();
02938 
02939         f->add_outer_ccb (f_oc, he1);
02940         f_oc->set_face (f);
02941         he1->set_outer_ccb (f_oc);
02942 
02943         // Set the component of all halfedges that used to belong to he1's
02944         // CCB.
02945         for (curr = he1->next(); curr != he1; curr = curr->next())
02946           curr->set_outer_ccb (f_oc);
02947 
02948 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE
02949         std::cout << "he1 (=> prev2) defines adjacent outer CCB" << std::endl;
02950         std::cout << "prev2->face(): " << (prev2->is_on_inner_ccb() ? 
02951                                            prev2->inner_ccb()->face() :
02952                                            prev2->outer_ccb()->face())
02953                   << std::endl;
02954         Sign_of_path sign_of_path(topology_traits());
02955         //std::cout << "prev2sign: " << sign_of_path(prev2, prev2) << std::endl;
02956 #endif
02957         
02958         // Notify the observers that we have added an outer CCB to f.
02959         _notify_after_add_outer_ccb ((Halfedge_handle (he1))->ccb());
02960 
02961         // Go over all other outer CCBs of f and check whether they should be
02962         // moved to be outer CCBs of the new face.
02963         DOuter_ccb_iter  oc_it = f->outer_ccbs_begin();
02964         DOuter_ccb_iter  oc_to_move;
02965 
02966         while (oc_it != f->outer_ccbs_end())
02967         {
02968           // Use the topology traits to determine whether the representative
02969           // of the current outer CCB should belong to the same face as he2
02970           // (which is on the outer boundary of the new face).
02971           if (*oc_it != he1 &&
02972               m_topol_traits.boundaries_of_same_face (*oc_it, he2))
02973           {
02974             // We increment the itrator before moving the outer CCB, because
02975             // this operation invalidates the iterator.
02976             oc_to_move = oc_it;
02977             ++oc_it;
02978 
02979             _move_outer_ccb (f, new_f, *oc_to_move);
02980           }
02981           else
02982           {
02983             ++oc_it;
02984           }
02985         }
02986       }
02987     }
02988     else
02989     {
02990       // In this case the face f is simply split into two (case 3.4).
02991       is_hole = false;
02992 
02993       // In this case, he1 lies on an outer CCB of f.
02994       he1->set_outer_ccb (oc1);
02995 
02996       // As the outer component of the exisitng face f may associated with
02997       // one of the halfedges along the boundary of the new face, we set it
02998       // to be he1.
02999       oc1->set_halfedge (he1);
03000     }
03001 
03002     // Check whether we should mark the original face and the new face as
03003     // bounded or as unbounded faces.
03004     if (! f->is_unbounded())
03005     {
03006       // The original face is bounded, so the new face split from it is
03007       // obviously bounded.
03008       new_f->set_unbounded (false);
03009     }
03010     else if (is_hole)
03011     {
03012       // The new face is a hole inside the original face, so it must be
03013       // bounded.
03014       new_f->set_unbounded (false);
03015     }
03016     else
03017     {
03018       // Use the topology traits to determine whether each of the split
03019       // faces is unbounded. Note that if the new face is bounded, then f
03020       // obviously reamins unbounded and there is no need for further checks.
03021       new_f->set_unbounded (m_topol_traits.is_unbounded (new_f));
03022       
03023       if (new_f->is_unbounded())
03024         f->set_unbounded (m_topol_traits.is_unbounded (f));
03025     }
03026 
03027     // Notify the observers that we have split the face.
03028     _notify_after_split_face (fh, Face_handle (new_f), is_hole);
03029   }
03030   else
03031   {
03032     CGAL_assertion (oc1 != NULL && oc2 != NULL && oc1 != oc2);
03033 
03034     // In case prev1 and prev2 belong to different outer CCBs of the same
03035     // face f (case 3.5), we have to merge this ccbs into one. Note that we
03036     // do not create a new face.
03037     new_face = false;
03038 
03039     // Notify the observers that we are about to merge two outer CCBs.
03040     Face_handle       fh (f);
03041 
03042     _notify_before_merge_outer_ccb (fh,
03043                                     (Halfedge_handle(prev1))->ccb(),
03044                                     (Halfedge_handle(prev2))->ccb(),
03045                                     Halfedge_handle (he1));
03046 
03047     // Remove the outer component prev2 belongs to, and unite it with the
03048     // outer component that prev1 belongs to.
03049     f->erase_outer_ccb (oc2);
03050 
03051     // Set the merged component for the two new halfedges.
03052     he1->set_outer_ccb (oc1);
03053     he2->set_outer_ccb (oc1);
03054 
03055     // Make all halfedges along oc2 to point to oc1.
03056     DHalfedge       *curr;
03057 
03058     for (curr = he2->next(); curr != he1; curr = curr->next())
03059       curr->set_outer_ccb (oc1);
03060 
03061     // Delete the redundant outer CCB.
03062     _dcel().delete_outer_ccb (oc2);
03063 
03064     // Notify the observers that we have merged the two CCBs.
03065     _notify_after_merge_outer_ccb (fh,
03066                                    (Halfedge_handle(he1))->ccb());
03067   }
03068 
03069   // Notify the observers that we have created a new edge.
03070   _notify_after_create_edge (Halfedge_handle (he2));
03071 
03072   // Return the halfedge directed from v1 to v2.
03073   return (he2);
03074 }
03075 
03076 //-----------------------------------------------------------------------------
03077 // Relocate all inner CCBs (holes) to their proper position,
03078 // immediately after a face has split due to the insertion of a new halfedge.
03079 //
03080 template<class GeomTraits, class TopTraits>
03081 void  Arrangement_on_surface_2<GeomTraits, TopTraits>::
03082 _relocate_inner_ccbs_in_new_face (DHalfedge *new_he)
03083 {
03084   // The given halfedge points to the new face, while its twin points to the
03085   // old face (the one that has just been split).
03086   DFace        *new_face = (new_he->is_on_inner_ccb()) ?
03087     new_he->inner_ccb()->face() :
03088     new_he->outer_ccb()->face();
03089   DHalfedge    *opp_he = new_he->opposite();
03090   const bool    opp_on_inner_ccb = opp_he->is_on_inner_ccb();
03091   DFace        *old_face = opp_on_inner_ccb ? opp_he->inner_ccb()->face() :
03092     opp_he->outer_ccb()->face();
03093   
03094   CGAL_assertion (new_face != old_face);
03095   
03096   // Examine the inner CCBs inside the existing old face and move the relevant
03097   // ones into the new face.
03098   DInner_ccb_iter    ic_it = old_face->inner_ccbs_begin();
03099   DInner_ccb_iter    ic_to_move;
03100 
03101   while (ic_it != old_face->inner_ccbs_end())
03102   {
03103     // In case the new edge represents the current component in the old face
03104     // (note we take the opposite halfedge, as it is incident to the old face),
03105     // then the new face already forms a hole in the old face, and we do not
03106     // need to move it.
03107     CGAL_assertion ((*ic_it)->is_on_inner_ccb());
03108     
03109     if (opp_on_inner_ccb && (*ic_it)->inner_ccb() == opp_he->inner_ccb())
03110     {
03111       ++ic_it;
03112       continue;
03113     }
03114     
03115     // Check whether the current inner CCB is inside new face (we actually
03116     // check if a representative vertex is located in the new face).
03117     if (m_topol_traits.is_in_face (new_face,
03118                                (*ic_it)->vertex()->point(),
03119                                (*ic_it)->vertex()))
03120     {
03121       // We increment the itrator before moving the inner CCB, because this
03122       // operation invalidates the iterator.
03123       ic_to_move = ic_it;
03124       ++ic_it;
03125       
03126       // Move the hole.
03127       _move_inner_ccb (old_face, new_face, *ic_to_move);
03128     }
03129     else
03130     {
03131       ++ic_it;
03132     }
03133   }
03134   
03135   return;
03136 }
03137 
03138 //-----------------------------------------------------------------------------
03139 // Relocate all isolated vertices to their proper position,
03140 // immediately after a face has split due to the insertion of a new halfedge.
03141 //
03142 template<class GeomTraits, class TopTraits>
03143 void Arrangement_on_surface_2<GeomTraits, TopTraits>::
03144 _relocate_isolated_vertices_in_new_face (DHalfedge *new_he)
03145 {
03146   // The given halfedge points to the new face, while its twin points to the
03147   // old face (the one that has just been split).
03148   DFace        *new_face = (new_he->is_on_inner_ccb()) ?
03149     new_he->inner_ccb()->face() :
03150     new_he->outer_ccb()->face();
03151   DHalfedge    *opp_he = new_he->opposite();
03152   DFace        *old_face = (opp_he->is_on_inner_ccb()) ?
03153     opp_he->inner_ccb()->face() :
03154     opp_he->outer_ccb()->face();
03155 
03156   CGAL_assertion (new_face != old_face);
03157 
03158   // Examine the isolated vertices inside the existing old face and move the
03159   // relevant ones into the new face.
03160   DIso_vertex_iter    iv_it;
03161   DIso_vertex_iter    iv_to_move;
03162 
03163   iv_it = old_face->isolated_vertices_begin();
03164   while (iv_it != old_face->isolated_vertices_end())
03165   {
03166     // Check whether the isolated vertex lies inside the new face.
03167     if (m_topol_traits.is_in_face (new_face, iv_it->point(), &(*iv_it)))
03168     {
03169       // We increment the isolated vertices itrator before moving the vertex,
03170       // because this operation invalidates the iterator.
03171       iv_to_move  = iv_it;
03172       ++iv_it;
03173 
03174       // Move the isolated vertex.
03175       _move_isolated_vertex (old_face, new_face, &(*iv_to_move));
03176     }
03177     else
03178     {
03179       ++iv_it;
03180     }
03181   }
03182 
03183   return;
03184 }
03185 
03186 //-----------------------------------------------------------------------------
03187 // Relocate all holes (inner CCBs) and isolated vertices to their proper
03188 // position, immediately after a face has split due to the insertion of a new
03189 // halfedge.
03190 //
03191 template<class GeomTraits, class TopTraits>
03192 void Arrangement_on_surface_2<GeomTraits, TopTraits>::
03193 _relocate_in_new_face(DHalfedge *new_he)
03194 {
03195   _relocate_inner_ccbs_in_new_face(new_he);
03196   _relocate_isolated_vertices_in_new_face(new_he);
03197   return;
03198 }
03199 
03200 //-----------------------------------------------------------------------------
03201 // Replace the point associated with the given vertex.
03202 //
03203 template<class GeomTraits, class TopTraits>
03204 void Arrangement_on_surface_2<GeomTraits, TopTraits>::
03205 _modify_vertex (DVertex *v, const Point_2& p)
03206 {
03207   // Notify the observers that we are about to modify a vertex.
03208   Vertex_handle  vh (v);
03209   _notify_before_modify_vertex (vh, p);
03210 
03211   // Modify the point associated with the vertex.
03212   v->point() = p;
03213 
03214   // Notify the observers that we have modified the vertex.
03215   _notify_after_modify_vertex (vh);
03216 
03217   return;
03218 }
03219 
03220 //-----------------------------------------------------------------------------
03221 // Replace the x-monotone curve associated with the given edge.
03222 //
03223 template<class GeomTraits, class TopTraits>
03224 void Arrangement_on_surface_2<GeomTraits, TopTraits>::
03225 _modify_edge (DHalfedge *he, const X_monotone_curve_2& cv)
03226 {
03227   // Notify the observers that we are about to modify an edge.
03228   Halfedge_handle  e (he);
03229   _notify_before_modify_edge (e, cv);
03230 
03231   // Modify the curve associated with the halfedge.
03232   he->curve() = cv;
03233 
03234   // Notify the observers that we have modified the edge.
03235   _notify_after_modify_edge (e);
03236 
03237   return;
03238 }
03239 
03240 //-----------------------------------------------------------------------------
03241 // Check if the given vertex represents one of the ends of a given curve.
03242 //
03243 template<class GeomTraits, class TopTraits>
03244 bool Arrangement_on_surface_2<GeomTraits, TopTraits>::
03245 _are_equal (const DVertex *v,
03246             const X_monotone_curve_2& cv, Arr_curve_end ind) const
03247 {
03248   // In case the given curve end has boundary conditions, use the topology
03249   // traits to determine whether it is equivalent to v.
03250   const Arr_parameter_space    ps_x =
03251     m_geom_traits->parameter_space_in_x_2_object() (cv, ind);
03252   const Arr_parameter_space    ps_y =
03253     m_geom_traits->parameter_space_in_y_2_object() (cv, ind);
03254 
03255   if (ps_x != ARR_INTERIOR || ps_y != ARR_INTERIOR)
03256   {
03257     return (m_topol_traits.are_equal (v, cv, ind, ps_x, ps_y));
03258   }
03259 
03260   // Otherwise, the curve end is a valid endpoint. Check that v is also
03261   // associated with a valid point that equals this endpoint.
03262   if (v->has_null_point())
03263     return (false);
03264 
03265   return (ind == ARR_MIN_END) ?
03266     (m_geom_traits->equal_2_object() 
03267      (m_geom_traits->construct_min_vertex_2_object() (cv), v->point())) :
03268     (m_geom_traits->equal_2_object() 
03269      (m_geom_traits->construct_max_vertex_2_object() (cv), v->point()));
03270 }
03271 
03272 //-----------------------------------------------------------------------------
03273 // Split a given edge into two at a given point, and associate the given
03274 // x-monotone curves with the split edges.
03275 //
03276 template<class GeomTraits, class TopTraits>
03277 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::DHalfedge*
03278 Arrangement_on_surface_2<GeomTraits, TopTraits>::
03279 _split_edge(DHalfedge *e, const Point_2& p,
03280             const X_monotone_curve_2& cv1, const X_monotone_curve_2& cv2)
03281 {
03282   // Allocate a new vertex and associate it with the split point.
03283   // Note that this point must not have any boundary conditions.
03284   DVertex         *v = _create_vertex (p);
03285 
03286   // Split the edge from the given vertex.
03287   return (_split_edge (e, v, cv1, cv2));
03288 }
03289 
03290 //-----------------------------------------------------------------------------
03291 // Split a given edge into two at a given vertex, and associate the given
03292 // x-monotone curves with the split edges.
03293 //
03294 template<class GeomTraits, class TopTraits>
03295 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::DHalfedge*
03296 Arrangement_on_surface_2<GeomTraits, TopTraits>::
03297 _split_edge(DHalfedge *e, DVertex *v,
03298             const X_monotone_curve_2& cv1, const X_monotone_curve_2& cv2)
03299 {
03300   // Get the split halfedge and its twin, its source and target.
03301   DHalfedge       *he1 = e;
03302   DHalfedge       *he2 = he1->opposite();
03303   DInner_ccb      *ic1 = (he1->is_on_inner_ccb()) ? he1->inner_ccb() : NULL;
03304   DOuter_ccb      *oc1 = (ic1 == NULL) ? he1->outer_ccb() : NULL;
03305   DInner_ccb      *ic2 = (he2->is_on_inner_ccb()) ? he2->inner_ccb() : NULL;
03306   DOuter_ccb      *oc2 = (ic2 == NULL) ? he2->outer_ccb() : NULL;
03307 
03308   // Notify the observers that we are about to split an edge.
03309   _notify_before_split_edge (Halfedge_handle (e), Vertex_handle (v), cv1, cv2);
03310 
03311   // Allocate a pair of new halfedges.
03312   DHalfedge   *he3 = _dcel().new_edge();
03313   DHalfedge   *he4 = he3->opposite();
03314 
03315   // Connect the new halfedges:
03316   //
03317   //            he1      he3
03318   //         -------> ------->
03319   //       (.)      (.)v     (.)
03320   //         <------- <-------
03321   //            he2      he4
03322   //
03323   v->set_halfedge (he4);
03324 
03325   if (he1->next() != he2)
03326   {
03327     // Connect e3 between e1 and its successor.
03328     he3->set_next (he1->next());
03329 
03330     // Insert he4 between he2 and its predecessor.
03331     he2->prev()->set_next (he4);
03332   }
03333   else
03334   {
03335     // he1 and he2 form an "antenna", so he4 becomes he3's successor.
03336     he3->set_next (he4);
03337   }
03338 
03339   if (oc1 != NULL)
03340     he3->set_outer_ccb (oc1);
03341   else
03342     he3->set_inner_ccb (ic1);
03343 
03344   he3->set_vertex (he1->vertex());
03345   he4->set_vertex (v);
03346   he4->set_next (he2);
03347 
03348   if (oc2 != NULL)
03349     he4->set_outer_ccb (oc2);
03350   else
03351     he4->set_inner_ccb (ic2);
03352 
03353   if (he1->vertex()->halfedge() == he1)
03354     // If he1 is the incident halfedge to its target, he3 replaces it.
03355     he1->vertex()->set_halfedge (he3);
03356 
03357   // Update the properties of the twin halfedges we have just split.
03358   he1->set_next(he3);
03359   he1->set_vertex(v);
03360 
03361   // The direction of he3 is the same as he1's (and the direction of he4 is
03362   // the same as he2).
03363   he3->set_direction (he1->direction());
03364 
03365   // Associate cv1 with he1 (and its twin). We allocate a new curve for cv2
03366   // and associate it with he3 (and its twin).
03367   X_monotone_curve_2  *dup_cv2 = _new_curve (cv2);
03368 
03369   he1->curve() = cv1;
03370   he3->set_curve (dup_cv2);
03371 
03372   // Notify the observers that we have split an edge into two.
03373   _notify_after_split_edge (Halfedge_handle (he1), Halfedge_handle (he3));
03374 
03375   // Return a handle for one of the existing halfedge that is incident to the
03376   // split point.
03377   return (he1);
03378 }
03379 
03380 //-----------------------------------------------------------------------------
03381 // Compare two vertices lexicographically, while taking care of boundary
03382 // conditions (for the special usage of _find_leftmost_vertex() alone!).
03383 //
03384 template<class GeomTraits, class TopTraits>
03385 Comparison_result
03386 Arrangement_on_surface_2<GeomTraits, TopTraits>::
03387 _compare_vertices_xy_impl (const DVertex * v1, const DVertex * v2,
03388                            Arr_not_all_sides_oblivious_tag) const
03389 {
03390   if (v1 == v2)
03391     return (EQUAL);
03392 
03393   // Check the boundary conditions in y:
03394   const Arr_parameter_space     ps_y1 = v1->parameter_space_in_y();
03395   const Arr_parameter_space     ps_y2 = v2->parameter_space_in_y();
03396 
03397   // In case one of the vertices is a singularity point in y, then the
03398   // "negative" singularity is the smallest vertex, and the "positive"
03399   // singularity is considered to be the largest vertex.
03400   if ((m_boundary_types[ps_y1] == ARR_CONTRACTION) &&
03401       (m_boundary_types[ps_y2] == ARR_CONTRACTION)) {
03402     if ((ps_y1 == ARR_BOTTOM_BOUNDARY) || (ps_y2 == ARR_TOP_BOUNDARY))
03403       return SMALLER;
03404     if ((ps_y2 == ARR_BOTTOM_BOUNDARY) || (ps_y1 == ARR_TOP_BOUNDARY))
03405       return LARGER;
03406   }
03407  
03408   // Check the boundary conditions in x:
03409   const Arr_parameter_space     ps_x1 = v1->parameter_space_in_x();
03410   const Arr_parameter_space     ps_x2 = v2->parameter_space_in_x();
03411   
03412   if (ps_x1 == ARR_LEFT_BOUNDARY) {
03413     return (ps_x1 == ps_x2) ?
03414       m_geom_traits->compare_xy_2_object() (v1->point(), v2->point()) : SMALLER;
03415   }
03416   else if (ps_x1 == ARR_RIGHT_BOUNDARY) {
03417     return (ps_x1 == ps_x2) ?
03418       m_geom_traits->compare_xy_2_object() (v1->point(), v2->point()) : LARGER;
03419   }
03420 
03421   if (ps_x2 == ARR_LEFT_BOUNDARY)
03422     return (LARGER);
03423   else if (ps_x2 == ARR_RIGHT_BOUNDARY)
03424     return (SMALLER);
03425 
03426   // Check the boundary conditions in y again:
03427   if (ps_y1 == ARR_BOTTOM_BOUNDARY) {
03428     return (ps_y1 == ps_y2) ?
03429       m_geom_traits->compare_xy_2_object() (v1->point(), v2->point()) : SMALLER;
03430   }
03431   else if (ps_y1 == ARR_TOP_BOUNDARY) {
03432     return (ps_y1 == ps_y2) ?
03433       m_geom_traits->compare_xy_2_object() (v1->point(), v2->point()) : LARGER;
03434   }
03435 
03436   if (ps_y2 == ARR_BOTTOM_BOUNDARY)
03437     return (LARGER);
03438   else if (ps_y2 == ARR_TOP_BOUNDARY)
03439     return (SMALLER);
03440   
03441   // If we reached here, both vertices do not have boundary conditions, and
03442   // we can just compare their associated points lexicographically.
03443   return (m_geom_traits->compare_xy_2_object() (v1->point(), v2->point()));
03444 }
03445 
03446 //-----------------------------------------------------------------------------
03447 // Locate the leftmost vertex on the a given sequence defined by two
03448 // halfedges. This sequence is still an open loop, but it will soon be closed
03449 // by the insertion of the given curve: The first vertex we consider is the
03450 // target vertex of the first halfedge, and the last vertex we consider is
03451 // the source vertex of the second halfedge, such that the new curve will
03452 // connect these two vertices.
03453 //
03454 template<class GeomTraits, class TopTraits>
03455 std::pair<const typename Arrangement_on_surface_2<GeomTraits,
03456                                                   TopTraits>::DVertex*,
03457           const typename Arrangement_on_surface_2<GeomTraits,
03458                                                   TopTraits>::DHalfedge*>
03459 Arrangement_on_surface_2<GeomTraits, TopTraits>::
03460 _find_leftmost_vertex_on_open_loop (const DHalfedge *he_before,
03461                                     const DHalfedge *he_after,
03462                                     const X_monotone_curve_2& cv,
03463                                     bool& is_perimetric) const
03464 {
03465   // We go over the sequence of vertices, starting from he_before's target
03466   // vertex, until reaching he_after's source vertex, and find the leftmost
03467   // one. Note that we do this carefully, keeping track of the number of
03468   // times we crossed the line of discontinuity in x or in y (if they exist).
03469   // Note that the path must not be incident to any vertex on open boundary.
03470   typename Traits_adaptor_2::Parameter_space_in_x_2    parameter_space_in_x =
03471     m_geom_traits->parameter_space_in_x_2_object(); 
03472   typename Traits_adaptor_2::Parameter_space_in_y_2    parameter_space_in_y =
03473     m_geom_traits->parameter_space_in_y_2_object(); 
03474   unsigned int      x_cross_count = 0;
03475   unsigned int      y_cross_count = 0;
03476   int               index = 0;
03477   const DHalfedge  *he = he_before;
03478   const DHalfedge  *he_left_low = NULL;
03479   int               ind_min = 0;
03480   const DVertex    *v_min = he_before->vertex();
03481   Arr_parameter_space     ps_x, ps_y;
03482 
03483   is_perimetric = false;
03484   do
03485   {
03486     // Get the boundary conditions of the current vertex.
03487     ps_x = he->vertex()->parameter_space_in_x();
03488     ps_y = he->vertex()->parameter_space_in_y();
03489 
03490     CGAL_assertion(!is_open(ps_x, ps_y));
03491 
03492     // Get the boundary conditions of the curve ends associated with the
03493     // current halfedge and its next halfedge.
03494     if (ps_x != ARR_INTERIOR || ps_y != ARR_INTERIOR)
03495     {
03496       // In case this he is the "before" halfegde, use the boundary conditions
03497       // of the proper curve-end of cv. Otherwise, use the boundary conditions
03498       // of the curve associated with he.
03499       if (he == he_before)
03500       {
03501         ps_x = parameter_space_in_x (cv, ARR_MIN_END);
03502         ps_y = parameter_space_in_y (cv, ARR_MIN_END);
03503         
03504         if ((ps_x == ARR_INTERIOR && ps_y == ARR_INTERIOR) ||
03505             ! m_topol_traits.are_equal (he->vertex(), cv, ARR_MIN_END, ps_x, ps_y))
03506         {
03507           ps_x = parameter_space_in_x (cv, ARR_MAX_END);
03508           ps_y = parameter_space_in_y (cv, ARR_MAX_END);
03509           
03510           CGAL_assertion (m_topol_traits.are_equal (he->vertex(),
03511                                                 cv, ARR_MAX_END, ps_x, ps_y));
03512         }
03513       }
03514       else
03515       {
03516         if (he->direction() == ARR_RIGHT_TO_LEFT)
03517         {
03518           ps_x = parameter_space_in_x (he->curve(), ARR_MIN_END);
03519           ps_y = parameter_space_in_y (he->curve(), ARR_MIN_END);
03520         }
03521         else
03522         {
03523           ps_x = parameter_space_in_x (he->curve(), ARR_MAX_END);
03524           ps_y = parameter_space_in_y (he->curve(), ARR_MAX_END);
03525         }
03526       }
03527 
03528       // In case this he->next() is the "after" halfegde, use the boundary
03529       // conditions of the proper curve-end of cv. Otherwise, use the boundary
03530       // conditions of the curve associated with he->next().
03531       Arr_parameter_space     ps_x_next, ps_y_next;
03532 
03533       if (he->next() == he_after)
03534       {
03535         ps_x_next = parameter_space_in_x (cv, ARR_MIN_END);
03536         ps_y_next = parameter_space_in_y (cv, ARR_MIN_END);
03537         
03538         if ((ps_x_next == ARR_INTERIOR && ps_y_next == ARR_INTERIOR) ||
03539             ! m_topol_traits.are_equal (he->next()->opposite()->vertex(),
03540                                     cv, ARR_MIN_END, ps_x_next, ps_y_next))
03541         {
03542           ps_x_next = parameter_space_in_x (cv, ARR_MAX_END);
03543           ps_y_next = parameter_space_in_y (cv, ARR_MAX_END);
03544           
03545           CGAL_assertion (m_topol_traits.are_equal
03546                           (he->next()->opposite()->vertex(),
03547                            cv, ARR_MAX_END, ps_x_next, ps_y_next));
03548         }
03549       }
03550       else
03551       {
03552         if (he->next()->direction() == ARR_LEFT_TO_RIGHT)
03553         {
03554           ps_x_next = parameter_space_in_x (he->next()->curve(), ARR_MIN_END);
03555           ps_y_next = parameter_space_in_y (he->next()->curve(), ARR_MIN_END);
03556         }
03557         else
03558         {
03559           ps_x_next = parameter_space_in_x (he->next()->curve(), ARR_MAX_END);
03560           ps_y_next = parameter_space_in_y (he->next()->curve(), ARR_MAX_END);
03561         }
03562       }
03563 
03564       // If we cross the line of discontinuity in x, then we must update the
03565       // index. Note that a crossing takes place in the following cases:
03566       //                .                                  .
03567       //                .                                  .
03568       //                .                                  .
03569       //                . v    he                   he     . v
03570       //       <-------(.)<---------             -------->(.)------->
03571       //                .                                  .
03572       //       (BEFORE) .    (AFTER)              (BEFORE) .  (AFTER)
03573       //       index-1  .      index              index    .  index+1
03574       //
03575       if ((ps_x == ARR_LEFT_BOUNDARY) && (ps_x_next == ARR_RIGHT_BOUNDARY))
03576       {
03577         CGAL_assertion((m_boundary_types[ps_x] == ARR_IDENTIFICATION) &&
03578                        (m_boundary_types[ps_x_next] == ARR_IDENTIFICATION));
03579         x_cross_count++;
03580         index--;
03581       }
03582       else if ((ps_x == ARR_RIGHT_BOUNDARY) && (ps_x_next == ARR_LEFT_BOUNDARY))
03583       {
03584         CGAL_assertion((m_boundary_types[ps_x] == ARR_IDENTIFICATION) &&
03585                        (m_boundary_types[ps_x_next] == ARR_IDENTIFICATION));
03586         x_cross_count++;
03587         index++;
03588       }
03589 
03590       // Check if we cross the line of discontinuity in y.
03591       if (((ps_y == ARR_BOTTOM_BOUNDARY) && (ps_y_next == ARR_TOP_BOUNDARY)) ||
03592           ((ps_y == ARR_TOP_BOUNDARY) && (ps_y_next == ARR_BOTTOM_BOUNDARY)))
03593       {
03594         CGAL_assertion((m_boundary_types[ps_y] == ARR_IDENTIFICATION) &&
03595                        (m_boundary_types[ps_y_next] == ARR_IDENTIFICATION));
03596         y_cross_count++;
03597       }
03598     }
03599 
03600     // If the halfedge is directed from right to left, its target vertex is
03601     // smaller than its source, so we should check whether it is also smaller
03602     // than the leftmost vertex so far. Note that we compare the vertices
03603     // lexicographically: first by the indices, then by x and y.
03604     if (he->direction() == ARR_RIGHT_TO_LEFT &&
03605         (he->next() == he_after ||
03606          he->next()->direction() == ARR_LEFT_TO_RIGHT))
03607     {
03608       if (v_min == he->opposite()->vertex() || v_min == he->vertex() ||
03609           index < ind_min ||
03610           (index == ind_min &&
03611            _compare_vertices_xy (he->vertex(), v_min) == SMALLER))
03612       {
03613         ind_min = index;
03614         v_min = he->vertex();
03615 
03616         if (he != he_before)
03617         {
03618           // If we need to compute the lowest halfedge incident to the leftmost
03619           // vertex, update it now. Note that we may visit the smallest vertex
03620           // several times, for example when we have (h2 and its twin form
03621           // an antenna):
03622           //
03623           //                         h1 /                       .
03624           //                           /   h2                   .
03625           //                       v (.)-------                 .
03626           //                           \                        .
03627           //                         h3 \                       .
03628           //
03629           // If we first reach the vertex v from h1's source, then we will
03630           // reach it again via h2. Since we take the last halfedge, we will
03631           // locate h2. On the other hand, if we reach the vertex v from h3's
03632           // source, we will leave it via h1's twin and will not return to it,
03633           // so h3 is the left-low halfedge in this case
03634           he_left_low = he;
03635         }
03636       }
03637     }
03638           
03639     // Move to the halfedge.
03640     he = he->next();
03641 
03642   } while (he != he_after);
03643 
03644   // Determine if the path is perimetric, namely if there exists a line of
03645   // discontinuity in x (or in y), and we have crossed it an odd number of
03646   // times.
03647   is_perimetric = (x_cross_count % 2 == 1) || (y_cross_count % 2 == 1);
03648   
03649   // Return the leftmost vertex and its index (with respect to he_before).
03650   return (std::make_pair (v_min, he_left_low));
03651 }
03652 
03653 //-----------------------------------------------------------------------------
03654 // Locate the leftmost vertex on the a given sequence, defined by an anchor
03655 // halfedge and its twin, which forms a closed loop (i.e., the anchor's twin
03656 // is reachable from the anchor halfedge).
03657 //
03658 template<class GeomTraits, class TopTraits>
03659 std::pair<int,
03660           const typename Arrangement_on_surface_2<GeomTraits,
03661                                                   TopTraits>::DVertex*>
03662 Arrangement_on_surface_2<GeomTraits, TopTraits>::
03663 _find_leftmost_vertex_on_closed_loop (const DHalfedge *he_anchor,
03664                                       bool& is_perimetric,
03665                                       bool& at_open_bnd) const
03666 {
03667   // We go over the sequence of vertices, starting from he_anchor's target
03668   // vertex and stopping at the source vertex of its twin. As this path is a
03669   // closed loop, he_anchor's twin is reachable from he_anchor.
03670   // Note that we do this carefully, keeping track of the number of times we
03671   // crossed the line of discontinuity in x or in y (if they exist). We return
03672   // the leftmost vertex we find, along with its index with respect of the
03673   // he_anchor halfedge; this index is decremented each time we cross the line
03674   // of discontinuity from right to left, and
03675   // incremented each time we cross it from left to right.
03676   typename Traits_adaptor_2::Parameter_space_in_x_2    parameter_space_in_x =
03677     m_geom_traits->parameter_space_in_x_2_object(); 
03678   typename Traits_adaptor_2::Parameter_space_in_y_2    parameter_space_in_y =
03679     m_geom_traits->parameter_space_in_y_2_object(); 
03680   unsigned int      x_cross_count = 0;
03681   unsigned int      y_cross_count = 0;
03682   int               index = 0;
03683   const DHalfedge  *he = he_anchor;
03684   int               ind_min = 0;
03685   const DVertex    *v_min = he->vertex();
03686   Arr_parameter_space     ps_x, ps_y;
03687 
03688   is_perimetric = false;
03689   at_open_bnd = false;
03690   do
03691   {
03692     // Get the boundary conditions of the current vertex.
03693     ps_x = he->vertex()->parameter_space_in_x();
03694     ps_y = he->vertex()->parameter_space_in_y();
03695 
03696     // Get the boundary conditions of the curve ends associated with the
03697     // current halfedge and its next halfedge.
03698     if (ps_x != ARR_INTERIOR || ps_y != ARR_INTERIOR) {
03699       // Stop here if the current vertex lies on open boundary
03700       if (is_open (ps_x, ps_y)) {
03701         at_open_bnd = true;
03702         index = 0;
03703         v_min = NULL;
03704         return (std::make_pair (index, v_min));
03705       }
03706 
03707       // If we are on the anchor halfedge, use the boundary conditions of
03708       // the curve associated with the predecessor of the anchor's twin.
03709       const DHalfedge  *he_curr = he;
03710 
03711       if (he == he_anchor)
03712         he = he_anchor->opposite()->prev();
03713 
03714       CGAL_assertion (! he_curr->has_null_curve());
03715       if (he_curr->direction() == ARR_RIGHT_TO_LEFT)
03716       {
03717         ps_x = parameter_space_in_x (he_curr->curve(), ARR_MIN_END);
03718         ps_y = parameter_space_in_y (he_curr->curve(), ARR_MIN_END);
03719       }
03720       else
03721       {
03722         ps_x = parameter_space_in_x (he_curr->curve(), ARR_MAX_END);
03723         ps_y = parameter_space_in_y (he_curr->curve(), ARR_MAX_END);
03724       }
03725 
03726       // Get the boundary conditions of the curve-end of the next halfedge.
03727       Arr_parameter_space     ps_x_next, ps_y_next;
03728 
03729       CGAL_assertion (! he->next()->has_null_curve());
03730       if (he->next()->direction() == ARR_LEFT_TO_RIGHT)
03731       {
03732         ps_x_next = parameter_space_in_x (he->next()->curve(), ARR_MIN_END);
03733         ps_y_next = parameter_space_in_y (he->next()->curve(), ARR_MIN_END);
03734       }
03735       else
03736       {
03737         ps_x_next = parameter_space_in_x (he->next()->curve(), ARR_MAX_END);
03738         ps_y_next = parameter_space_in_y (he->next()->curve(), ARR_MAX_END);
03739       }
03740 
03741       // If we cross the line of discontinuity in x, then we must update the
03742       // index. Note that a crossing takes place in the following cases:
03743       //                .                                  .
03744       //                .                                  .
03745       //                .                                  .
03746       //                . v    he                   he     . v
03747       //       <-------(.)<---------             -------->(.)------->
03748       //                .                                  .
03749       //       (BEFORE) .    (AFTER)              (BEFORE) .  (AFTER)
03750       //       index-1  .      index              index    .  index+1
03751       //
03752       if ((ps_x == ARR_LEFT_BOUNDARY) && (ps_x_next == ARR_RIGHT_BOUNDARY))
03753       {
03754         CGAL_assertion((m_boundary_types[ps_x] == ARR_IDENTIFICATION) &&
03755                        (m_boundary_types[ps_x_next] == ARR_IDENTIFICATION));
03756         x_cross_count++;
03757         index--;
03758       }
03759       else if ((ps_x == ARR_RIGHT_BOUNDARY) && (ps_x_next == ARR_LEFT_BOUNDARY))
03760       {
03761         CGAL_assertion((m_boundary_types[ps_x] == ARR_IDENTIFICATION) &&
03762                        (m_boundary_types[ps_x_next] == ARR_IDENTIFICATION));
03763         x_cross_count++;
03764         index++;
03765       }
03766 
03767       // Check if we cross the line of discontinuity in y.
03768       if (((ps_y == ARR_BOTTOM_BOUNDARY) && (ps_y_next == ARR_TOP_BOUNDARY)) ||
03769           ((ps_y == ARR_TOP_BOUNDARY) && (ps_y_next == ARR_BOTTOM_BOUNDARY)))
03770       {
03771         CGAL_assertion((m_boundary_types[ps_y] == ARR_IDENTIFICATION) &&
03772                        (m_boundary_types[ps_y_next] == ARR_IDENTIFICATION));
03773         y_cross_count++;
03774       }
03775     }
03776 
03777     // If the halfedge is directed from right to left, its target vertex is
03778     // smaller than its source, so we should check whether it is also smaller
03779     // than the leftmost vertex so far. Note that we compare the vertices
03780     // lexicographically: first by the indices, then by x and y.
03781     if (he != he_anchor && he->direction() == ARR_RIGHT_TO_LEFT &&
03782         he->next()->direction() == ARR_LEFT_TO_RIGHT)
03783     {
03784       if (v_min == he->opposite()->vertex() ||
03785           v_min == he->vertex() ||
03786           index < ind_min ||
03787           (index == ind_min &&
03788            _compare_vertices_xy (he->vertex(), v_min) == SMALLER))
03789       {
03790         ind_min = index;
03791         v_min = he->vertex();
03792       }
03793     }
03794           
03795     // Move to the next halfedge.
03796     he = he->next();
03797     CGAL_assertion (he != he_anchor);      // Guard for infinite loops.
03798 
03799   } while (he->next() != he_anchor->opposite());
03800 
03801   // Determine if the path is perimetric, namely if there exists a line of
03802   // discontinuity in x (or in y), and we have crossed it an odd number of
03803   // times.
03804   is_perimetric = (x_cross_count % 2 == 1) || (y_cross_count % 2 == 1);
03805     
03806   // Return the leftmost vertex and its index (with respect to he_anchor).
03807   return (std::make_pair (ind_min, v_min));
03808 }
03809 
03810 //-----------------------------------------------------------------------------
03811 // Determine whether a given query halfedge lies in the interior of a new
03812 // face we are about to create, by connecting it with another halfedge
03813 // using a given x-monotone curve.
03814 //
03815 template <class GeomTraits, class TopTraits>
03816 bool Arrangement_on_surface_2<GeomTraits, TopTraits>::
03817 _is_inside_new_face (const DHalfedge *prev1,
03818                      const DHalfedge *prev2,
03819                      const X_monotone_curve_2& cv) const
03820 {
03821   // Go over all halfedges of along boundary of the face which will eventually
03822   // contain prev1: As the new face is not constructed yet, this traversal
03823   // is simulated by going from prev2's target vertex to prev1's target vertex
03824   // (the source of prev1's successor) and then returning over the new curve.
03825   // During the traversal we locate the leftmost halfedge along the boundary
03826   // (i.e, the one with the lexicographically smallest target vertex, which is
03827   // also the lowest halfedge incident to this vertex we encountered during
03828   // our traversal).
03829   const DHalfedge              *he_last = prev1->next();
03830   bool                          is_perimetric;
03831   std::pair<const DVertex*, const DHalfedge*>   find_res =
03832     _find_leftmost_vertex_on_open_loop (prev2, he_last, cv, is_perimetric);
03833 
03834   if (is_perimetric)
03835   {
03836     // std::cout << "perimetric" << std::endl;
03837     // In this case the route from prev1's target to prev2's target is
03838     // perimetric. We use the topology traits to determine which halfedge
03839     // lies inside the hole (in case a hole is indeed created).
03840     return (m_topol_traits.is_on_new_perimetric_face_boundary (prev1, prev2, cv));
03841   }
03842 
03843   const DVertex                *v_min = find_res.first;
03844   const DHalfedge              *he_left_low = find_res.second;
03845 
03846   CGAL_assertion (! v_min->has_null_point());
03847 
03848   // Now note that the curves of leftmost edge and its successor are defined
03849   // to the right of the smallest vertex. We compare them to the right of this
03850   // point to determine whether prev1 is inside the hole to be created or not.
03851   const X_monotone_curve_2  *p_cv_curr;
03852   const X_monotone_curve_2  *p_cv_next;
03853 
03854   if (he_left_low != NULL)
03855   {
03856     p_cv_curr = &(he_left_low->curve());
03857 
03858     // Take special care if the next curve should really be the new curve.
03859     if (he_left_low->next() != he_last)
03860       p_cv_next = &(he_left_low->next()->curve());
03861     else
03862       p_cv_next = &cv;
03863   }
03864   else
03865   {
03866     // In this case, the leftmost edge should be the one associated with the
03867     // new curve (which has not been created yet).
03868     p_cv_curr = &cv;
03869     p_cv_next = &(prev2->next()->curve());
03870   }
03871 
03872   // Check if the vertex lies on the line of discontinuity in y, in which case
03873   // special care must be taken.
03874   if ((v_min->parameter_space_in_y() != ARR_INTERIOR) &&
03875       (m_boundary_types[v_min->parameter_space_in_y()] == ARR_IDENTIFICATION))
03876   {
03877     // Both current and next curves are incident to the line of discontinuity.
03878     // As v_min is the leftmost vertex, we now that their left ends must have
03879     // a boundary condition of type discontinuity in y.
03880     Arr_parameter_space  ps_y_curr =
03881       m_geom_traits->parameter_space_in_y_2_object()(*p_cv_curr, ARR_MIN_END);
03882     Arr_parameter_space  ps_y_next =
03883       m_geom_traits->parameter_space_in_y_2_object()(*p_cv_next, ARR_MIN_END);
03884 
03885     // Check if the curves lie on opposite sides of the line of discontinuity.
03886     if ((ps_y_curr == ARR_BOTTOM_BOUNDARY) && (ps_y_next == ARR_TOP_BOUNDARY))
03887     {
03888       // In this case the current curve is "above" the next one to the right
03889       // of v_min, in a cyclic order around the line of discontinuity.
03890       return (true);
03891     }
03892     else if ((ps_y_curr == ARR_TOP_BOUNDARY) &&
03893              (ps_y_next == ARR_BOTTOM_BOUNDARY))
03894     {
03895       // In this case the current curve is "below" the next one to the right
03896       // of v_min, in a cyclic order around the line of discontinuity.
03897       return (false);
03898     }
03899 
03900     // If both curves are on the same side of the line of discontinuity, we
03901     // continue to compare them to the right of v_min.
03902     CGAL_assertion (((ps_y_curr == ARR_BOTTOM_BOUNDARY) &&
03903                      (ps_y_next == ARR_BOTTOM_BOUNDARY)) ||
03904                     ((ps_y_curr == ARR_TOP_BOUNDARY) &&
03905                      (ps_y_next == ARR_TOP_BOUNDARY)));
03906   }
03907 
03908   // Check if the leftmost vertex is asingularity point in y, in which case
03909   // special care must be taken.
03910   if ((v_min->parameter_space_in_y() != ARR_INTERIOR) &&
03911       (m_boundary_types[v_min->parameter_space_in_y()] == ARR_CONTRACTION))
03912   {
03913     // Get the curve-ends for cv_curr and cv_next that conincide with the
03914     // singularity point.
03915     Arr_curve_end      ind_curr;
03916     Arr_curve_end      ind_next;
03917 
03918     if (he_left_low != NULL)
03919     {
03920       // The singularity point is he_left_low's target and cv_curr is its
03921       // associated curve.
03922       ind_curr = (he_left_low->direction() == ARR_LEFT_TO_RIGHT) ?
03923         ARR_MAX_END : ARR_MIN_END;
03924 
03925       if (he_left_low->next() != he_last)
03926       {
03927         // The singularity point is he_left_low->next()'s source and cv_next
03928         // is its associated curve.
03929         ind_next = (he_left_low->next()->direction() == ARR_LEFT_TO_RIGHT) ?
03930           ARR_MIN_END : ARR_MAX_END;
03931       }
03932       else {
03933         // In this case cv_next equals cv.
03934         ind_next =
03935           (m_topol_traits.are_equal
03936            (v_min, cv, ARR_MIN_END,
03937             m_geom_traits->parameter_space_in_x_2_object() (cv, ARR_MIN_END),
03938             m_geom_traits->parameter_space_in_y_2_object() (cv, ARR_MIN_END))) ?
03939           ARR_MIN_END : ARR_MAX_END;
03940       }
03941     }
03942     else
03943     {
03944       // In this case cv_curr equals cv.
03945       ind_curr =
03946         (m_topol_traits.are_equal
03947          (v_min, cv, ARR_MIN_END,
03948           m_geom_traits->parameter_space_in_x_2_object() (cv, ARR_MIN_END),
03949           m_geom_traits->parameter_space_in_y_2_object() (cv, ARR_MIN_END))) ?
03950         ARR_MIN_END : ARR_MAX_END;
03951 
03952       // The singularity point is prev2->next()'s source and cv_next
03953       // is its associated curve.
03954       ind_next = (prev2->next()->direction() == ARR_LEFT_TO_RIGHT) ?
03955         ARR_MIN_END : ARR_MAX_END;
03956     }
03957 
03958     // Compare the horizontal position of the two curve-ends at the point
03959     // of singularity.
03960     const Comparison_result   x_res =
03961       m_geom_traits->compare_x_near_boundary_2_object() (*p_cv_curr, ind_curr,
03962                                                        *p_cv_next, ind_next);
03963 
03964     CGAL_assertion (x_res != EQUAL);
03965 
03966     return (((v_min->parameter_space_in_y() == ARR_BOTTOM_BOUNDARY) &&
03967              (x_res == SMALLER)) ||
03968             ((v_min->parameter_space_in_y() == ARR_TOP_BOUNDARY) &&
03969              (x_res == LARGER)));
03970   }
03971 
03972   return (m_geom_traits->compare_y_at_x_right_2_object()
03973           (*p_cv_curr, *p_cv_next, v_min->point()) == LARGER);
03974 }
03975 
03976 //-----------------------------------------------------------------------------
03977 // Remove a pair of twin halfedges from the arrangement.
03978 // In case the removal causes the creation of a new hole, the given halfedge
03979 // should point at this hole.
03980 //
03981 template<class GeomTraits, class TopTraits>
03982 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::DFace*
03983 Arrangement_on_surface_2<GeomTraits, TopTraits>::
03984 _remove_edge (DHalfedge *e, bool remove_source, bool remove_target)
03985 {
03986   // Get the pair of twin edges to be removed, the connected components they
03987   // belong to and their incident faces.
03988   DHalfedge   *he1 = e;
03989   DHalfedge   *he2 = e->opposite();
03990   DInner_ccb  *ic1 = (he1->is_on_inner_ccb()) ? he1->inner_ccb() : NULL;
03991   DOuter_ccb  *oc1 = (ic1 == NULL) ? he1->outer_ccb() : NULL;
03992   DFace       *f1 = (oc1 != NULL) ? oc1->face() : ic1->face();
03993   DInner_ccb  *ic2 = (he2->is_on_inner_ccb()) ? he2->inner_ccb() : NULL;
03994   DOuter_ccb  *oc2 = (ic2 == NULL) ? he2->outer_ccb() : NULL;
03995   DFace       *f2 = (oc2 != NULL) ? oc2->face() : ic2->face();
03996   DHalfedge   *prev1 = NULL;
03997   DHalfedge   *prev2 = NULL;
03998 
03999   // Notify the observers that we are about to remove an edge.
04000   Halfedge_handle  hh (e);
04001 
04002   _notify_before_remove_edge (hh);
04003 
04004   // Check if the two incident faces are equal, in which case no face will be
04005   // merged and deleted (and a hole may be created).
04006   if (f1 == f2)
04007   {
04008     // Check if the two halfedges are successors along the face boundary.
04009     if (he1->next() == he2 && he2->next() == he1)
04010     {
04011       CGAL_assertion (ic1 != NULL && ic1 == ic2);
04012 
04013       // The two halfedges form a "singleton" hole inside the incident face
04014       // (case 1 of the removal procedure, as detailed in the design document),
04015       // so we simply have to remove it.
04016       // First notify the observers that we are about to remove this hole
04017       // (inner CCB).
04018       Face_handle               fh (f1);
04019 
04020       _notify_before_remove_inner_ccb (fh, (Halfedge_handle(he1))->ccb());
04021 
04022       // Erase the inner CCB from the incident face and delete the
04023       // corresponding component.      
04024       f1->erase_inner_ccb (ic1);
04025 
04026       _dcel().delete_inner_ccb (ic1);
04027 
04028       // Notify the observers that the inner CCB has been removed.
04029       _notify_after_remove_inner_ccb (fh);
04030 
04031       // Remove the end-vertices, if necessary.
04032       if (remove_target)
04033       {
04034         if (he1->vertex()->parameter_space_in_x() != ARR_INTERIOR || 
04035             he1->vertex()->parameter_space_in_y() != ARR_INTERIOR)
04036         {
04037           he1->vertex()->set_halfedge(NULL);    // disconnect the end vertex
04038           _remove_vertex_if_redundant (he1->vertex(), f1);
04039         }
04040         else
04041         {
04042           // Delete the he1's target vertex and its associated point.
04043           _notify_before_remove_vertex (Vertex_handle (he1->vertex()));
04044           
04045           _delete_point (he1->vertex()->point());
04046           _dcel().delete_vertex (he1->vertex());
04047 
04048           _notify_after_remove_vertex ();
04049         }
04050       }
04051       else
04052       {
04053         // The remaining target vertex now becomes an isolated vertex inside
04054         // the containing face:
04055         _insert_isolated_vertex (f1, he1->vertex());
04056       }
04057 
04058       if (remove_source)
04059       {
04060         if (he2->vertex()->parameter_space_in_x() != ARR_INTERIOR || 
04061             he2->vertex()->parameter_space_in_y() != ARR_INTERIOR)
04062         {
04063           he2->vertex()->set_halfedge(NULL);    // disconnect the end vertex
04064           _remove_vertex_if_redundant (he2->vertex(), f1);
04065         }
04066         else
04067         {
04068           // Delete the he1's source vertex and its associated point.
04069           _notify_before_remove_vertex (Vertex_handle (he2->vertex()));
04070           
04071           _delete_point (he2->vertex()->point());
04072           _dcel().delete_vertex (he2->vertex());
04073           
04074           _notify_after_remove_vertex ();
04075         }
04076       }
04077       else
04078       {
04079         // The remaining source vertex now becomes an isolated vertex inside
04080         // the containing face:
04081         _insert_isolated_vertex (f1, he2->vertex());
04082       }
04083 
04084       // Delete the curve associated with the edge to be removed.
04085       _delete_curve (he1->curve());
04086       _dcel().delete_edge (he1);
04087 
04088       // Notify the observers that an edge has been deleted.
04089       _notify_after_remove_edge();
04090 
04091       // Return the face that used to contain the hole.
04092       return (f1);
04093     }
04094     else if (he1->next() == he2 || he2->next() == he1)
04095     {
04096       CGAL_assertion (oc1 == oc2 && ic1 == ic2);
04097 
04098       // In this case the two halfedges form an "antenna" (case 2).
04099       // Make he1 point at the tip of this "antenna" (swap the pointer if
04100       // necessary).
04101       bool     remove_tip_vertex = remove_target;
04102  
04103       if (he2->next() == he1)
04104       {
04105         he1 = he2;
04106         he2 = he1->opposite();
04107         remove_tip_vertex = remove_source;
04108       }
04109 
04110       // Remove the two halfedges from the boundary chain by connecting
04111       // he1's predecessor with he2's successor.
04112       prev1 = he1->prev();
04113       prev1->set_next (he2->next());
04114 
04115       // In case the halfedges to be deleted are represantatives of their
04116       // CCB (note that noth should belong to the same CCB, be it an outer
04117       // CCB or an inner one), make prev1 the components representative.
04118       if (oc1 != NULL && (oc1->halfedge() == he1 ||
04119                           oc1->halfedge() == he2))
04120       {
04121         oc1->set_halfedge (prev1);
04122       }
04123       else if (ic1 != NULL && (ic1->halfedge() == he1 ||
04124                                ic1->halfedge() == he2))
04125       {
04126         ic1->set_halfedge (prev1);
04127       }
04128 
04129       // In case he2 is the representative halfedge of its target vertex,
04130       // replace it by prev1 (which also points at this vertex).
04131       if (he2->vertex()->halfedge() == he2)
04132         he2->vertex()->set_halfedge (prev1);
04133 
04134       // Try to temove the base vertex, in case it has boundary conditions.
04135       if (he2->vertex()->parameter_space_in_x() != ARR_INTERIOR || 
04136           he2->vertex()->parameter_space_in_y() != ARR_INTERIOR)
04137       {
04138         _remove_vertex_if_redundant (he2->vertex(), f1);
04139       }
04140 
04141       // Remove the redundant tip vertex, if necessary.
04142       if (remove_tip_vertex)
04143       {
04144         if (he1->vertex()->parameter_space_in_x() != ARR_INTERIOR || 
04145             he1->vertex()->parameter_space_in_y() != ARR_INTERIOR)
04146         {
04147           he1->vertex()->set_halfedge(NULL);    // disconnect the end vertex
04148           _remove_vertex_if_redundant (he1->vertex(), f1);
04149         }
04150         else
04151         {
04152           // Delete the vertex that forms the tip of the "antenna".
04153           _notify_before_remove_vertex (Vertex_handle (he1->vertex()));
04154           
04155           _delete_point (he1->vertex()->point());
04156           _dcel().delete_vertex (he1->vertex());
04157 
04158           _notify_after_remove_vertex();
04159         }
04160       }
04161       else
04162       {
04163         // The remaining "antenna" tip now becomes an isolated vertex inside
04164         // the containing face:
04165         _insert_isolated_vertex (f1, he1->vertex());
04166       }
04167 
04168       // Delete the curve associated with the edge to be removed.
04169       _delete_curve (he1->curve());
04170       _dcel().delete_edge (he1);
04171 
04172       // Notify the observers that an edge has been deleted.
04173       _notify_after_remove_edge();
04174 
04175       // Return the incident face.
04176       return (f1);
04177     }
04178 
04179     // In this case the degree of both end-vertices is at least 2, so we
04180     // can use the two predecessor halfedges of he1 and he2.
04181     bool        add_inner_ccb = false;
04182 
04183     prev1 = he1->prev();
04184     prev2 = he2->prev();
04185 
04186     if (ic1 != NULL && ic1 == ic2)
04187     {
04188       // If both halfedges lie on the same inner component (hole) inside the
04189       // face (case 3.1), we have to split this component into two holes.
04190       //
04191       //    +-----------------------------+
04192       //    |           prev1             |
04193       //    |   +----+ /    +----+        |
04194       //    |   |    +......+    |        |
04195       //    |   +----+      +----+        |
04196       //    |                             |
04197       //    +-----------------------------+
04198       //
04199       // Notify the observers we are about to split an inner CCB.
04200       _notify_before_split_inner_ccb (Face_handle (f1),
04201                                       (Halfedge_handle 
04202                                        (*(ic1->iterator())))->ccb(),
04203                                       Halfedge_handle (he1));
04204 
04205       // We first make prev1 the new representative halfedge of the first
04206       // inner CCB.
04207       ic1->set_halfedge (prev1);
04208 
04209       // Create a new component that represents the new hole we split.
04210       DInner_ccb     *new_ic = _dcel().new_inner_ccb();
04211 
04212       f1->add_inner_ccb (new_ic, prev2);
04213       new_ic->set_face (f1);
04214 
04215       // Associate all halfedges along the hole boundary with the new inner
04216       // component.
04217       DHalfedge       *curr;
04218 
04219       for (curr = he1->next(); curr != he2; curr = curr->next())
04220         curr->set_inner_ccb (new_ic);
04221 
04222       // Notify the observers that the hole has been split.
04223       _notify_after_split_inner_ccb (Face_handle (f1),
04224                                      (Halfedge_handle (prev1))->ccb(),
04225                                      (Halfedge_handle (prev2))->ccb());
04226     }
04227     else if (oc1 != oc2)
04228     {
04229       // RWRW: NEW!
04230       CGAL_assertion (oc1 != NULL && oc2 != NULL);
04231 
04232       // In case both halfegdes he1 and he2 are incident to the same face
04233       // but lie on different outer CCBs of this face, removing this pair of
04234       // halfedge causes the two components two merge and to become an
04235       // inner CCB in the face.
04236       // We first remove the outer CCB oc1 from f, and inform the observers
04237       // on doing so.
04238       Face_handle               fh (f1);
04239 
04240       _notify_before_remove_outer_ccb (fh, (Halfedge_handle(he1))->ccb());
04241 
04242       f1->erase_outer_ccb (oc1);
04243       _dcel().delete_outer_ccb (oc1);
04244 
04245       _notify_after_remove_outer_ccb (fh);
04246 
04247       // We now remove the outer CCBs oc2 from f, and inform the observers
04248       // on doing so.
04249       _notify_before_remove_outer_ccb (fh, (Halfedge_handle(he2))->ccb());
04250 
04251       f2->erase_outer_ccb (oc2);
04252       _dcel().delete_outer_ccb (oc2);
04253 
04254       _notify_after_remove_outer_ccb (fh);
04255 
04256       // Mark that we should eventually add a new inner CCB inside the face.
04257       add_inner_ccb = true;
04258     }
04259     else
04260     {
04261       CGAL_assertion (oc1 != NULL && oc1 == oc2);
04262 
04263       // If both halfedges are incident to the same outer CCB of their
04264       // face (case 3.2), we have to distinguish two sub-cases:
04265       if (m_topol_traits.hole_creation_after_edge_removal (he1))
04266       {
04267         // We have to create a new hole in the interior of the incident face
04268         // (case 3.2.1):
04269         //
04270         //    +-----------------------------+
04271         //    | prev1                       |
04272         //    v         +----+              |
04273         //    +........>+    |              |
04274         //    |   he1   +----+              |
04275         //    |                             |
04276         //    +-----------------------------+
04277         //
04278         // Note that it is guaranteed that he1 points at this new hole, while
04279         // he2 points at the boundary of the face that contains this hole.
04280         // First notify the observers we are about to form a new inner
04281         // CCB inside f1.
04282         _notify_before_add_inner_ccb (Face_handle (f1),
04283                                       Halfedge_handle (he1->next()));
04284 
04285         // Create a new component that represents the new hole.
04286         DInner_ccb   *new_ic = _dcel().new_inner_ccb();
04287 
04288         f1->add_inner_ccb (new_ic, he1->next());
04289         new_ic->set_face (f1);
04290 
04291         // Associate all halfedges along the hole boundary with the new inner
04292         // component.
04293         DHalfedge       *curr;
04294 
04295         for (curr = he1->next(); curr != he2; curr = curr->next())
04296           curr->set_inner_ccb (new_ic);
04297 
04298         // As the outer CCB of f1 may be represented by any of the
04299         // halfedges in between he1 -> ... -> he2 (the halfedges in between
04300         // represent the outer boundary of the new hole that is formed),
04301         // We represent the outer boundary of f1 by prev1, which definately
04302         // stays on the outer boundary.
04303         oc1->set_halfedge (prev1);
04304 
04305         // Notify the observers that a new hole has been formed.
04306         Ccb_halfedge_circulator   hccb = (Halfedge_handle(he1->next()))->ccb();
04307 
04308         _notify_after_add_inner_ccb (hccb);
04309       }
04310       else
04311       {
04312         // We have to split the outer CCB into two outer components
04313         // (case 3.2.2), such that the number of outer CCBs of the face is
04314         // incremented.
04315         // First we notify the observers that we are about to split an outer
04316         // component.
04317         _notify_before_split_outer_ccb (Face_handle (f1),
04318                                         Halfedge_handle (he1)->ccb(),
04319                                         Halfedge_handle (he1));
04320 
04321         // Create a new outer component.
04322         DOuter_ccb   *new_oc = _dcel().new_outer_ccb();
04323 
04324         f1->add_outer_ccb (new_oc, he1->next());
04325         new_oc->set_face (f1);
04326 
04327         // Associate all halfedges from he1 until he2 with the new CCB.
04328         DHalfedge       *curr;
04329 
04330         for (curr = he1->next(); curr != he2; curr = curr->next())
04331           curr->set_outer_ccb (new_oc);
04332 
04333         // As the outer CCB of f1 may be represented by any of the
04334         // halfedges in between he1 -> ... -> he2 (the halfedges in between
04335         // are on the new outer CCB we have just created), we represent the
04336         // former outer CCB by prev1, which definately stays on it.
04337         oc1->set_halfedge (prev1);
04338 
04339         // Notify the observers that a new outer CCB has been formed.
04340         Ccb_halfedge_circulator   hccb = (Halfedge_handle(he1->next()))->ccb();
04341 
04342         _notify_after_split_outer_ccb (Face_handle (f1),
04343                                        Halfedge_handle (he1->next())->ccb(),
04344                                        Halfedge_handle (prev1)->ccb());
04345       }
04346     }
04347 
04348     // Disconnect the two halfedges we are about to delete from the edge list.
04349     prev1->set_next (he2->next());
04350     prev2->set_next (he1->next());
04351 
04352     // If one of these edges is an incident halfedge of its target vertex,
04353     // replace it by the appropriate predecessor.
04354     if (he1->vertex()->halfedge() == he1)
04355       he1->vertex()->set_halfedge (prev2);
04356 
04357     if (he2->vertex()->halfedge() == he2)
04358       he2->vertex()->set_halfedge (prev1);
04359 
04360     // Remove the end vertices, in case they become redundant.
04361     if (he1->vertex()->parameter_space_in_x() != ARR_INTERIOR || 
04362         he1->vertex()->parameter_space_in_y() != ARR_INTERIOR)
04363     {
04364       _remove_vertex_if_redundant (he1->vertex(), f1);
04365     }
04366 
04367     if (he2->vertex()->parameter_space_in_x() != ARR_INTERIOR || 
04368         he2->vertex()->parameter_space_in_y() != ARR_INTERIOR)
04369     {
04370       _remove_vertex_if_redundant (he2->vertex(), f1);
04371     }
04372 
04373     // Delete the curve associated with the edge to be removed.
04374     _delete_curve (he1->curve());
04375 
04376     // Delete the pair of halfedges.
04377     _dcel().delete_edge (he1);
04378 
04379     // RWRW: NEW!
04380     // In case we have to create a new inner CCB inside the face (new removal
04381     // case), do it now.
04382     if (add_inner_ccb)
04383     {
04384       // Notify the observers that we are about to create a new inner CCB
04385       // inside the merged face.
04386       Halfedge_handle   hh (prev1);
04387 
04388       _notify_before_add_inner_ccb (Face_handle (f1), hh);
04389 
04390       // Initiate a new inner CCB inside the given face.
04391       DInner_ccb   *new_ic = _dcel().new_inner_ccb();
04392 
04393       f1->add_inner_ccb (new_ic, prev1);
04394       new_ic->set_face (f1);
04395 
04396       // Set the innser CCB of the halfedges along the component boundary.
04397       DHalfedge   *curr = prev1;
04398 
04399       do
04400       {
04401         curr->set_inner_ccb (new_ic);
04402         curr = curr->next();
04403       } while (curr != prev1);
04404 
04405       // Notify the observers that we have formed a new inner CCB.
04406       _notify_after_add_inner_ccb (hh->ccb());
04407     }
04408 
04409     // Notify the observers that an edge has been deleted.
04410     _notify_after_remove_edge();
04411 
04412     // Return the incident face.
04413     return (f1);
04414   }
04415 
04416   // The two incident faces are not the same - in this case, the edge we are
04417   // about to delete separates these two faces. We therefore have to delete
04418   // one of these faces and merge it with the other face.
04419   // First notify the observers we are about to merge the two faces.
04420   _notify_before_merge_face (Face_handle (f1), Face_handle (f2),
04421                              Halfedge_handle (he1));
04422 
04423   // We begin by checking whether one of the face is a hole inside the other
04424   // face.
04425   DHalfedge   *curr;
04426 
04427   prev1 = he1->prev();
04428   prev2 = he2->prev();
04429 
04430   CGAL_assertion (ic1 == NULL || ic2 == NULL);
04431 
04432   if (ic1 == NULL && ic2 == NULL)
04433   {
04434     bool          add_inner_ccb = false;
04435 
04436     // Both halfedges lie on the outer boundary of their incident faces
04437     // (case 3.4). We have to distinguish two possible sub-cases.
04438     if (m_topol_traits.hole_creation_after_edge_removal (he1))
04439     {
04440       // We have to remove the outer CCBs of f1 and f2 that he1 and he2 lie
04441       // on, and create a new hole in the merged face (case 3.4.1).
04442       // We first remove the outer CCB oc1 from f1, and inform the observers
04443       // on doing so.
04444       _notify_before_remove_outer_ccb (Face_handle (f1),
04445                                        (Halfedge_handle(he1))->ccb());
04446 
04447       f1->erase_outer_ccb (oc1);
04448       _dcel().delete_outer_ccb (oc1);
04449 
04450       _notify_after_remove_outer_ccb (Face_handle (f1));
04451 
04452       // We now remove the outer CCBs oc2 from f2, and inform the observers
04453       // on doing so.
04454       _notify_before_remove_outer_ccb (Face_handle (f2),
04455                                        (Halfedge_handle(he2))->ccb());
04456 
04457       f2->erase_outer_ccb (oc2);
04458       _dcel().delete_outer_ccb (oc2);
04459 
04460       _notify_after_remove_outer_ccb (Face_handle (f2));
04461 
04462       // Mark that we should eventually add a new inner CCB in the merged face.
04463       add_inner_ccb = true;
04464     }
04465     else
04466     {
04467       // f1 and f2 are two adjacent faces (case 3.4.2), so we simply merge
04468       // them.
04469       // We first set the connected component of f2's outer-boundary halfedges
04470       // to be the same as f1's outer component.
04471       for (curr = he2->next(); curr != he2; curr = curr->next())
04472         curr->set_outer_ccb (oc1);
04473     }
04474 
04475     // Move the holes inside f2 to f1.
04476     DInner_ccb_iter    ic_it = f2->inner_ccbs_begin();
04477     DInner_ccb_iter    ic_to_move;
04478     
04479     while (ic_it != f2->inner_ccbs_end())
04480     {
04481       // We increment the holes itrator before moving the hole, because
04482       // this operation invalidates the iterator.
04483       ic_to_move  = ic_it;
04484       ++ic_it;
04485       
04486       _move_inner_ccb (f2, f1, *ic_to_move);
04487     }
04488 
04489     // In case he1, which is about to be deleted, is a representative
04490     // halfedge of outer component of f1, we replace it by its predecessor.
04491     if (oc1->halfedge() == he1)
04492       oc1->set_halfedge (prev1);
04493 
04494     // Move the isolated vertices inside f2 to f1.
04495     DIso_vertex_iter    iv_it = f2->isolated_vertices_begin();
04496     DIso_vertex_iter    iv_to_move;
04497     
04498     while (iv_it != f2->isolated_vertices_end())
04499     {
04500       // We increment the isolated vertices itrator before moving the vertex,
04501       // because this operation invalidates the iterator.
04502       iv_to_move  = iv_it;
04503       ++iv_it;
04504 
04505       _move_isolated_vertex (f2, f1, &(*iv_to_move)); 
04506     }
04507 
04508     // If he1 or he2 are the incident halfedges to their target vertices,
04509     // we replace them by the appropriate predecessors.
04510     if (he1->vertex()->halfedge() == he1)
04511       he1->vertex()->set_halfedge (prev2);
04512       
04513     if (he2->vertex()->halfedge() == he2)
04514       he2->vertex()->set_halfedge (prev1);
04515     
04516     // Disconnect the two halfedges we are about to delete from the edge
04517     // list.
04518     prev1->set_next (he2->next());
04519     prev2->set_next (he1->next());
04520       
04521       // Delete the curve associated with the edge to be removed.
04522     _delete_curve (he1->curve());
04523 
04524     // If the face f2 we have just merged with f1 is unbounded, then the
04525     // merged face is also unbounded.
04526     if (f2->is_unbounded())
04527       f1->set_unbounded(true);
04528 
04529     // Delete the face f2.
04530     _dcel().delete_face (f2);
04531       
04532     // Notify the observers that the faces have been merged.
04533     _notify_after_merge_face (Face_handle (f1));
04534 
04535     // Remove the end vertices, in case they become redundant.
04536     if (he1->vertex()->parameter_space_in_x() != ARR_INTERIOR || 
04537         he1->vertex()->parameter_space_in_y() != ARR_INTERIOR)
04538     {
04539       _remove_vertex_if_redundant (he1->vertex(), f1);
04540     }
04541     
04542     if (he2->vertex()->parameter_space_in_x() != ARR_INTERIOR || 
04543         he2->vertex()->parameter_space_in_y() != ARR_INTERIOR)
04544     {
04545       _remove_vertex_if_redundant (he2->vertex(), f1);
04546     }
04547     
04548     // Delete the pair of halfedges.
04549     _dcel().delete_edge (he1);
04550 
04551     // In case we have to create a new inner CCB inside the merged face
04552     // (case 3.4.1), do it now.
04553     if (add_inner_ccb)
04554     {
04555       // Notify the observers that we are about to create a new inner CCB
04556       // inside the merged face.
04557       Halfedge_handle   hh (prev1);
04558 
04559       _notify_before_add_inner_ccb (Face_handle (f1), hh);
04560 
04561       // Initiate a new inner CCB inside the given face.
04562       DInner_ccb   *new_ic = _dcel().new_inner_ccb();
04563 
04564       f1->add_inner_ccb (new_ic, prev1);
04565       new_ic->set_face (f1);
04566 
04567       // Set the innser CCB of the halfedges along the component boundary.
04568       curr = prev1;
04569       do
04570       {
04571         curr->set_inner_ccb (new_ic);
04572         curr = curr->next();
04573       } while (curr != prev1);
04574 
04575       // Notify the observers that we have formed a new inner CCB.
04576       _notify_after_add_inner_ccb (hh->ccb());
04577     }
04578 
04579     // Notify the observers that an edge has been deleted.
04580     _notify_after_remove_edge();
04581       
04582     // Return the merged face.
04583     return (f1); 
04584   }
04585 
04586   // In this case we merge a face with another face that now forms a hole
04587   // inside it (case 3.3). We first make sure that f1 contains the hole f2, so
04588   // we can merge f2 with it (we swap roles between the halfedges if
04589   // necessary).
04590   if (ic2 != NULL)
04591   { 
04592     he1 = he2;
04593     he2 = he1->opposite();
04594 
04595     ic1 = ic2;
04596     ic2 = NULL;
04597 
04598     oc2 = oc1;
04599     oc1 = NULL;
04600 
04601     DFace   *tf = f1;
04602     f1 = f2;
04603     f2 = tf;
04604     
04605     prev1 = he1->prev();
04606     prev2 = he2->prev();
04607   }
04608 
04609   // By removing the edge we open a closed face f2 contained in f1. By doing
04610   // this, the outer boundary of f2 unites with the hole boundary that ic1
04611   // represents. We therefore have to set the component of all halfedges
04612   // along the boundary of f2 to be ic1.
04613   for (curr = he2->next(); curr != he2; curr = curr->next())
04614     curr->set_inner_ccb (ic1);
04615 
04616   // Move the inner CCBs inside f2 to f1.
04617   DInner_ccb_iter    ic_it = f2->inner_ccbs_begin();
04618   DInner_ccb_iter    ic_to_move;
04619 
04620   while (ic_it != f2->inner_ccbs_end())
04621   {
04622     // We increment the holes itrator before moving the hole, because
04623     // this operation invalidates the iterator.
04624     ic_to_move  = ic_it;
04625     ++ic_it;
04626 
04627     _move_inner_ccb (f2, f1, *ic_to_move); 
04628   }
04629 
04630   // Move the isolated vertices inside f2 to f1.
04631   DIso_vertex_iter    iv_it = f2->isolated_vertices_begin();
04632   DIso_vertex_iter    iv_to_move;
04633 
04634   while (iv_it != f2->isolated_vertices_end())
04635   {
04636     // We increment the isolated vertices itrator before moving the vertex,
04637     // because this operation invalidates the iterator.
04638     iv_to_move  = iv_it;
04639     ++iv_it;
04640 
04641     _move_isolated_vertex (f2, f1, &(*iv_to_move)); 
04642   }
04643         
04644   // Notice that f2 will be merged with f1, but its boundary will still be
04645   // a hole inside this face. In case he1 is a represantative of this hole,
04646   // replace it by its predecessor.
04647   if (ic1->halfedge() == he1)
04648     ic1->set_halfedge (prev1);
04649   
04650   // If he1 or he2 are the incident halfedges to their target vertices,
04651   // we replace them by the appropriate predecessors.
04652   if (he1->vertex()->halfedge() == he1)
04653     he1->vertex()->set_halfedge (prev2);
04654         
04655   if (he2->vertex()->halfedge() == he2)
04656     he2->vertex()->set_halfedge (prev1);
04657       
04658   // Disconnect the two halfedges we are about to delete from the edge
04659   // list.
04660   prev1->set_next (he2->next());
04661   prev2->set_next (he1->next());
04662 
04663   // Delete the curve associated with the edge to be removed.
04664   _delete_curve (he1->curve());
04665 
04666   // If the face f2 we have just merged with f1 is unbounded, then the merged
04667   // face is also unbounded.
04668   if (f2->is_unbounded())
04669     f1->set_unbounded(true);
04670 
04671   // Delete the face f2.
04672   _dcel().delete_face (f2);
04673       
04674   // Notify the observers that the faces have been merged.
04675   _notify_after_merge_face (Face_handle (f1));
04676 
04677   // Remove the end vertices, in case they become redundant.
04678   if (he1->vertex()->parameter_space_in_x() != ARR_INTERIOR || 
04679       he1->vertex()->parameter_space_in_y() != ARR_INTERIOR)
04680   {
04681     _remove_vertex_if_redundant (he1->vertex(), f1);
04682   }
04683   
04684   if (he2->vertex()->parameter_space_in_x() != ARR_INTERIOR || 
04685       he2->vertex()->parameter_space_in_y() != ARR_INTERIOR)
04686   {
04687     _remove_vertex_if_redundant (he2->vertex(), f1);
04688   }
04689 
04690   // Delete the pair of halfedges.
04691   _dcel().delete_edge (he1);
04692 
04693   // Notify the observers that an edge has been deleted.
04694   _notify_after_remove_edge();
04695 
04696   // Return the merged face.
04697   return (f1);
04698 }
04699 
04700 //-----------------------------------------------------------------------------
04701 // Remove a vertex in case it becomes redundant after the deletion of an
04702 // incident edge.
04703 //
04704 template<class GeomTraits, class TopTraits>
04705 void
04706 Arrangement_on_surface_2<GeomTraits, TopTraits>::
04707 _remove_vertex_if_redundant (DVertex *v, DFace *f)
04708 {
04709   CGAL_precondition (v->parameter_space_in_x() != ARR_INTERIOR || 
04710                      v->parameter_space_in_y() != ARR_INTERIOR);
04711 
04712   // In case the vertex has no incident halfedges, remove it if it is
04713   // redundant. Otherwise, make it an isolated vertex.
04714   if (v->halfedge() == NULL)
04715   {
04716     if (m_topol_traits.is_redundant (v))
04717     {
04718       // Remove the vertex and notify the observers on doing so.
04719       _notify_before_remove_vertex (Vertex_handle (v));
04720 
04721       m_topol_traits.erase_redundant_vertex (v);
04722 
04723       // Note the topology traits do not free the vertex - we now do it.
04724       if (! v->has_null_point())
04725         _delete_point (v->point());
04726       _dcel().delete_vertex (v);
04727 
04728       _notify_after_remove_vertex();
04729     }
04730     else
04731     {
04732       // Keep the vertex as an isolated one.
04733       _insert_isolated_vertex (f, v);
04734     }
04735 
04736     return;
04737   }
04738 
04739   // Get the first two incident halfedges of v.
04740   DHalfedge  *he1 = v->halfedge();
04741   DHalfedge  *he2 = he1->next()->opposite();
04742   
04743   if (he2->next()->opposite() != he1)
04744   {
04745     // In this case there are more than two incident edges, so v obviously
04746     // cannot be removed.
04747     return;
04748   }
04749 
04750   if (! he1->has_null_curve() || ! he2->has_null_curve())
04751   {
04752     // We can only merge fictitious halfedges.
04753     return;
04754   }
04755 
04756   // Now check if the vertex is redundant. If it is, remove it by merging
04757   // its two incident fictitious halfedges.
04758   if (m_topol_traits.is_redundant (v))
04759   {
04760     // Use the topology traits to merge the two fictitious halfedges.
04761     _notify_before_merge_fictitious_edge (Halfedge_handle (he1),
04762                                           Halfedge_handle (he2));
04763 
04764     he1 = m_topol_traits.erase_redundant_vertex (v);
04765 
04766     _notify_after_merge_fictitious_edge (Halfedge_handle (he1));
04767 
04768     // Note the topology traits do not free the vertex - we now do it.
04769     _notify_before_remove_vertex (Vertex_handle (v));
04770     
04771     if (! v->has_null_point())
04772       _delete_point (v->point());
04773     _dcel().delete_vertex (v);
04774 
04775     _notify_after_remove_vertex();
04776   }
04777 
04778   return;
04779 }
04780 
04781 //-----------------------------------------------------------------------------
04782 // Remove an isolated vertex from the interior of a given face (but not from
04783 // the DCEL).
04784 //
04785 template<class GeomTraits, class TopTraits>
04786 void Arrangement_on_surface_2<GeomTraits, TopTraits>::
04787 _remove_isolated_vertex (DVertex* v)
04788 {
04789   // Remove the isolated vertex from the face and delete its record.
04790   DIso_vertex  *iv = v->isolated_vertex();
04791   DFace        *f = iv->face();
04792 
04793   f->erase_isolated_vertex (iv);
04794   _dcel().delete_isolated_vertex (iv);
04795   
04796   return;
04797 }
04798 
04799 //---------------------------------------------------------------------------
04800 // Check whether the arrangement is valid. In particular, check the
04801 // validity of each vertex, halfedge, and face.
04802 //
04803 template<class GeomTraits, class TopTraits>
04804 bool Arrangement_on_surface_2<GeomTraits, TopTraits>::is_valid() const
04805 {
04806   Vertex_const_iterator    vit;
04807   bool                     is_vertex_valid;
04808 
04809   for (vit = vertices_begin(); vit != vertices_end(); ++vit)
04810   {
04811     is_vertex_valid = _is_valid (vit);
04812     if (!is_vertex_valid) 
04813     {
04814       CGAL_warning_msg (is_vertex_valid, "Invalid vertex.");
04815       return (false);
04816     }
04817   }
04818     
04819   Halfedge_const_iterator  heit;
04820   bool                     is_halfedge_valid;
04821 
04822   for (heit = halfedges_begin(); heit != halfedges_end(); ++heit) 
04823   {
04824     is_halfedge_valid = _is_valid (heit);
04825     if (! is_halfedge_valid) 
04826     {
04827       CGAL_warning_msg (is_halfedge_valid, "Invalid halfedge.");
04828       return (false);
04829     }
04830   }
04831     
04832   Face_const_iterator     fit;
04833   bool                    is_face_valid;
04834 
04835   for (fit = faces_begin(); fit != faces_end(); ++fit) 
04836   {
04837     is_face_valid = _is_valid (fit);
04838     if (! is_face_valid)
04839     {
04840       CGAL_warning_msg (is_face_valid, "Invalid face.");
04841       return (false);
04842     }
04843   }
04844 
04845   bool  are_vertices_unique = _are_vertices_unique();
04846   if (! are_vertices_unique)
04847   {
04848     CGAL_warning_msg (are_vertices_unique,
04849                       "Found two vertices with the same geometric point.");
04850     return (false);
04851   }
04852 
04853   // If we reached here, the arrangement is valid.
04854   return (true);
04855 }
04856 
04857 //---------------------------------------------------------------------------
04858 // Check the validity of a vertex.
04859 //
04860 template<class GeomTraits, class TopTraits>
04861 bool Arrangement_on_surface_2<GeomTraits, TopTraits>::
04862 _is_valid (Vertex_const_handle v) const
04863 {    
04864   // Do not check isolated vertices, as they have no incident halfedges.
04865   if (v->is_isolated())
04866     return (true);
04867 
04868   // Make sure that the vertex is the target of all its incident halfedges.
04869   Halfedge_around_vertex_const_circulator circ = v->incident_halfedges();
04870   Halfedge_around_vertex_const_circulator start = circ;
04871 
04872   do
04873   {
04874     if (circ->target() != v)
04875       return (false);
04876     
04877     ++circ;
04878   } while (circ != start);
04879 
04880   // In case of a non-boundary vertex, make sure the curves are correctly
04881   // ordered around this vertex.
04882   if (v->parameter_space_in_x() ==
04883       ARR_INTERIOR && v->parameter_space_in_y() == ARR_INTERIOR)
04884   {
04885     if (! _are_curves_ordered_cw_around_vertrex (v))
04886       return (false);
04887   }
04888 
04889   return (true);
04890 }
04891 
04892 //---------------------------------------------------------------------------
04893 // Check the validity of a halfedge.
04894 //
04895 template<class GeomTraits, class TopTraits>
04896 bool Arrangement_on_surface_2<GeomTraits, TopTraits>::
04897 _is_valid (Halfedge_const_handle he) const
04898 {
04899   // Check relations with the previous and the next halfedges.
04900   if (he->prev()->target() != he->source())
04901     return (false);
04902 
04903   if (he->target() != he->next()->source())
04904     return (false);
04905 
04906   // Check relations with the twin.
04907   if (he != he->twin()->twin())
04908     return (false);
04909   
04910   if (he->source() != he->twin()->target() || 
04911       he->target() != he->twin()->source())
04912     return (false);
04913 
04914   if (he->direction() == he->twin()->direction())
04915     return (false);
04916 
04917   // Stop here in case of a fictitious edge.
04918   if (he->is_fictitious())
04919     return (true);
04920 
04921   // Check that the end points of the curve associated with the halfedge
04922   // really equal the source and target vertices of this halfedge.
04923   const X_monotone_curve_2&  cv = he->curve();
04924   const DVertex             *source = _vertex (he->source());
04925   const DVertex             *target = _vertex (he->target());
04926   Comparison_result          res;
04927 
04928   if (source->parameter_space_in_x() == ARR_INTERIOR &&
04929       source->parameter_space_in_y() == ARR_INTERIOR &&
04930       target->parameter_space_in_x() == ARR_INTERIOR &&
04931       target->parameter_space_in_y() == ARR_INTERIOR)
04932   {
04933     res = m_geom_traits->compare_xy_2_object()(source->point(), target->point());
04934   }
04935   else
04936   {
04937     res = (he->direction() == ARR_LEFT_TO_RIGHT) ? SMALLER : LARGER;
04938   }
04939 
04940   if (res == SMALLER)
04941   {
04942     if (he->direction() != ARR_LEFT_TO_RIGHT)
04943       return (false);
04944 
04945     return (_are_equal (_vertex (he->source()), cv, ARR_MIN_END) &&
04946             _are_equal (_vertex (he->target()), cv, ARR_MAX_END));
04947   }
04948   else if (res == LARGER)
04949   {
04950     if (he->direction() != ARR_RIGHT_TO_LEFT)
04951       return (false);
04952 
04953     return (_are_equal (_vertex (he->source()), cv, ARR_MAX_END) &&
04954             _are_equal (_vertex (he->target()), cv, ARR_MIN_END));
04955   }
04956 
04957   // In that case, the source and target of the halfedge are equal.
04958   return (false);
04959 }
04960 
04961 //---------------------------------------------------------------------------
04962 // Check the validity of a face.
04963 //
04964 template<class GeomTraits, class TopTraits>
04965 bool Arrangement_on_surface_2<GeomTraits, TopTraits>::
04966 _is_valid (Face_const_handle f) const
04967 {
04968   // Check if all outer components of the face refer to f.
04969   const DFace                   *p_f = _face (f);
04970   DOuter_ccb_const_iter          oc_it;
04971   const DHalfedge               *he;
04972   const DOuter_ccb              *oc;
04973 
04974   for (oc_it = p_f->outer_ccbs_begin();
04975        oc_it != p_f->outer_ccbs_end(); ++oc_it)
04976   {
04977     he = *oc_it;
04978     if (he->is_on_inner_ccb())
04979       return (false);
04980 
04981     oc = he->outer_ccb();
04982     if (oc->face() != p_f)
04983       return (false);
04984 
04985     if (! _is_outer_ccb_valid (oc, he))
04986       return (false);
04987   }
04988  
04989   // Check if all inner components of the face refer to f.
04990   DInner_ccb_const_iter          ic_it;
04991   const DInner_ccb              *ic;
04992 
04993   for (ic_it = p_f->inner_ccbs_begin();
04994        ic_it != p_f->inner_ccbs_end(); ++ic_it)
04995   {
04996     he = *ic_it;
04997     if (! he->is_on_inner_ccb())
04998       return (false);
04999 
05000     ic = he->inner_ccb();
05001     if (ic->face() != p_f)
05002       return (false);
05003 
05004     if (! _is_inner_ccb_valid (ic, he))
05005       return (false);
05006   }
05007  
05008   // Check if all isolated vertices inside the face refer to f.
05009   DIso_vertex_const_iter          iv_it;
05010   const DVertex                  *v;
05011   const DIso_vertex              *iv;
05012 
05013   for (iv_it = p_f->isolated_vertices_begin();
05014        iv_it != p_f->isolated_vertices_end(); ++iv_it)
05015   {
05016     v = &(*iv_it);
05017     if (! v->is_isolated())
05018       return (false);
05019 
05020     iv = v->isolated_vertex();
05021     if (iv->face() != p_f)
05022       return (false);
05023   }
05024 
05025   // If we reached here, the face is valid.
05026   return (true);
05027 }
05028 
05029 //---------------------------------------------------------------------------
05030 // Check the validity of an outer CCB.
05031 //
05032 template<class GeomTraits, class TopTraits>
05033 bool Arrangement_on_surface_2<GeomTraits, TopTraits>::
05034 _is_outer_ccb_valid (const DOuter_ccb *oc, const DHalfedge *first) const
05035 {
05036   // Make sure that all halfedges along the CCB refer to the same component.
05037   const DHalfedge   *curr = first;
05038   bool               found_rep = false;
05039 
05040   do
05041   {
05042     if (curr->is_on_inner_ccb())
05043       return (false);
05044 
05045     if (oc != curr->outer_ccb())
05046       return (false);
05047 
05048     if (! found_rep && oc->halfedge() == curr)
05049       found_rep = true;
05050 
05051     curr = curr->next();
05052   } while (curr != first);
05053   
05054   // Return if we found the CCB representative along the outer CCB.
05055   return (found_rep);
05056 }
05057 
05058 //---------------------------------------------------------------------------
05059 // Check the validity of an inner CCB.
05060 //
05061 template<class GeomTraits, class TopTraits>
05062 bool Arrangement_on_surface_2<GeomTraits, TopTraits>::
05063 _is_inner_ccb_valid (const DInner_ccb *ic, const DHalfedge *first) const
05064 {
05065   // Make sure that all halfedges along the CCB refer to the same component.
05066   const DHalfedge   *curr = first;
05067   bool               found_rep = false;
05068 
05069   do
05070   {
05071     if (! curr->is_on_inner_ccb())
05072       return (false);
05073 
05074     if (ic != curr->inner_ccb())
05075       return (false);
05076 
05077     if (! found_rep && ic->halfedge() == curr)
05078       found_rep = true;
05079 
05080     curr = curr->next();
05081   } while (curr != first);
05082   
05083   // Return if we found the CCB representative along the inner CCB.
05084   return (found_rep);
05085 }
05086 
05087 //---------------------------------------------------------------------------
05088 // Check that all vertices are unique (no two vertices with the same 
05089 // geometric point).
05090 //
05091 template<class GeomTraits, class TopTraits>
05092 bool Arrangement_on_surface_2<GeomTraits, TopTraits>::
05093 _are_vertices_unique() const
05094 {
05095   if (number_of_vertices() < 2)
05096     return (true);
05097 
05098   // Store all points associated with non-boundary vertices.
05099   std::vector<Point_2>  points_vec (number_of_vertices());
05100   Vertex_const_iterator vit;
05101   unsigned int          i = 0;
05102   
05103   for (vit = vertices_begin(); vit != vertices_end(); ++vit)
05104   {
05105     if (vit->parameter_space_in_x() == ARR_INTERIOR &&
05106         vit->parameter_space_in_y() == ARR_INTERIOR)
05107     { 
05108       points_vec[i] = vit->point();
05109       ++i;
05110     }
05111   }
05112   points_vec.resize (i);
05113 
05114   // Sort the vector of points and make sure no two adjacent points in the
05115   // sorted vector are equal.
05116   typedef typename Traits_adaptor_2::Compare_xy_2       Compare_xy_2;
05117   typedef typename Traits_adaptor_2::Equal_2            Equal_2;
05118   
05119   Equal_2       equal = m_geom_traits->equal_2_object();
05120   Compare_xy_2  compare_xy = m_geom_traits->compare_xy_2_object();
05121   Compare_to_less<Compare_xy_2>       cmp = compare_to_less (compare_xy);
05122   
05123   std::sort(points_vec.begin(), points_vec.end(), cmp);
05124   for (i = 1; i < points_vec.size(); ++i)
05125   {
05126     if (equal (points_vec[i-1], points_vec[i]))
05127       return (false);
05128   }
05129   
05130   return (true);
05131 }
05132 
05133 //---------------------------------------------------------------------------
05134 // Check that the curves around a given vertex are ordered clockwise.
05135 //
05136 template<class GeomTraits, class TopTraits>
05137 bool Arrangement_on_surface_2<GeomTraits, TopTraits>::
05138 _are_curves_ordered_cw_around_vertrex (Vertex_const_handle v) const
05139 {
05140   if(v->degree() < 3)
05141     return (true);
05142 
05143   typename Traits_adaptor_2::Is_between_cw_2  is_between_cw =
05144     m_geom_traits ->is_between_cw_2_object();
05145 
05146   Halfedge_around_vertex_const_circulator circ = v->incident_halfedges();
05147   Halfedge_around_vertex_const_circulator first = circ;
05148   Halfedge_around_vertex_const_circulator prev, next;
05149   bool                                    eq1, eq2;
05150 
05151   do
05152   {
05153     prev = circ; --prev;
05154     next = circ; ++next;
05155 
05156     if (!is_between_cw(circ->curve(), (circ->direction() == ARR_RIGHT_TO_LEFT),
05157                        prev->curve(), (prev->direction() == ARR_RIGHT_TO_LEFT),
05158                        next->curve(), (next->direction() == ARR_RIGHT_TO_LEFT),
05159                        v->point(), eq1, eq2))
05160       return (false);
05161 
05162     if (eq1 || eq2)
05163       return (false);
05164     
05165     ++circ;
05166   } while (circ != first);
05167    
05168   return (true);
05169 }
05170 
05171 CGAL_END_NAMESPACE
05172 
05173 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines